res_pjsip: Add option to force G.726 to be treated as AAL2 packed.
[asterisk/asterisk.git] / channels / chan_iax2.c
index be5b4c7..da6bec7 100644 (file)
@@ -58,7 +58,7 @@
 
 #include "asterisk.h"
 
-ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
+ASTERISK_REGISTER_FILE()
 
 #include <sys/mman.h>
 #include <dirent.h>
@@ -285,7 +285,7 @@ static int nochecksums = 0;
 /* Sample over last 100 units to determine historic jitter */
 #define GAMMA (0.01)
 
-static struct iax2_codec_pref prefs;
+static struct iax2_codec_pref prefs_global;
 
 static const char tdesc[] = "Inter Asterisk eXchange Driver (Ver 2)";
 
@@ -353,22 +353,22 @@ static int (*iax2_regfunk)(const char *username, int onoff) = NULL;
 #define IAX_CAPABILITY_FULLBANDWIDTH   0xFFFF
 /* T1, maybe ISDN */
 #define IAX_CAPABILITY_MEDBANDWIDTH (IAX_CAPABILITY_FULLBANDWIDTH & \
-                     ~ast_format_compatibility_format2bitfield(ast_format_slin) &      \
-                     ~ast_format_compatibility_format2bitfield(ast_format_slin16) &    \
-                     ~ast_format_compatibility_format2bitfield(ast_format_siren7) &       \
-                     ~ast_format_compatibility_format2bitfield(ast_format_siren14) &      \
-                     ~ast_format_compatibility_format2bitfield(ast_format_g719) &         \
-                     ~ast_format_compatibility_format2bitfield(ast_format_ulaw) &         \
-                     ~ast_format_compatibility_format2bitfield(ast_format_alaw) &         \
-                     ~ast_format_compatibility_format2bitfield(ast_format_g722))
+                     ~AST_FORMAT_SLIN &      \
+                     ~AST_FORMAT_SLIN16 &    \
+                     ~AST_FORMAT_SIREN7 &       \
+                     ~AST_FORMAT_SIREN14 &      \
+                     ~AST_FORMAT_G719 &         \
+                     ~AST_FORMAT_ULAW &         \
+                     ~AST_FORMAT_ALAW &         \
+                     ~AST_FORMAT_G722)
 /* A modem */
 #define IAX_CAPABILITY_LOWBANDWIDTH (IAX_CAPABILITY_MEDBANDWIDTH & \
-                     ~ast_format_compatibility_format2bitfield(ast_format_g726) &         \
-                     ~ast_format_compatibility_format2bitfield(ast_format_g726_aal2) &    \
-                     ~ast_format_compatibility_format2bitfield(ast_format_adpcm))
+                     ~AST_FORMAT_G726 &         \
+                     ~AST_FORMAT_G726_AAL2 &    \
+                     ~AST_FORMAT_ADPCM)
 
 #define IAX_CAPABILITY_LOWFREE      (IAX_CAPABILITY_LOWBANDWIDTH & \
-                     ~ast_format_compatibility_format2bitfield(ast_format_g723))
+                     ~AST_FORMAT_G723)
 
 
 #define DEFAULT_MAXMS          2000            /* Must be faster than 2 seconds by default */
@@ -387,7 +387,7 @@ static int (*iax2_regfunk)(const char *username, int onoff) = NULL;
                        break; \
                \
                for (idx = 0; idx < 16; idx++) \
-                       sprintf(digest + (idx << 1), "%2.2x", (unsigned) key[idx]); \
+                       sprintf(digest + (idx << 1), "%02hhx", (unsigned char) key[idx]); \
                \
                ast_log(LOG_NOTICE, msg " IAX_COMMAND_RTKEY to rotate key to '%s'\n", digest); \
        } while(0)
@@ -395,8 +395,6 @@ static int (*iax2_regfunk)(const char *username, int onoff) = NULL;
 static struct io_context *io;
 static struct ast_sched_context *sched;
 
-#define DONT_RESCHEDULE -2
-
 static iax2_format iax2_capability = IAX_CAPABILITY_FULLBANDWIDTH;
 
 static int iaxdebug = 0;
@@ -435,38 +433,37 @@ struct iax2_context {
 };
 
 
-#define        IAX_HASCALLERID         (uint64_t)(1 << 0)    /*!< CallerID has been specified */
-#define IAX_DELME               (uint64_t)(1 << 1)    /*!< Needs to be deleted */
-#define IAX_TEMPONLY            (uint64_t)(1 << 2)    /*!< Temporary (realtime) */
-#define IAX_TRUNK               (uint64_t)(1 << 3)    /*!< Treat as a trunk */
-#define IAX_NOTRANSFER          (uint64_t)(1 << 4)    /*!< Don't native bridge */
-#define IAX_USEJITTERBUF        (uint64_t)(1 << 5)    /*!< Use jitter buffer */
-#define IAX_DYNAMIC             (uint64_t)(1 << 6)    /*!< dynamic peer */
-#define IAX_SENDANI             (uint64_t)(1 << 7)    /*!< Send ANI along with CallerID */
-#define IAX_RTSAVE_SYSNAME      (uint64_t)(1 << 8)    /*!< Save Systname on Realtime Updates */
-#define IAX_ALREADYGONE         (uint64_t)(1 << 9)    /*!< Already disconnected */
-#define IAX_PROVISION           (uint64_t)(1 << 10)   /*!< This is a provisioning request */
-#define IAX_QUELCH              (uint64_t)(1 << 11)   /*!< Whether or not we quelch audio */
-#define IAX_ENCRYPTED           (uint64_t)(1 << 12)   /*!< Whether we should assume encrypted tx/rx */
-#define IAX_KEYPOPULATED        (uint64_t)(1 << 13)   /*!< Whether we have a key populated */
-#define IAX_CODEC_USER_FIRST    (uint64_t)(1 << 14)   /*!< are we willing to let the other guy choose the codec? */
-#define IAX_CODEC_NOPREFS       (uint64_t)(1 << 15)   /*!< Force old behaviour by turning off prefs */
-#define IAX_CODEC_NOCAP         (uint64_t)(1 << 16)   /*!< only consider requested format and ignore capabilities*/
-#define IAX_RTCACHEFRIENDS      (uint64_t)(1 << 17)   /*!< let realtime stay till your reload */
-#define IAX_RTUPDATE            (uint64_t)(1 << 18)   /*!< Send a realtime update */
-#define IAX_RTAUTOCLEAR         (uint64_t)(1 << 19)   /*!< erase me on expire */
-#define IAX_FORCEJITTERBUF      (uint64_t)(1 << 20)   /*!< Force jitterbuffer, even when bridged to a channel that can take jitter */
-#define IAX_RTIGNOREREGEXPIRE   (uint64_t)(1 << 21)   /*!< When using realtime, ignore registration expiration */
-#define IAX_TRUNKTIMESTAMPS     (uint64_t)(1 << 22)   /*!< Send trunk timestamps */
-#define IAX_TRANSFERMEDIA       (uint64_t)(1 << 23)   /*!< When doing IAX2 transfers, transfer media only */
-#define IAX_MAXAUTHREQ          (uint64_t)(1 << 24)   /*!< Maximum outstanding AUTHREQ restriction is in place */
-#define IAX_DELAYPBXSTART       (uint64_t)(1 << 25)   /*!< Don't start a PBX on the channel until the peer sends us a response, so that we've achieved a three-way handshake with them before sending voice or anything else */
-#define IAX_ALLOWFWDOWNLOAD     (uint64_t)(1 << 26)   /*!< Allow the FWDOWNL command? */
-#define IAX_IMMEDIATE           (uint64_t)(1 << 27)   /*!< Allow immediate off-hook to extension s */
-#define IAX_SENDCONNECTEDLINE   (uint64_t)(1 << 28)   /*!< Allow sending of connected line updates */
-#define IAX_RECVCONNECTEDLINE   (uint64_t)(1 << 29)   /*!< Allow receiving of connected line updates */
-#define IAX_FORCE_ENCRYPT       (uint64_t)(1 << 30)   /*!< Forces call encryption, if encryption not possible hangup */
-#define IAX_SHRINKCALLERID      (uint64_t)(1 << 31)   /*!< Turn on and off caller id shrinking */
+#define IAX_HASCALLERID         (uint64_t)(1LLU << 0)    /*!< CallerID has been specified */
+#define IAX_DELME               (uint64_t)(1LLU << 1)    /*!< Needs to be deleted */
+#define IAX_TEMPONLY            (uint64_t)(1LLU << 2)    /*!< Temporary (realtime) */
+#define IAX_TRUNK               (uint64_t)(1LLU << 3)    /*!< Treat as a trunk */
+#define IAX_NOTRANSFER          (uint64_t)(1LLU << 4)    /*!< Don't native bridge */
+#define IAX_USEJITTERBUF        (uint64_t)(1LLU << 5)    /*!< Use jitter buffer */
+#define IAX_DYNAMIC             (uint64_t)(1LLU << 6)    /*!< dynamic peer */
+#define IAX_SENDANI             (uint64_t)(1LLU << 7)    /*!< Send ANI along with CallerID */
+#define IAX_RTSAVE_SYSNAME      (uint64_t)(1LLU << 8)    /*!< Save Systname on Realtime Updates */
+#define IAX_ALREADYGONE         (uint64_t)(1LLU << 9)    /*!< Already disconnected */
+#define IAX_PROVISION           (uint64_t)(1LLU << 10)   /*!< This is a provisioning request */
+#define IAX_QUELCH              (uint64_t)(1LLU << 11)   /*!< Whether or not we quelch audio */
+#define IAX_ENCRYPTED           (uint64_t)(1LLU << 12)   /*!< Whether we should assume encrypted tx/rx */
+#define IAX_KEYPOPULATED        (uint64_t)(1LLU << 13)   /*!< Whether we have a key populated */
+#define IAX_CODEC_USER_FIRST    (uint64_t)(1LLU << 14)   /*!< are we willing to let the other guy choose the codec? */
+#define IAX_CODEC_NOPREFS       (uint64_t)(1LLU << 15)   /*!< Force old behaviour by turning off prefs */
+#define IAX_CODEC_NOCAP         (uint64_t)(1LLU << 16)   /*!< only consider requested format and ignore capabilities*/
+#define IAX_RTCACHEFRIENDS      (uint64_t)(1LLU << 17)   /*!< let realtime stay till your reload */
+#define IAX_RTUPDATE            (uint64_t)(1LLU << 18)   /*!< Send a realtime update */
+#define IAX_RTAUTOCLEAR         (uint64_t)(1LLU << 19)   /*!< erase me on expire */
+#define IAX_RTIGNOREREGEXPIRE   (uint64_t)(1LLU << 21)   /*!< When using realtime, ignore registration expiration */
+#define IAX_TRUNKTIMESTAMPS     (uint64_t)(1LLU << 22)   /*!< Send trunk timestamps */
+#define IAX_TRANSFERMEDIA       (uint64_t)(1LLU << 23)   /*!< When doing IAX2 transfers, transfer media only */
+#define IAX_MAXAUTHREQ          (uint64_t)(1LLU << 24)   /*!< Maximum outstanding AUTHREQ restriction is in place */
+#define IAX_DELAYPBXSTART       (uint64_t)(1LLU << 25)   /*!< Don't start a PBX on the channel until the peer sends us a response, so that we've achieved a three-way handshake with them before sending voice or anything else */
+#define IAX_ALLOWFWDOWNLOAD     (uint64_t)(1LLU << 26)   /*!< Allow the FWDOWNL command? */
+#define IAX_IMMEDIATE           (uint64_t)(1LLU << 27)   /*!< Allow immediate off-hook to extension s */
+#define IAX_SENDCONNECTEDLINE   (uint64_t)(1LLU << 28)   /*!< Allow sending of connected line updates */
+#define IAX_RECVCONNECTEDLINE   (uint64_t)(1LLU << 29)   /*!< Allow receiving of connected line updates */
+#define IAX_FORCE_ENCRYPT       (uint64_t)(1LLU << 30)   /*!< Forces call encryption, if encryption not possible hangup */
+#define IAX_SHRINKCALLERID      (uint64_t)(1LLU << 31)   /*!< Turn on and off caller id shrinking */
 static int global_rtautoclear = 120;
 
 static int reload_config(int forced_reload);
@@ -635,6 +632,8 @@ struct iax2_registry {
        struct ast_sockaddr us;                 /*!< Who the server thinks we are */
        struct ast_dnsmgr_entry *dnsmgr;        /*!< DNS refresh manager */
        AST_LIST_ENTRY(iax2_registry) entry;
+       int port;
+       char hostname[];
 };
 
 static AST_LIST_HEAD_STATIC(registrations, iax2_registry);
@@ -682,7 +681,7 @@ struct chan_iax2_pvt {
        /*! Socket to send/receive on for this call */
        int sockfd;
        /*! ast_callid bound to dialog */
-       struct ast_callid *callid;
+       ast_callid callid;
        /*! Last received voice format */
        iax2_format voiceformat;
        /*! Last received video format */
@@ -863,6 +862,8 @@ struct chan_iax2_pvt {
        int frames_dropped;
        /*! received frame count: (just for stats) */
        int frames_received;
+       /*! Destroying this call initiated. */
+       int destroy_initiated;
        /*! num bytes used for calltoken ie, even an empty ie should contain 2 */
        unsigned char calltoken_ie_len;
        /*! hold all signaling frames from the pbx thread until we have a destination callno */
@@ -917,7 +918,7 @@ static struct ast_taskprocessor *transmit_processor;
 
 static int randomcalltokendata;
 
-static const time_t MAX_CALLTOKEN_DELAY = 10;
+static time_t max_calltoken_delay = 10;
 
 /*!
  * This module will get much higher performance when doing a lot of
@@ -1106,30 +1107,22 @@ static void signal_condition(ast_mutex_t *lock, ast_cond_t *cond)
  */
 static struct chan_iax2_pvt *iaxs[IAX_MAX_CALLS];
 
-static struct ast_callid *iax_pvt_callid_get(int callno)
+static ast_callid iax_pvt_callid_get(int callno)
 {
-       if (iaxs[callno]->callid) {
-               return ast_callid_ref(iaxs[callno]->callid);
-       }
-       return NULL;
+       return iaxs[callno]->callid;
 }
 
-static void iax_pvt_callid_set(int callno, struct ast_callid *callid)
+static void iax_pvt_callid_set(int callno, ast_callid callid)
 {
-       if (iaxs[callno]->callid) {
-               ast_callid_unref(iaxs[callno]->callid);
-       }
-       ast_callid_ref(callid);
        iaxs[callno]->callid = callid;
 }
 
 static void iax_pvt_callid_new(int callno)
 {
-       struct ast_callid *callid = ast_create_callid();
+       ast_callid callid = ast_create_callid();
        char buffer[AST_CALLID_BUFFER_LENGTH];
        ast_callid_strnprint(buffer, sizeof(buffer), callid);
        iax_pvt_callid_set(callno, callid);
-       ast_callid_unref(callid);
 }
 
 /*!
@@ -1419,6 +1412,8 @@ static int iax2_is_control_frame_allowed(int subtype)
                /* Only meaningful across a bridge on this machine for direct-media exchange. */
        case AST_CONTROL_PVT_CAUSE_CODE:
                /* Intended only for the sending machine's local channel structure. */
+       case AST_CONTROL_MASQUERADE_NOTIFY:
+               /* Intended only for masquerades when calling ast_indicate_data(). */
        case AST_CONTROL_STREAM_STOP:
        case AST_CONTROL_STREAM_SUSPEND:
        case AST_CONTROL_STREAM_RESTART:
@@ -1435,13 +1430,6 @@ static int iax2_is_control_frame_allowed(int subtype)
        return is_allowed;
 }
 
-static void mwi_event_cb(void *userdata, struct stasis_subscription *sub, struct stasis_message *msg)
-{
-       /* The MWI subscriptions exist just so the core knows we care about those
-        * mailboxes.  However, we just grab the events out of the cache when it
-        * is time to send MWI, since it is only sent with a REGACK. */
-}
-
 static void network_change_stasis_subscribe(void)
 {
        if (!network_change_sub) {
@@ -1676,23 +1664,48 @@ static int iax2_sched_add(struct ast_sched_context *con, int when,
        return ast_sched_add(con, when, callback, data);
 }
 
+/*
+ * \brief Acquire the iaxsl[callno] if call exists and not having ongoing hangup.
+ * \param callno Call number to lock.
+ * \return 0 If call disappeared or has ongoing hangup procedure. 1 If call found and mutex is locked.
+ */
+static int iax2_lock_callno_unless_destroyed(int callno)
+{
+       ast_mutex_lock(&iaxsl[callno]);
+
+       /* We acquired the lock; but the call was already destroyed (we came after full hang up procedures)
+        * or destroy initiated (in middle of hang up procedure. */
+       if (!iaxs[callno] || iaxs[callno]->destroy_initiated) {
+               ast_debug(3, "I wanted to lock callno %d, but it is dead or going to die.\n", callno);
+               ast_mutex_unlock(&iaxsl[callno]);
+               return 0;
+       }
+
+       /* Lock acquired, and callno is alive and kicking. */
+       return 1;
+}
+
 static int send_ping(const void *data);
 
 static void __send_ping(const void *data)
 {
-       int callno = (long) data;
+       int callno = PTR_TO_CALLNO(data);
 
-       ast_mutex_lock(&iaxsl[callno]);
+       if (iax2_lock_callno_unless_destroyed(callno) == 0) {
+               ast_debug(3, "Hangup initiated on call %d, aborting __send_ping\n", callno);
+               return;
+       }
 
-       if (iaxs[callno]) {
-               if (iaxs[callno]->peercallno) {
-                       send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_PING, 0, NULL, 0, -1);
-                       if (iaxs[callno]->pingid != DONT_RESCHEDULE) {
-                               iaxs[callno]->pingid = iax2_sched_add(sched, ping_time * 1000, send_ping, data);
-                       }
-               }
-       } else {
-               ast_debug(1, "I was supposed to send a PING with callno %d, but no such call exists.\n", callno);
+       /* Mark pingid as invalid scheduler id. */
+       iaxs[callno]->pingid = -1;
+
+       /* callno is now locked. */
+       if (iaxs[callno]->peercallno) {
+               /* Send PING packet. */
+               send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_PING, 0, NULL, 0, -1);
+
+               /* Schedule sending next ping. */
+               iaxs[callno]->pingid = iax2_sched_add(sched, ping_time * 1000, send_ping, data);
        }
 
        ast_mutex_unlock(&iaxsl[callno]);
@@ -1700,13 +1713,6 @@ static void __send_ping(const void *data)
 
 static int send_ping(const void *data)
 {
-       int callno = (long) data;
-       ast_mutex_lock(&iaxsl[callno]);
-       if (iaxs[callno] && iaxs[callno]->pingid != DONT_RESCHEDULE) {
-               iaxs[callno]->pingid = -1;
-       }
-       ast_mutex_unlock(&iaxsl[callno]);
-
 #ifdef SCHED_MULTITHREADED
        if (schedule_action(__send_ping, data))
 #endif
@@ -1747,19 +1753,23 @@ static int send_lagrq(const void *data);
 
 static void __send_lagrq(const void *data)
 {
-       int callno = (long) data;
+       int callno = PTR_TO_CALLNO(data);
 
-       ast_mutex_lock(&iaxsl[callno]);
+       if (iax2_lock_callno_unless_destroyed(callno) == 0) {
+               ast_debug(3, "Hangup initiated on call %d, aborting __send_lagrq\n", callno);
+               return;
+       }
 
-       if (iaxs[callno]) {
-               if (iaxs[callno]->peercallno) {
-                       send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_LAGRQ, 0, NULL, 0, -1);
-                       if (iaxs[callno]->lagid != DONT_RESCHEDULE) {
-                               iaxs[callno]->lagid = iax2_sched_add(sched, lagrq_time * 1000, send_lagrq, data);
-                       }
-               }
-       } else {
-               ast_debug(1, "I was supposed to send a LAGRQ with callno %d, but no such call exists.\n", callno);
+       /* Mark lagid as invalid scheduler id. */
+       iaxs[callno]->lagid = -1;
+
+       /* callno is now locked. */
+       if (iaxs[callno]->peercallno) {
+               /* Send LAGRQ packet. */
+               send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_LAGRQ, 0, NULL, 0, -1);
+
+               /* Schedule sending next lagrq. */
+               iaxs[callno]->lagid = iax2_sched_add(sched, lagrq_time * 1000, send_lagrq, data);
        }
 
        ast_mutex_unlock(&iaxsl[callno]);
@@ -1767,13 +1777,6 @@ static void __send_lagrq(const void *data)
 
 static int send_lagrq(const void *data)
 {
-       int callno = (long) data;
-       ast_mutex_lock(&iaxsl[callno]);
-       if (iaxs[callno] && iaxs[callno]->lagid != DONT_RESCHEDULE) {
-               iaxs[callno]->lagid = -1;
-       }
-       ast_mutex_unlock(&iaxsl[callno]);
-
 #ifdef SCHED_MULTITHREADED
        if (schedule_action(__send_lagrq, data))
 #endif
@@ -1815,7 +1818,41 @@ static iax2_format uncompress_subclass(unsigned char csub)
                return csub;
 }
 
-static iax2_format iax2_codec_choose(struct iax2_codec_pref *pref, iax2_format formats, int find_best)
+static struct ast_format *codec_choose_from_prefs(struct iax2_codec_pref *pref, struct ast_format_cap *cap)
+{
+       int x;
+       struct ast_format *found_format = NULL;
+
+       for (x = 0; x < ARRAY_LEN(pref->order); ++x) {
+               struct ast_format *pref_format;
+               uint64_t pref_bitfield;
+
+               pref_bitfield = iax2_codec_pref_order_value_to_format_bitfield(pref->order[x]);
+               if (!pref_bitfield) {
+                       break;
+               }
+
+               pref_format = ast_format_compatibility_bitfield2format(pref_bitfield);
+               if (!pref_format) {
+                       /* The bitfield is not associated with any format. */
+                       continue;
+               }
+               found_format = ast_format_cap_get_compatible_format(cap, pref_format);
+               if (found_format) {
+                       break;
+               }
+       }
+
+       if (found_format && (ast_format_get_type(found_format) == AST_MEDIA_TYPE_AUDIO)) {
+               return found_format;
+       }
+
+       ast_debug(4, "Could not find preferred codec - Returning zero codec.\n");
+       ao2_cleanup(found_format);
+       return NULL;
+}
+
+static iax2_format iax2_codec_choose(struct iax2_codec_pref *pref, iax2_format formats)
 {
        struct ast_format_cap *cap;
        struct ast_format *tmpfmt;
@@ -1823,7 +1860,12 @@ static iax2_format iax2_codec_choose(struct iax2_codec_pref *pref, iax2_format f
 
        if ((cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
                iax2_format_compatibility_bitfield2cap(formats, cap);
-               tmpfmt = ast_format_cap_get_format(cap, 0);
+               tmpfmt = codec_choose_from_prefs(pref, cap);
+               if (!tmpfmt) {
+                       ao2_ref(cap, -1);
+                       return 0;
+               }
+
                format = ast_format_compatibility_format2bitfield(tmpfmt);
                ao2_ref(tmpfmt, -1);
                ao2_ref(cap, -1);
@@ -1832,25 +1874,6 @@ static iax2_format iax2_codec_choose(struct iax2_codec_pref *pref, iax2_format f
        return format;
 }
 
-static iax2_format iax2_best_codec(iax2_format formats)
-{
-       struct ast_format_cap *cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
-       struct ast_format *tmpfmt;
-       iax2_format format;
-
-       if (!cap) {
-               return 0;
-       }
-
-       iax2_format_compatibility_bitfield2cap(formats, cap);
-       tmpfmt = ast_format_cap_get_format(cap, 0);
-       format = ast_format_compatibility_format2bitfield(tmpfmt);
-       ao2_ref(tmpfmt, -1);
-       ao2_ref(cap, -1);
-
-       return format;
-}
-
 const char *iax2_getformatname(iax2_format format)
 {
        struct ast_format *tmpfmt;
@@ -1880,33 +1903,24 @@ static const char *iax2_getformatname_multiple(iax2_format format, struct ast_st
 static int iax2_parse_allow_disallow(struct iax2_codec_pref *pref, iax2_format *formats, const char *list, int allowing)
 {
        int res, i;
-       struct ast_format_cap *cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
-
-       if (!cap) {
-               return 1;
-       }
+       struct ast_format_cap *cap;
 
        /* We want to add the formats to the cap in the preferred order */
-       for (i = 0; i < IAX2_CODEC_PREF_SIZE; i++) {
-               uint64_t pref_as_bitfield = iax2_codec_pref_order_value_to_format_bitfield(pref->order[i]);
-
-               if (!pref_as_bitfield) {
-                       break;
-               }
-
-               if (iax2_format_compatibility_bitfield2cap(pref_as_bitfield, cap)) {
-                       ao2_ref(cap, -1);
-                       return 1;
-               }
+       cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+       if (!cap || iax2_codec_pref_to_cap(pref, cap)) {
+               ao2_cleanup(cap);
+               return 1;
        }
 
        res = ast_format_cap_update_by_allow_disallow(cap, list, allowing);
-       *formats = iax2_format_compatibility_cap2bitfield(cap);
 
+       /* Adjust formats bitfield and pref list to match. */
+       *formats = iax2_format_compatibility_cap2bitfield(cap);
        iax2_codec_pref_remove_missing(pref, *formats);
 
        for (i = 0; i < ast_format_cap_count(cap); i++) {
                struct ast_format *fmt = ast_format_cap_get_format(cap, i);
+
                iax2_codec_pref_append(pref, fmt, ast_format_cap_get_format_framing(cap, fmt));
                ao2_ref(fmt, -1);
        }
@@ -2008,11 +2022,6 @@ static struct iax2_user *find_user(const char *name)
 {
        return ao2_find(users, name, OBJ_KEY);
 }
-static inline struct iax2_user *user_ref(struct iax2_user *user)
-{
-       ao2_ref(user, +1);
-       return user;
-}
 
 static inline struct iax2_user *user_unref(struct iax2_user *user)
 {
@@ -2051,6 +2060,16 @@ static int iax2_getpeername(struct ast_sockaddr addr, char *host, int len)
        return res;
 }
 
+/* Call AST_SCHED_DEL on a scheduled task if it is found in scheduler. */
+static int iax2_delete_from_sched(const void* data)
+{
+       int sched_id = (int)(long)data;
+
+       AST_SCHED_DEL(sched, sched_id);
+
+       return 0;
+}
+
 /*!\note Assumes the lock on the pvt is already held, when
  * iax2_destroy_helper() is called. */
 static void iax2_destroy_helper(struct chan_iax2_pvt *pvt)
@@ -2067,11 +2086,27 @@ static void iax2_destroy_helper(struct chan_iax2_pvt *pvt)
 
                ast_clear_flag64(pvt, IAX_MAXAUTHREQ);
        }
-       /* No more pings or lagrq's */
-       AST_SCHED_DEL_SPINLOCK(sched, pvt->pingid, &iaxsl[pvt->callno]);
-       pvt->pingid = DONT_RESCHEDULE;
-       AST_SCHED_DEL_SPINLOCK(sched, pvt->lagid, &iaxsl[pvt->callno]);
-       pvt->lagid = DONT_RESCHEDULE;
+
+
+       /* Mark call destroy initiated flag. */
+       pvt->destroy_initiated = 1;
+
+       /*
+        * Schedule deleting the scheduled (but didn't run yet) PINGs or LAGRQs.
+        * Already running tasks will be terminated because of destroy_initiated.
+        *
+        * Don't call AST_SCHED_DEL from this thread for pingid and lagid because
+        * it leads to a deadlock between the scheduler thread callback locking
+        * the callno mutex and this thread which holds the callno mutex one or
+        * more times.  It is better to have another thread delete the scheduled
+        * callbacks which doesn't lock the callno mutex.
+        */
+       iax2_sched_add(sched, 0, iax2_delete_from_sched, (void*)(long)pvt->pingid);
+       iax2_sched_add(sched, 0, iax2_delete_from_sched, (void*)(long)pvt->lagid);
+
+       pvt->pingid = -1;
+       pvt->lagid = -1;
+
        AST_SCHED_DEL(sched, pvt->autoid);
        AST_SCHED_DEL(sched, pvt->authid);
        AST_SCHED_DEL(sched, pvt->initid);
@@ -2190,11 +2225,6 @@ static void pvt_destructor(void *obj)
                jb_destroy(pvt->jb);
                ast_string_field_free_memory(pvt);
        }
-
-       if (pvt->callid) {
-               ast_callid_unref(pvt->callid);
-       }
-
 }
 
 static struct chan_iax2_pvt *new_iax(struct ast_sockaddr *addr, const char *host)
@@ -2212,7 +2242,7 @@ static struct chan_iax2_pvt *new_iax(struct ast_sockaddr *addr, const char *host
                return NULL;
        }
 
-       tmp->prefs = prefs;
+       tmp->prefs = prefs_global;
        tmp->pingid = -1;
        tmp->lagid = -1;
        tmp->autoid = -1;
@@ -3165,7 +3195,7 @@ static int __find_callno(unsigned short callno, unsigned short dcallno, struct a
                        iaxs[x]->pingid = iax2_sched_add(sched, ping_time * 1000, send_ping, (void *)(long)x);
                        iaxs[x]->lagid = iax2_sched_add(sched, lagrq_time * 1000, send_lagrq, (void *)(long)x);
                        iaxs[x]->amaflags = amaflags;
-                       ast_copy_flags64(iaxs[x], &globalflags, IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF | IAX_SENDCONNECTEDLINE | IAX_RECVCONNECTEDLINE | IAX_FORCE_ENCRYPT);
+                       ast_copy_flags64(iaxs[x], &globalflags, IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_SENDCONNECTEDLINE | IAX_RECVCONNECTEDLINE | IAX_FORCE_ENCRYPT);
                        ast_string_field_set(iaxs[x], accountcode, accountcode);
                        ast_string_field_set(iaxs[x], mohinterpret, mohinterpret);
                        ast_string_field_set(iaxs[x], mohsuggest, mohsuggest);
@@ -3773,7 +3803,7 @@ static char *handle_cli_iax2_show_peer(struct ast_cli_entry *e, int cmd, struct
        char status[30];
        char cbuf[256];
        struct iax2_peer *peer;
-       struct ast_str *codec_buf = ast_str_alloca(64);
+       struct ast_str *codec_buf = ast_str_alloca(256);
        struct ast_str *encmethods = ast_str_alloca(256);
        int load_realtime = 0;
 
@@ -3824,17 +3854,15 @@ static char *handle_cli_iax2_show_peer(struct ast_cli_entry *e, int cmd, struct
                ast_cli(a->fd, "  Addr->IP     : %s Port %s\n",  str_addr ? str_addr : "(Unspecified)", str_port);
                ast_cli(a->fd, "  Defaddr->IP  : %s Port %s\n", str_defaddr, str_defport);
                ast_cli(a->fd, "  Username     : %s\n", peer->username);
-               ast_cli(a->fd, "  Codecs       : ");
-               ast_cli(a->fd, "%s\n", iax2_getformatname_multiple(peer->capability, &codec_buf));
+               ast_cli(a->fd, "  Codecs       : %s\n", iax2_getformatname_multiple(peer->capability, &codec_buf));
 
-               ast_cli(a->fd, "  Codec Order  : ");
-               if (iax2_codec_pref_string(&peer->prefs, cbuf, sizeof(cbuf)) != -1) {
-                       ast_cli(a->fd, "%s\n", cbuf);
+               if (iax2_codec_pref_string(&peer->prefs, cbuf, sizeof(cbuf)) < 0) {
+                       strcpy(cbuf, "Error"); /* Safe */
                }
+               ast_cli(a->fd, "  Codec Order  : %s\n", cbuf);
 
-               ast_cli(a->fd, "  Status       : ");
                peer_status(peer, status, sizeof(status));
-               ast_cli(a->fd, "%s\n",status);
+               ast_cli(a->fd, "  Status       : %s\n", status);
                ast_cli(a->fd, "  Qualify      : every %dms when OK, every %dms when UNREACHABLE (sample smoothing %s)\n", peer->pokefreqok, peer->pokefreqnotok, peer->smoothing ? "On" : "Off");
                ast_cli(a->fd, "\n");
                peer_unref(peer);
@@ -4112,7 +4140,7 @@ static void __get_from_jb(const void *p)
        if(ms >= (next = jb_next(pvt->jb))) {
                struct ast_format *voicefmt;
                voicefmt = ast_format_compatibility_bitfield2format(pvt->voiceformat);
-               ret = jb_get(pvt->jb, &frame, ms, ast_format_get_default_ms(voicefmt));
+               ret = jb_get(pvt->jb, &frame, ms, voicefmt ? ast_format_get_default_ms(voicefmt) : 20);
                switch(ret) {
                case JB_OK:
                        fr = frame.data;
@@ -4178,8 +4206,6 @@ static int schedule_delivery(struct iax_frame *fr, int updatehistory, int fromtr
        int type, len;
        int ret;
        int needfree = 0;
-       struct ast_channel *owner = NULL;
-       RAII_VAR(struct ast_channel *, bridge, NULL, ast_channel_cleanup);
 
        /*
         * Clear fr->af.data if there is no data in the buffer.  Things
@@ -4220,45 +4246,6 @@ static int schedule_delivery(struct iax_frame *fr, int updatehistory, int fromtr
                return -1;
        }
 
-       iax2_lock_owner(fr->callno);
-       if (!iaxs[fr->callno]) {
-               /* The call dissappeared so discard this frame that we could not send. */
-               iax2_frame_free(fr);
-               return -1;
-       }
-       if ((owner = iaxs[fr->callno]->owner)) {
-               bridge = ast_channel_bridge_peer(owner);
-       }
-
-       /* if the user hasn't requested we force the use of the jitterbuffer, and we're bridged to
-        * a channel that can accept jitter, then flush and suspend the jb, and send this frame straight through */
-       if ( (!ast_test_flag64(iaxs[fr->callno], IAX_FORCEJITTERBUF)) && owner && bridge && (ast_channel_tech(bridge)->properties & AST_CHAN_TP_WANTSJITTER) ) {
-               jb_frame frame;
-
-               ast_channel_unlock(owner);
-
-               /* deliver any frames in the jb */
-               while (jb_getall(iaxs[fr->callno]->jb, &frame) == JB_OK) {
-                       __do_deliver(frame.data);
-                       /* __do_deliver() can make the call disappear */
-                       if (!iaxs[fr->callno])
-                               return -1;
-               }
-
-               jb_reset(iaxs[fr->callno]->jb);
-
-               AST_SCHED_DEL(sched, iaxs[fr->callno]->jbid);
-
-               /* deliver this frame now */
-               if (tsout)
-                       *tsout = fr->ts;
-               __do_deliver(fr);
-               return -1;
-       }
-       if (owner) {
-               ast_channel_unlock(owner);
-       }
-
        /* insert into jitterbuffer */
        /* TODO: Perhaps we could act immediately if it's not droppable and late */
        ret = jb_put(iaxs[fr->callno]->jb, fr, type, len, fr->ts,
@@ -4393,7 +4380,7 @@ static struct iax2_peer *realtime_peer(const char *peername, struct ast_sockaddr
                if (var && !ast_sockaddr_isnull(addr)) {
                        for (tmp = var; tmp; tmp = tmp->next) {
                                if (!strcasecmp(tmp->name, "host")) {
-                                       struct ast_sockaddr *hostaddr;
+                                       struct ast_sockaddr *hostaddr = NULL;
 
                                        if (!ast_sockaddr_resolve(&hostaddr, tmp->value, PARSE_PORT_FORBID, AST_AF_UNSPEC)
                                                || ast_sockaddr_cmp_addr(hostaddr, addr)) {
@@ -4401,6 +4388,7 @@ static struct iax2_peer *realtime_peer(const char *peername, struct ast_sockaddr
                                                ast_variables_destroy(var);
                                                var = NULL;
                                        }
+                                       ast_free(hostaddr);
                                        break;
                                }
                        }
@@ -4515,7 +4503,7 @@ static struct iax2_user *realtime_user(const char *username, struct ast_sockaddr
                if (var) {
                        for (tmp = var; tmp; tmp = tmp->next) {
                                if (!strcasecmp(tmp->name, "host")) {
-                                       struct ast_sockaddr *hostaddr;
+                                       struct ast_sockaddr *hostaddr = NULL;
 
                                        if (!ast_sockaddr_resolve(&hostaddr, tmp->value, PARSE_PORT_FORBID, AST_AF_UNSPEC)
                                                || ast_sockaddr_cmp_addr(hostaddr, addr)) {
@@ -4523,6 +4511,7 @@ static struct iax2_user *realtime_user(const char *username, struct ast_sockaddr
                                                ast_variables_destroy(var);
                                                var = NULL;
                                        }
+                                       ast_free(hostaddr);
                                        break;
                                }
                        }
@@ -4583,6 +4572,7 @@ static void realtime_update_peer(const char *peername, struct ast_sockaddr *sock
 struct create_addr_info {
        iax2_format capability;
        uint64_t flags;
+       struct iax2_codec_pref prefs;
        int maxtime;
        int encmethods;
        int found;
@@ -4592,7 +4582,6 @@ struct create_addr_info {
        char secret[80];
        char outkey[80];
        char timezone[80];
-       char prefs[32];
        char cid_num[80];
        char cid_name[80];
        char context[AST_MAX_CONTEXT];
@@ -4605,7 +4594,6 @@ static int create_addr(const char *peername, struct ast_channel *c, struct ast_s
 {
        struct iax2_peer *peer;
        int res = -1;
-       struct iax2_codec_pref ourprefs;
 
        ast_clear_flag64(cai, IAX_SENDANI | IAX_TRUNK);
        cai->sockfd = defaultsockfd;
@@ -4626,20 +4614,24 @@ static int create_addr(const char *peername, struct ast_channel *c, struct ast_s
                }
 
                ast_sockaddr_copy(addr, &peer_addr);
-               /* use global iax prefs for unknown peer/user */
-               /* But move the calling channel's native codec to the top of the preference list */
-               memcpy(&ourprefs, &prefs, sizeof(ourprefs));
+               /*
+                * Use The global iax prefs for unknown peer/user.
+                * However, move the calling channel's native codec to
+                * the top of the preference list.
+                */
+               cai->prefs = prefs_global;
                if (c) {
                        int i;
 
                        for (i = 0; i < ast_format_cap_count(ast_channel_nativeformats(c)); i++) {
                                struct ast_format *format = ast_format_cap_get_format(
                                        ast_channel_nativeformats(c), i);
-                               iax2_codec_pref_prepend(&ourprefs, format, ast_format_cap_get_format_framing(ast_channel_nativeformats(c), format), 1);
+                               iax2_codec_pref_prepend(&cai->prefs, format,
+                                       ast_format_cap_get_format_framing(ast_channel_nativeformats(c), format),
+                                       1);
                                ao2_ref(format, -1);
                        }
                }
-               iax2_codec_pref_convert(&ourprefs, cai->prefs, sizeof(cai->prefs), 1);
                return 0;
        }
 
@@ -4654,13 +4646,13 @@ static int create_addr(const char *peername, struct ast_channel *c, struct ast_s
        if (peer->maxms && ((peer->lastms > peer->maxms) || (peer->lastms < 0)))
                goto return_unref;
 
-       ast_copy_flags64(cai, peer, IAX_SENDANI | IAX_TRUNK | IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF | IAX_SENDCONNECTEDLINE | IAX_RECVCONNECTEDLINE | IAX_FORCE_ENCRYPT);
+       ast_copy_flags64(cai, peer, IAX_SENDANI | IAX_TRUNK | IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_SENDCONNECTEDLINE | IAX_RECVCONNECTEDLINE | IAX_FORCE_ENCRYPT);
        cai->maxtime = peer->maxms;
        cai->capability = peer->capability;
        cai->encmethods = peer->encmethods;
        cai->sockfd = peer->sockfd;
        cai->adsi = peer->adsi;
-       memcpy(&ourprefs, &peer->prefs, sizeof(ourprefs));
+       cai->prefs = peer->prefs;
        /* Move the calling channel's native codec to the top of the preference list */
        if (c) {
                int i;
@@ -4668,11 +4660,12 @@ static int create_addr(const char *peername, struct ast_channel *c, struct ast_s
                for (i = 0; i < ast_format_cap_count(ast_channel_nativeformats(c)); i++) {
                        struct ast_format *tmpfmt = ast_format_cap_get_format(
                                ast_channel_nativeformats(c), i);
-                       iax2_codec_pref_prepend(&ourprefs, tmpfmt, ast_format_cap_get_format_framing(ast_channel_nativeformats(c), tmpfmt), 1);
+                       iax2_codec_pref_prepend(&cai->prefs, tmpfmt,
+                               ast_format_cap_get_format_framing(ast_channel_nativeformats(c), tmpfmt),
+                               1);
                        ao2_ref(tmpfmt, -1);
                }
        }
-       iax2_codec_pref_convert(&ourprefs, cai->prefs, sizeof(cai->prefs), 1);
        ast_copy_string(cai->context, peer->context, sizeof(cai->context));
        ast_copy_string(cai->peercontext, peer->peercontext, sizeof(cai->peercontext));
        ast_copy_string(cai->username, peer->username, sizeof(cai->username));
@@ -4975,7 +4968,7 @@ static int handle_call_token(struct ast_iax2_full_hdr *fh, struct iax_ies *ies,
                if (strcmp(hash, rec_hash)) {
                        ast_log(LOG_WARNING, "Address %s failed CallToken hash inspection\n", ast_sockaddr_stringify(addr));
                        goto reject; /* received hash does not match ours, reject */
-               } else if ((t < rec_time) || ((t - rec_time) >= MAX_CALLTOKEN_DELAY)) {
+               } else if ((t < rec_time) || ((t - rec_time) >= max_calltoken_delay)) {
                        ast_log(LOG_WARNING, "Too much delay in IAX2 calltoken timestamp from address %s\n", ast_sockaddr_stringify(addr));
                        goto reject; /* too much delay, reject */
                }
@@ -5021,7 +5014,7 @@ reject:
  * password field will be set to NULL.
  *
  * \note The dial string format is:
- *       [username[:password]@]peer[:port][/exten[@@context]][/options]
+ *       [username[:password]@]peer[:port][/exten[@context]][/options]
  */
 static void parse_dial_string(char *data, struct parsed_dial_string *pds)
 {
@@ -5054,9 +5047,10 @@ static void parse_dial_string(char *data, struct parsed_dial_string *pds)
        pds->peer = strsep(&data, ":");
        pds->port = data;
 
-       /* check for a key name wrapped in [] in the secret position, if found,
-          move it to the key field instead
-       */
+       /*
+        * Check for a key name wrapped in [] in the password position.
+        * If found, move it to the key field instead.
+        */
        if (pds->password && (pds->password[0] == '[')) {
                pds->key = ast_strip_quoted(pds->password, "[", "]");
                pds->password = NULL;
@@ -5079,6 +5073,7 @@ static int iax2_call(struct ast_channel *c, const char *dest, int timeout)
        unsigned char osp_block_index;
        unsigned int osp_block_length;
        unsigned char osp_buffer[256];
+       char encoded_prefs[32];
        iax2_format iax2_tmpfmt;
 
        if ((ast_channel_state(c) != AST_STATE_DOWN) && (ast_channel_state(c) != AST_STATE_RESERVED)) {
@@ -5147,7 +5142,8 @@ static int iax2_call(struct ast_channel *c, const char *dest, int timeout)
        }
 
        /* WARNING: this breaks down at 190 bits! */
-       iax_ie_append_str(&ied, IAX_IE_CODEC_PREFS, cai.prefs);
+       iax2_codec_pref_convert(&cai.prefs, encoded_prefs, sizeof(encoded_prefs), 1);
+       iax_ie_append_str(&ied, IAX_IE_CODEC_PREFS, encoded_prefs);
 
        if (l) {
                iax_ie_append_str(&ied, IAX_IE_CALLING_NUMBER, l);
@@ -5752,6 +5748,7 @@ static int iax2_indicate(struct ast_channel *c, int condition, const void *data,
                }
                break;
        case AST_CONTROL_PVT_CAUSE_CODE:
+       case AST_CONTROL_MASQUERADE_NOTIFY:
                res = -1;
                goto done;
        }
@@ -5806,28 +5803,66 @@ static int iax2_getpeertrunk(struct ast_sockaddr addr)
 }
 
 /*! \brief  Create new call, interface with the PBX core */
-static struct ast_channel *ast_iax2_new(int callno, int state, iax2_format capability, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, unsigned int cachable)
+static struct ast_channel *ast_iax2_new(int callno, int state, iax2_format capability,
+       struct iax2_codec_pref *prefs, const struct ast_assigned_ids *assignedids,
+       const struct ast_channel *requestor, unsigned int cachable)
 {
-       struct ast_channel *tmp;
+       struct ast_channel *tmp = NULL;
        struct chan_iax2_pvt *i;
+       struct iax2_peer *peer;
        struct ast_variable *v = NULL;
        struct ast_format_cap *native;
        struct ast_format *tmpfmt;
-       struct ast_callid *callid;
+       ast_callid callid;
+       char *peer_name = NULL;
 
        if (!(i = iaxs[callno])) {
                ast_log(LOG_WARNING, "No IAX2 pvt found for callno '%d' !\n", callno);
                return NULL;
        }
 
+       if (!capability) {
+               ast_log(LOG_WARNING, "No formats specified for call to: IAX2/%s-%d\n",
+                       i->host, i->callno);
+               return NULL;
+       }
        native = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
        if (!native) {
                return NULL;
        }
+       if (iax2_codec_pref_best_bitfield2cap(capability, prefs, native)
+               || !ast_format_cap_count(native)) {
+               ast_log(LOG_WARNING, "No requested formats available for call to: IAX2/%s-%d\n",
+                       i->host, i->callno);
+               ao2_ref(native, -1);
+               return NULL;
+       }
+
+       if (!ast_strlen_zero(i->peer)) {
+               peer_name = ast_strdupa(i->peer);
+       } else if (!ast_strlen_zero(i->host)) {
+               peer_name = ast_strdupa(i->host);
+       }
 
-       /* Don't hold call lock */
+       /* Don't hold call lock while making a channel or looking up a peer */
        ast_mutex_unlock(&iaxsl[callno]);
-       tmp = ast_channel_alloc(1, state, i->cid_num, i->cid_name, i->accountcode, i->exten, i->context, assignedids, requestor, i->amaflags, "IAX2/%s-%d", i->host, i->callno);
+
+       if (!ast_strlen_zero(peer_name)) {
+               peer = find_peer(peer_name, 1);
+               if (peer && peer->endpoint) {
+                       tmp = ast_channel_alloc_with_endpoint(1, state, i->cid_num, i->cid_name,
+                               i->accountcode, i->exten, i->context, assignedids, requestor,
+                               i->amaflags, peer->endpoint, "IAX2/%s-%d", i->host, i->callno);
+               }
+               ao2_cleanup(peer);
+       }
+
+       if (!tmp) {
+               tmp = ast_channel_alloc(1, state, i->cid_num, i->cid_name, i->accountcode,
+                       i->exten, i->context, assignedids, requestor, i->amaflags, "IAX2/%s-%d",
+                       i->host, i->callno);
+       }
+
        ast_mutex_lock(&iaxsl[callno]);
        if (i != iaxs[callno]) {
                if (tmp) {
@@ -5854,9 +5889,8 @@ static struct ast_channel *ast_iax2_new(int callno, int state, iax2_format capab
        ast_channel_tech_set(tmp, &iax2_tech);
 
        /* We can support any format by default, until we get restricted */
-       iax2_format_compatibility_bitfield2cap(capability, native);
        ast_channel_nativeformats_set(tmp, native);
-       tmpfmt = ast_format_cap_get_format(ast_channel_nativeformats(tmp), 0);
+       tmpfmt = ast_format_cap_get_format(native, 0);
 
        ast_channel_set_readformat(tmp, tmpfmt);
        ast_channel_set_rawreadformat(tmp, tmpfmt);
@@ -5955,8 +5989,10 @@ static struct ast_channel *ast_iax2_new(int callno, int state, iax2_format capab
        if (state != AST_STATE_DOWN) {
                if (ast_pbx_start(tmp)) {
                        ast_log(LOG_WARNING, "Unable to start PBX on %s\n", ast_channel_name(tmp));
+                       /* unlock and relock iaxsl[callno] to preserve locking order */
+                       ast_mutex_unlock(&iaxsl[callno]);
                        ast_hangup(tmp);
-                       i->owner = NULL;
+                       ast_mutex_lock(&iaxsl[callno]);
                        return NULL;
                }
        }
@@ -5984,7 +6020,7 @@ static unsigned int calc_txpeerstamp(struct iax2_trunk_peer *tpeer, int sampms,
        ms = ast_tvdiff_ms(*now, tpeer->txtrunktime);
        /* Predict from last value */
        pred = tpeer->lastsent + sampms;
-       if (abs(ms - pred) < MAX_TIMESTAMP_SKEW)
+       if (labs(ms - pred) < MAX_TIMESTAMP_SKEW)
                ms = pred;
 
        /* We never send the same timestamp twice, so fudge a little if we must */
@@ -6057,7 +6093,8 @@ static unsigned int calc_timestamp(struct chan_iax2_pvt *p, unsigned int ts, str
                        ms = 0;
                if (voice) {
                        /* On a voice frame, use predicted values if appropriate */
-                       if (p->notsilenttx && abs(ms - p->nextpred) <= MAX_TIMESTAMP_SKEW) {
+                       adjust = (ms - p->nextpred);
+                       if (p->notsilenttx && abs(adjust) <= MAX_TIMESTAMP_SKEW) {
                                /* Adjust our txcore, keeping voice and non-voice synchronized */
                                /* AN EXPLANATION:
                                   When we send voice, we usually send "calculated" timestamps worked out
@@ -6076,7 +6113,6 @@ static unsigned int calc_timestamp(struct chan_iax2_pvt *p, unsigned int ts, str
                                   changing at all.  But if a consistent different starts to develop it
                                   will be eliminated over the course of 10 frames (200-300msecs)
                                */
-                               adjust = (ms - p->nextpred);
                                if (adjust < 0)
                                        p->offset = ast_tvsub(p->offset, ast_samp2tv(abs(adjust), 10000));
                                else if (adjust > 0)
@@ -6098,9 +6134,9 @@ static unsigned int calc_timestamp(struct chan_iax2_pvt *p, unsigned int ts, str
                                * silent periods are multiples of
                                * frame size too) */
 
-                               if (iaxdebug && abs(ms - p->nextpred) > MAX_TIMESTAMP_SKEW )
+                               if (iaxdebug && abs(adjust) > MAX_TIMESTAMP_SKEW )
                                        ast_debug(1, "predicted timestamp skew (%d) > max (%d), using real ts instead.\n",
-                                               abs(ms - p->nextpred), MAX_TIMESTAMP_SKEW);
+                                               abs(adjust), MAX_TIMESTAMP_SKEW);
 
                                if (f->samples >= rate) /* check to make sure we don't core dump */
                                {
@@ -6126,11 +6162,12 @@ static unsigned int calc_timestamp(struct chan_iax2_pvt *p, unsigned int ts, str
                } else {
                        /* On a dataframe, use last value + 3 (to accomodate jitter buffer shrinking) if appropriate unless
                           it's a genuine frame */
+                       adjust = (ms - p->lastsent);
                        if (genuine) {
                                /* genuine (IAX LAGRQ etc) must keep their clock-based stamps */
                                if (ms <= p->lastsent)
                                        ms = p->lastsent + 3;
-                       } else if (abs(ms - p->lastsent) <= MAX_TIMESTAMP_SKEW) {
+                       } else if (abs(adjust) <= MAX_TIMESTAMP_SKEW) {
                                /* non-genuine frames (!?) (DTMF, CONTROL) should be pulled into the predicted stream stamps */
                                ms = p->lastsent + 3;
                        }
@@ -6382,7 +6419,7 @@ static int decode_frame(ast_aes_decrypt_key *dcx, struct ast_iax2_full_hdr *fh,
 
                padding = 16 + (workspace[15] & 0x0f);
                if (iaxdebug)
-                       ast_debug(1, "Decoding full frame with length %d (padding = %d) (15=%02x)\n", *datalen, padding, (unsigned)workspace[15]);
+                       ast_debug(1, "Decoding full frame with length %d (padding = %d) (15=%02hhx)\n", *datalen, padding, workspace[15]);
                if (*datalen < padding + sizeof(struct ast_iax2_full_hdr))
                        return -1;
 
@@ -6429,7 +6466,7 @@ static int encrypt_frame(ast_aes_encrypt_key *ecx, struct ast_iax2_full_hdr *fh,
                workspace[15] &= 0xf0;
                workspace[15] |= (padding & 0xf);
                if (iaxdebug)
-                       ast_debug(1, "Encoding full frame %d/%d with length %d + %d padding (15=%02x)\n", fh->type, fh->csub, *datalen, padding, (unsigned)workspace[15]);
+                       ast_debug(1, "Encoding full frame %d/%d with length %d + %d padding (15=%02hhx)\n", fh->type, fh->csub, *datalen, padding, workspace[15]);
                *datalen += padding;
                memcpy_encrypt(efh->encdata, workspace, *datalen - sizeof(struct ast_iax2_full_enc_hdr), ecx);
                if (*datalen >= 32 + sizeof(struct ast_iax2_full_enc_hdr))
@@ -6533,7 +6570,8 @@ static int iax2_send(struct chan_iax2_pvt *pvt, struct ast_frame *f, unsigned in
                /* High two bytes are the same on timestamp, or sending on a trunk */ &&
            (f->frametype == AST_FRAME_VOICE)
                /* is a voice frame */ &&
-               (ast_format_cmp(f->subclass.format, ast_format_compatibility_bitfield2format(pvt->svoiceformat)))
+               (ast_format_cmp(f->subclass.format, ast_format_compatibility_bitfield2format(pvt->svoiceformat)) ==
+                       AST_FORMAT_CMP_EQUAL)
                /* is the same type */ ) {
                        /* Force immediate rather than delayed transmission */
                        now = 1;
@@ -6547,7 +6585,8 @@ static int iax2_send(struct chan_iax2_pvt *pvt, struct ast_frame *f, unsigned in
                 * Otherwise send a mini video frame
                 */
                if (((fts & 0xFFFF8000L) == (pvt->lastvsent & 0xFFFF8000L)) &&
-               (ast_format_cmp(f->subclass.format, ast_format_compatibility_bitfield2format(pvt->svideoformat)))
+               (ast_format_cmp(f->subclass.format, ast_format_compatibility_bitfield2format(pvt->svideoformat)) ==
+                       AST_FORMAT_CMP_EQUAL)
                   ) {
                        now = 1;
                        sendmini = 1;
@@ -6810,31 +6849,23 @@ static void _iax2_show_peers_one(int fd, struct mansession *s, struct show_peers
        }
 
        if (s) {
-
                if (cont->peerlist) { /* IAXpeerlist */
-
                        astman_append(s,
                                "Event: PeerEntry\r\n%s"
                                "Channeltype: IAX\r\n",
                                cont->idtext);
-
                        if (!ast_strlen_zero(peer->username)) {
-
                                astman_append(s,
                                        "ObjectName: %s\r\n"
                                        "ObjectUsername: %s\r\n",
                                        peer->name,
                                        peer->username);
-
                        } else {
-
                                astman_append(s,
                                        "ObjectName: %s\r\n",
                                        name);
                        }
-
                } else { /* IAXpeers */
-
                        astman_append(s,
                                "Event: PeerEntry\r\n%s"
                                "Channeltype: IAX2\r\n"
@@ -6842,28 +6873,21 @@ static void _iax2_show_peers_one(int fd, struct mansession *s, struct show_peers
                                cont->idtext,
                                name);
                }
-
                astman_append(s,
                        "ChanObjectType: peer\r\n"
                        "IPaddress: %s\r\n",
                        tmp_host);
-
                if (cont->peerlist) { /* IAXpeerlist */
-
                        astman_append(s,
                                "Mask: %s\r\n"
                                "Port: %s\r\n",
                                tmp_mask,
                                tmp_port);
-
                } else { /* IAXpeers */
-
                        astman_append(s,
                                "IPport: %s\r\n",
                                tmp_port);
-
                }
-
                astman_append(s,
                        "Dynamic: %s\r\n"
                        "Trunk: %s\r\n"
@@ -6873,19 +6897,13 @@ static void _iax2_show_peers_one(int fd, struct mansession *s, struct show_peers
                        ast_test_flag64(peer, IAX_TRUNK) ? "yes" : "no",
                        peer->encmethods ? ast_str_buffer(encmethods) : "no",
                        status);
-
                if (cont->peerlist) { /* IAXpeerlist */
-
                        astman_append(s, "\r\n");
-
                } else { /* IAXpeers */
-
                        astman_append(s,
                                "Description: %s\r\n\r\n",
                                peer->description);
-
                }
-
        } else {
                ast_cli(fd, PEERS_FORMAT,
                        name,
@@ -6900,7 +6918,6 @@ static void _iax2_show_peers_one(int fd, struct mansession *s, struct show_peers
        }
 
        cont->total_peers++;
-
 }
 
 static int __iax2_show_peers(int fd, int *total, struct mansession *s, const int argc, const char * const argv[])
@@ -7213,16 +7230,14 @@ static int manager_iax2_show_peers(struct mansession *s, const struct message *m
                snprintf(idtext, sizeof(idtext), "ActionID: %s\r\n", id);
 
        astman_send_listack(s, m, "Peer status list will follow", "start");
-        /* List the peers in separate manager events */
+
+       /* List the peers in separate manager events */
        __iax2_show_peers(-1, &total, s, 3, a);
-        /* Send final confirmation */
-        astman_append(s,
-        "Event: PeerlistComplete\r\n"
-        "EventList: Complete\r\n"
-        "ListItems: %d\r\n"
-        "%s"
-        "\r\n", total, idtext);
-        return 0;
+
+       /* Send final confirmation */
+       astman_send_list_complete_start(s, m, "PeerlistComplete", total);
+       astman_send_list_complete_end(s);
+       return 0;
 }
 
 /*! \brief callback to display iax peers in manager format */
@@ -7250,25 +7265,16 @@ static int manager_iax2_show_peer_list(struct mansession *s, const struct messag
                snprintf(cont.idtext, sizeof(cont.idtext), "ActionID: %s\r\n", id);
        }
 
-       astman_append(s,
-               "Response: Success\r\n"
-               "%sMessage: IAX Peer status list will follow\r\n\r\n",
-               cont.idtext);
-
+       astman_send_listack(s, m, "IAX Peer status list will follow", "start");
 
        i = ao2_iterator_init(peers, 0);
        for (; (peer = ao2_iterator_next(&i)); peer_unref(peer)) {
-
                _iax2_show_peers_one(-1, s, &cont, peer);
-
        }
        ao2_iterator_destroy(&i);
 
-       astman_append(s,
-               "Event: PeerlistComplete\r\n"
-               "%sListItems: %d\r\n\r\n",
-               cont.idtext,
-               cont.total_peers);
+       astman_send_list_complete_start(s, m, "PeerlistComplete", cont.total_peers);
+       astman_send_list_complete_end(s);
 
        return RESULT_SUCCESS;
 }
@@ -7373,12 +7379,8 @@ static int manager_iax2_show_registry(struct mansession *s, const struct message
        }
        AST_LIST_UNLOCK(&registrations);
 
-       astman_append(s,
-               "Event: RegistrationsComplete\r\n"
-               "EventList: Complete\r\n"
-               "ListItems: %d\r\n"
-               "%s"
-               "\r\n", total, idtext);
+       astman_send_list_complete_start(s, m, "RegistrationsComplete", total);
+       astman_send_list_complete_end(s);
 
        return 0;
 }
@@ -7814,8 +7816,10 @@ static int check_access(int callno, struct ast_sockaddr *addr, struct iax_ies *i
        /* Use provided preferences until told otherwise for actual preferences */
        if (ies->codec_prefs) {
                iax2_codec_pref_convert(&iaxs[callno]->rprefs, ies->codec_prefs, 32, 0);
-               iax2_codec_pref_convert(&iaxs[callno]->prefs, ies->codec_prefs, 32, 0);
+       } else {
+               memset(&iaxs[callno]->rprefs, 0, sizeof(iaxs[callno]->rprefs));
        }
+       iaxs[callno]->prefs = iaxs[callno]->rprefs;
 
        if (!gotcapability) {
                iaxs[callno]->peercapability = iaxs[callno]->peerformat;
@@ -7950,7 +7954,7 @@ static int check_access(int callno, struct ast_sockaddr *addr, struct iax_ies *i
                        iaxs[callno]->amaflags = user->amaflags;
                if (!ast_strlen_zero(user->language))
                        ast_string_field_set(iaxs[callno], language, user->language);
-               ast_copy_flags64(iaxs[callno], user, IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF | IAX_SENDCONNECTEDLINE | IAX_RECVCONNECTEDLINE);
+               ast_copy_flags64(iaxs[callno], user, IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_SENDCONNECTEDLINE | IAX_RECVCONNECTEDLINE);
                /* Keep this check last */
                if (!ast_strlen_zero(user->dbsecret)) {
                        char *family, *key=NULL;
@@ -8143,7 +8147,7 @@ static int authenticate_verify(struct chan_iax2_pvt *p, struct iax_ies *ies)
                        MD5Final(digest, &md5);
                        /* If they support md5, authenticate with it.  */
                        for (x=0;x<16;x++)
-                               sprintf(requeststr + (x << 1), "%2.2x", (unsigned)digest[x]); /* safe */
+                               sprintf(requeststr + (x << 1), "%02hhx", digest[x]); /* safe */
                        if (!strcasecmp(requeststr, md5secret)) {
                                res = 0;
                                break;
@@ -8275,7 +8279,7 @@ static int register_verify(int callno, struct ast_sockaddr *addr, struct iax_ies
                        MD5Update(&md5, (unsigned char *)tmppw, strlen(tmppw));
                        MD5Final(digest, &md5);
                        for (x=0;x<16;x++)
-                               sprintf(requeststr + (x << 1), "%2.2x", (unsigned)digest[x]); /* safe */
+                               sprintf(requeststr + (x << 1), "%02hhx", digest[x]); /* safe */
                        if (!strcasecmp(requeststr, md5secret))
                                break;
                }
@@ -8359,7 +8363,7 @@ static int authenticate(const char *challenge, const char *secret, const char *k
                        MD5Final(digest, &md5);
                        /* If they support md5, authenticate with it.  */
                        for (x=0;x<16;x++)
-                               sprintf(digres + (x << 1),  "%2.2x", (unsigned)digest[x]); /* safe */
+                               sprintf(digres + (x << 1),  "%02hhx", digest[x]); /* safe */
                        if (pvt) {
                                build_encryption_keys(digest, pvt);
                        }
@@ -8506,6 +8510,17 @@ static int iax2_do_register(struct iax2_registry *reg);
 static void __iax2_do_register_s(const void *data)
 {
        struct iax2_registry *reg = (struct iax2_registry *)data;
+
+       if (ast_sockaddr_isnull(&reg->addr)) {
+               reg->addr.ss.ss_family = AST_AF_UNSPEC;
+               ast_dnsmgr_lookup(reg->hostname, &reg->addr, &reg->dnsmgr, srvlookup ? "_iax._udp" : NULL);
+               if (!ast_sockaddr_port(&reg->addr)) {
+                       ast_sockaddr_set_port(&reg->addr, reg->port);
+               } else {
+                       reg->port = ast_sockaddr_port(&reg->addr);
+               }
+       }
+
        reg->expire = -1;
        iax2_do_register(reg);
 }
@@ -8738,8 +8753,9 @@ static int iax2_append_register(const char *hostname, const char *username,
 {
        struct iax2_registry *reg;
 
-       if (!(reg = ast_calloc(1, sizeof(*reg))))
+       if (!(reg = ast_calloc(1, sizeof(*reg) + strlen(hostname) + 1))) {
                return -1;
+       }
 
        reg->addr.ss.ss_family = AST_AF_UNSPEC;
        if (ast_dnsmgr_lookup(hostname, &reg->addr, &reg->dnsmgr, srvlookup ? "_iax._udp" : NULL) < 0) {
@@ -8748,13 +8764,24 @@ static int iax2_append_register(const char *hostname, const char *username,
        }
 
        ast_copy_string(reg->username, username, sizeof(reg->username));
+       strcpy(reg->hostname, hostname); /* Note: This is safe */
 
-       if (secret)
+       if (secret) {
                ast_copy_string(reg->secret, secret, sizeof(reg->secret));
+       }
 
        reg->expire = -1;
        reg->refresh = IAX_DEFAULT_REG_EXPIRE;
-       ast_sockaddr_set_port(&reg->addr, porta ? atoi(porta) : IAX_DEFAULT_PORTNO);
+
+       reg->port = ast_sockaddr_port(&reg->addr);
+
+       if (!porta && !reg->port) {
+               reg->port = IAX_DEFAULT_PORTNO;
+       } else if (porta) {
+               sscanf(porta, "%5d", &reg->port);
+       }
+
+       ast_sockaddr_set_port(&reg->addr, reg->port);
 
        AST_LIST_LOCK(&registrations);
        AST_LIST_INSERT_HEAD(&registrations, reg, entry);
@@ -10208,12 +10235,11 @@ static int socket_process_helper(struct iax2_thread *thread)
        }
 
        if (fr->callno > 0) {
-               struct ast_callid *mount_callid;
+               ast_callid mount_callid;
                ast_mutex_lock(&iaxsl[fr->callno]);
                if (iaxs[fr->callno] && ((mount_callid = iax_pvt_callid_get(fr->callno)))) {
                        /* Bind to thread */
                        ast_callid_threadassoc_add(mount_callid);
-                       ast_callid_unref(mount_callid);
                }
        }
 
@@ -10463,8 +10489,9 @@ static int socket_process_helper(struct iax2_thread *thread)
                    (f.frametype == AST_FRAME_IAX)) {
                        if (ast_test_flag64(iaxs[fr->callno], IAX_DELAYPBXSTART)) {
                                ast_clear_flag64(iaxs[fr->callno], IAX_DELAYPBXSTART);
-                               if (!ast_iax2_new(fr->callno, AST_STATE_RING, iaxs[fr->callno]->chosenformat, NULL, NULL,
-                                                 ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_AUTHENTICATED))) {
+                               if (!ast_iax2_new(fr->callno, AST_STATE_RING,
+                                       iaxs[fr->callno]->chosenformat, &iaxs[fr->callno]->rprefs, NULL, NULL,
+                                       ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_AUTHENTICATED))) {
                                        ast_variables_destroy(ies.vars);
                                        ast_mutex_unlock(&iaxsl[fr->callno]);
                                        return 1;
@@ -10758,7 +10785,7 @@ static int socket_process_helper(struct iax2_thread *thread)
                                                        } else
                                                                pref = iaxs[fr->callno]->prefs;
 
-                                                       format = iax2_codec_choose(&pref, iaxs[fr->callno]->capability & iaxs[fr->callno]->peercapability, 0);
+                                                       format = iax2_codec_choose(&pref, iaxs[fr->callno]->capability & iaxs[fr->callno]->peercapability);
                                                        iax2_codec_pref_string(&iaxs[fr->callno]->rprefs, caller_pref_buf, sizeof(caller_pref_buf) - 1);
                                                        iax2_codec_pref_string(&iaxs[fr->callno]->prefs, host_pref_buf, sizeof(host_pref_buf) - 1);
                                                }
@@ -10800,7 +10827,7 @@ static int socket_process_helper(struct iax2_thread *thread)
                                                                        if(ast_test_flag64(iaxs[fr->callno], IAX_CODEC_NOPREFS)) {
                                                                                using_prefs = ast_test_flag64(iaxs[fr->callno], IAX_CODEC_NOCAP) ? "reqonly" : "disabled";
                                                                                memset(&pref, 0, sizeof(pref));
-                                                                               format = iax2_best_codec(iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability);
+                                                                               format = iax2_format_compatibility_best(iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability);
                                                                                strcpy(caller_pref_buf,"disabled");
                                                                                strcpy(host_pref_buf,"disabled");
                                                                        } else {
@@ -10814,9 +10841,9 @@ static int socket_process_helper(struct iax2_thread *thread)
                                                                                                pref = iaxs[fr->callno]->rprefs;
                                                                                                using_prefs = "caller";
                                                                                        }
-                                                                                       format = iax2_codec_choose(&pref, iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability, 1);
+                                                                                       format = iax2_codec_choose(&pref, iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability);
                                                                                } else /* if no codec_prefs IE do it the old way */
-                                                                                       format = iax2_best_codec(iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability);
+                                                                                       format = iax2_format_compatibility_best(iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability);
                                                                        }
                                                                }
 
@@ -11018,7 +11045,9 @@ static int socket_process_helper(struct iax2_thread *thread)
                                                struct ast_str *cap_buf = ast_str_alloca(64);
 
                                                /* Switch us to use a compatible format */
-                                               iax2_format_compatibility_bitfield2cap(iaxs[fr->callno]->peerformat, native);
+                                               iax2_codec_pref_best_bitfield2cap(
+                                                       iaxs[fr->callno]->peerformat, &iaxs[fr->callno]->rprefs,
+                                                       native);
                                                ast_channel_nativeformats_set(iaxs[fr->callno]->owner, native);
                                                ast_verb(3, "Format for call is %s\n", ast_format_cap_get_names(ast_channel_nativeformats(iaxs[fr->callno]->owner), &cap_buf));
 
@@ -11212,7 +11241,7 @@ static int socket_process_helper(struct iax2_thread *thread)
                                                        }
                                                } else /* if no codec_prefs IE do it the old way */
                                                        pref = iaxs[fr->callno]->prefs;
-                                               format = iax2_codec_choose(&pref, iaxs[fr->callno]->capability & iaxs[fr->callno]->peercapability, 0);
+                                               format = iax2_codec_choose(&pref, iaxs[fr->callno]->capability & iaxs[fr->callno]->peercapability);
                                                iax2_codec_pref_string(&iaxs[fr->callno]->rprefs, caller_pref_buf, sizeof(caller_pref_buf) - 1);
                                                iax2_codec_pref_string(&iaxs[fr->callno]->prefs, host_pref_buf, sizeof(host_pref_buf) - 1);
                                        }
@@ -11258,8 +11287,9 @@ static int socket_process_helper(struct iax2_thread *thread)
                                                                if(ast_test_flag64(iaxs[fr->callno], IAX_CODEC_NOPREFS)) {
                                                                        using_prefs = ast_test_flag64(iaxs[fr->callno], IAX_CODEC_NOCAP) ? "reqonly" : "disabled";
                                                                        memset(&pref, 0, sizeof(pref));
-                                                                       format = ast_test_flag64(iaxs[fr->callno], IAX_CODEC_NOCAP) ?
-                                                                               iaxs[fr->callno]->peerformat : iax2_best_codec(iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability);
+                                                                       format = ast_test_flag64(iaxs[fr->callno], IAX_CODEC_NOCAP)
+                                                                               ? iaxs[fr->callno]->peerformat
+                                                                               : iax2_format_compatibility_best(iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability);
                                                                        strcpy(caller_pref_buf,"disabled");
                                                                        strcpy(host_pref_buf,"disabled");
                                                                } else {
@@ -11273,9 +11303,9 @@ static int socket_process_helper(struct iax2_thread *thread)
                                                                                        pref = iaxs[fr->callno]->rprefs;
                                                                                        using_prefs = "caller";
                                                                                }
-                                                                               format = iax2_codec_choose(&pref, iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability, 1);
+                                                                               format = iax2_codec_choose(&pref, iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability);
                                                                        } else /* if no codec_prefs IE do it the old way */
-                                                                               format = iax2_best_codec(iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability);
+                                                                               format = iax2_format_compatibility_best(iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability);
                                                                }
                                                        }
                                                        if (!format) {
@@ -11336,9 +11366,11 @@ static int socket_process_helper(struct iax2_thread *thread)
                                                                                        using_prefs);
 
                                                        ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED);
-                                                       if (!(c = ast_iax2_new(fr->callno, AST_STATE_RING, format, NULL, NULL, 1)))
+                                                       c = ast_iax2_new(fr->callno, AST_STATE_RING, format,
+                                                               &iaxs[fr->callno]->rprefs, NULL, NULL, 1);
+                                                       if (!c) {
                                                                iax2_destroy(fr->callno);
-                                                       else if (ies.vars) {
+                                                       } else if (ies.vars) {
                                                                struct ast_datastore *variablestore;
                                                                struct ast_variable *var, *prev = NULL;
                                                                AST_LIST_HEAD(, ast_var_t) *varlist;
@@ -11410,9 +11442,12 @@ immediatedial:
                                                                iax2_getformatname_multiple(iaxs[fr->callno]->peerformat, &cap_buf));
                                                ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED);
                                                send_command(iaxs[fr->callno], AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, 0, NULL, 0, -1);
-                                               if (!(c = ast_iax2_new(fr->callno, AST_STATE_RING, iaxs[fr->callno]->peerformat, NULL, NULL, 1)))
+                                               c = ast_iax2_new(fr->callno, AST_STATE_RING,
+                                                       iaxs[fr->callno]->peerformat, &iaxs[fr->callno]->rprefs,
+                                                       NULL, NULL, 1);
+                                               if (!c) {
                                                        iax2_destroy(fr->callno);
-                                               else if (ies.vars) {
+                                               } else if (ies.vars) {
                                                        struct ast_datastore *variablestore;
                                                        struct ast_variable *var, *prev = NULL;
                                                        AST_LIST_HEAD(, ast_var_t) *varlist;
@@ -11876,7 +11911,7 @@ immediatedial:
                if (iaxdebug && iaxs[fr->callno]) {
                        ast_debug(1, "Received out of order packet... (type=%u, subclass %d, ts = %u, last = %u)\n", f.frametype, f.subclass.integer, fr->ts, iaxs[fr->callno]->last);
                }
-               fr->outoforder = -1;
+               fr->outoforder = 1;
        }
        fr->cacheable = ((f.frametype == AST_FRAME_VOICE) || (f.frametype == AST_FRAME_VIDEO));
        if (iaxs[fr->callno]) {
@@ -11901,11 +11936,9 @@ immediatedial:
 
 static int socket_process(struct iax2_thread *thread)
 {
-       struct ast_callid *callid;
        int res = socket_process_helper(thread);
-       if ((callid = ast_read_threadstorage_callid())) {
+       if (ast_read_threadstorage_callid()) {
                ast_callid_threadassoc_remove();
-               callid = ast_callid_unref(callid);
        }
        return res;
 }
@@ -12100,6 +12133,9 @@ static int iax2_do_register(struct iax2_registry *reg)
                        (5 * reg->refresh / 6) * 1000, iax2_do_register_s, reg);
                return -1;
        }
+       if (!ast_sockaddr_port(&reg->addr) && reg->port) {
+               ast_sockaddr_set_port(&reg->addr, reg->port);
+       }
 
        if (!reg->callno) {
 
@@ -12300,6 +12336,7 @@ static int iax2_poke_peer_cb(void *obj, void *arg, int flags)
 static int iax2_poke_peer(struct iax2_peer *peer, int heldcall)
 {
        int callno;
+       int poke_timeout;
 
        if (!peer->maxms || (ast_sockaddr_isnull(&peer->addr) && !peer->dnsmgr)) {
                /* IF we have no IP without dnsmgr, or this isn't to be monitored, return
@@ -12323,15 +12360,11 @@ static int iax2_poke_peer(struct iax2_peer *peer, int heldcall)
        callno = peer->callno = find_callno(0, 0, &peer->addr, NEW_FORCE, peer->sockfd, 0);
        if (heldcall)
                ast_mutex_lock(&iaxsl[heldcall]);
-       if (peer->callno < 1) {
+       if (callno < 1) {
                ast_log(LOG_WARNING, "Unable to allocate call for poking peer '%s'\n", peer->name);
                return -1;
        }
 
-       /* Speed up retransmission times for this qualify call */
-       iaxs[peer->callno]->pingtime = peer->maxms / 4 + 1;
-       iaxs[peer->callno]->peerpoke = peer;
-
        if (peer->pokeexpire > -1) {
                if (!AST_SCHED_DEL(sched, peer->pokeexpire)) {
                        peer->pokeexpire = -1;
@@ -12339,12 +12372,24 @@ static int iax2_poke_peer(struct iax2_peer *peer, int heldcall)
                }
        }
 
+       if (peer->lastms < 0){
+               /* If the host is already unreachable then use time less than the unreachable
+                * interval. 5/6 is arbitrary multiplier to get value less than
+                * peer->pokefreqnotok. Value less than peer->pokefreqnotok is used to expire
+                * current POKE before starting new POKE (which is scheduled after
+                * peer->pokefreqnotok). */
+               poke_timeout = peer->pokefreqnotok * 5  / 6;
+       } else {
+               /* If the host is reachable, use timeout large enough to allow for multiple
+                * POKE retries. Limit this value to less than peer->pokefreqok. 5/6 is arbitrary
+                * multiplier to get value less than peer->pokefreqok. Value less than
+                * peer->pokefreqok is used to expire current POKE before starting new POKE
+                * (which is scheduled after peer->pokefreqok). */
+               poke_timeout = MIN(MAX_RETRY_TIME * 2 + peer->maxms, peer->pokefreqok * 5  / 6);
+       }
+
        /* Queue up a new task to handle no reply */
-       /* If the host is already unreachable then use the unreachable interval instead */
-       if (peer->lastms < 0)
-               peer->pokeexpire = iax2_sched_add(sched, peer->pokefreqnotok, iax2_poke_noanswer, peer_ref(peer));
-       else
-               peer->pokeexpire = iax2_sched_add(sched, DEFAULT_MAXMS * 2, iax2_poke_noanswer, peer_ref(peer));
+       peer->pokeexpire = iax2_sched_add(sched, poke_timeout, iax2_poke_noanswer, peer_ref(peer));
 
        if (peer->pokeexpire == -1)
                peer_unref(peer);
@@ -12356,6 +12401,11 @@ static int iax2_poke_peer(struct iax2_peer *peer, int heldcall)
                        .buf = { 0 },
                        .pos = 0,
                };
+
+               /* Speed up retransmission times for this qualify call */
+               iaxs[callno]->pingtime = peer->maxms / 8;
+               iaxs[callno]->peerpoke = peer;
+
                add_empty_calltoken_ie(iaxs[callno], &ied); /* this _MUST_ be the last ie added */
                send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_POKE, 0, ied.buf, ied.pos, -1);
        }
@@ -12383,7 +12433,7 @@ static struct ast_channel *iax2_request(const char *type, struct ast_format_cap
        struct parsed_dial_string pds;
        struct create_addr_info cai;
        char *tmpstr;
-       struct ast_callid *callid;
+       ast_callid callid;
 
        memset(&pds, 0, sizeof(pds));
        tmpstr = ast_strdupa(data);
@@ -12398,7 +12448,7 @@ static struct ast_channel *iax2_request(const char *type, struct ast_format_cap
        memset(&cai, 0, sizeof(cai));
        cai.capability = iax2_capability;
 
-       ast_copy_flags64(&cai, &globalflags, IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF | IAX_SENDCONNECTEDLINE | IAX_RECVCONNECTEDLINE);
+       ast_copy_flags64(&cai, &globalflags, IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_SENDCONNECTEDLINE | IAX_RECVCONNECTEDLINE);
 
        /* Populate our address from the given */
        if (create_addr(pds.peer, NULL, &addr, &cai)) {
@@ -12420,7 +12470,7 @@ static struct ast_channel *iax2_request(const char *type, struct ast_format_cap
        }
 
        /* If this is a trunk, update it now */
-       ast_copy_flags64(iaxs[callno], &cai, IAX_TRUNK | IAX_SENDANI | IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF | IAX_SENDCONNECTEDLINE | IAX_RECVCONNECTEDLINE);
+       ast_copy_flags64(iaxs[callno], &cai, IAX_TRUNK | IAX_SENDANI | IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_SENDCONNECTEDLINE | IAX_RECVCONNECTEDLINE);
        if (ast_test_flag64(&cai, IAX_TRUNK)) {
                int new_callno;
                if ((new_callno = make_trunk(callno, 1)) != -1)
@@ -12435,7 +12485,8 @@ static struct ast_channel *iax2_request(const char *type, struct ast_format_cap
                ast_string_field_set(iaxs[callno], host, pds.peer);
        }
 
-       c = ast_iax2_new(callno, AST_STATE_DOWN, cai.capability, assignedids, requestor, cai.found);
+       c = ast_iax2_new(callno, AST_STATE_DOWN, cai.capability, &cai.prefs, assignedids,
+               requestor, cai.found);
 
        ast_mutex_unlock(&iaxsl[callno]);
 
@@ -12460,16 +12511,18 @@ static struct ast_channel *iax2_request(const char *type, struct ast_format_cap
                if (!ast_format_cap_count(joint)) {
                        struct ast_format *best_fmt_cap = NULL;
                        struct ast_format *best_fmt_native = NULL;
+
                        res = ast_translator_best_choice(cap, ast_channel_nativeformats(c), &best_fmt_cap, &best_fmt_native);
                        if (res < 0) {
-                               struct ast_str *native_cap_buf = ast_str_alloca(64);
-                               struct ast_str *cap_buf = ast_str_alloca(64);
+                               struct ast_str *native_cap_buf = ast_str_alloca(256);
+                               struct ast_str *cap_buf = ast_str_alloca(256);
 
                                ast_log(LOG_WARNING, "Unable to create translator path for %s to %s on %s\n",
                                        ast_format_cap_get_names(ast_channel_nativeformats(c), &native_cap_buf),
                                        ast_format_cap_get_names(cap, &cap_buf),
                                        ast_channel_name(c));
                                ast_hangup(c);
+                               ao2_ref(joint, -1);
                                return NULL;
                        }
                        ast_format_cap_append(joint, best_fmt_native, 0);
@@ -12485,9 +12538,6 @@ static struct ast_channel *iax2_request(const char *type, struct ast_format_cap
                ao2_ref(format, -1);
        }
 
-       if (callid) {
-               ast_callid_unref(callid);
-       }
        return c;
 }
 
@@ -12737,7 +12787,7 @@ static struct iax2_peer *build_peer(const char *name, struct ast_variable *v, st
 
        if (peer) {
                if (firstpass) {
-                       ast_copy_flags64(peer, &globalflags, IAX_USEJITTERBUF | IAX_FORCEJITTERBUF | IAX_SENDCONNECTEDLINE | IAX_RECVCONNECTEDLINE | IAX_FORCE_ENCRYPT);
+                       ast_copy_flags64(peer, &globalflags, IAX_USEJITTERBUF | IAX_SENDCONNECTEDLINE | IAX_RECVCONNECTEDLINE | IAX_FORCE_ENCRYPT);
                        peer->encmethods = iax2_encryption;
                        peer->adsi = adsi;
                        ast_string_field_set(peer, secret, "");
@@ -12747,7 +12797,7 @@ static struct iax2_peer *build_peer(const char *name, struct ast_variable *v, st
                                ast_sockaddr_set_port(&peer->addr, IAX_DEFAULT_PORTNO);
                                peer->expiry = min_reg_expire;
                        }
-                       peer->prefs = prefs;
+                       peer->prefs = prefs_global;
                        peer->capability = iax2_capability;
                        peer->smoothing = 0;
                        peer->pokefreqok = DEFAULT_FREQ_OK;
@@ -12824,8 +12874,6 @@ static struct iax2_peer *build_peer(const char *name, struct ast_variable *v, st
                                        ast_set_flags_to64(peer, IAX_NOTRANSFER|IAX_TRANSFERMEDIA, IAX_NOTRANSFER);
                        } else if (!strcasecmp(v->name, "jitterbuffer")) {
                                ast_set2_flag64(peer, ast_true(v->value), IAX_USEJITTERBUF);
-                       } else if (!strcasecmp(v->name, "forcejitterbuffer")) {
-                               ast_set2_flag64(peer, ast_true(v->value), IAX_FORCEJITTERBUF);
                        } else if (!strcasecmp(v->name, "host")) {
                                if (!strcasecmp(v->value, "dynamic")) {
                                        /* They'll register with us */
@@ -12996,7 +13044,10 @@ static struct iax2_peer *build_peer(const char *name, struct ast_variable *v, st
 
                mailbox_specific_topic = ast_mwi_topic(peer->mailbox);
                if (mailbox_specific_topic) {
-                       peer->mwi_event_sub = stasis_subscribe(mailbox_specific_topic, mwi_event_cb, NULL);
+                       /* The MWI subscriptions exist just so the core knows we care about those
+                        * mailboxes.  However, we just grab the events out of the cache when it
+                        * is time to send MWI, since it is only sent with a REGACK. */
+                       peer->mwi_event_sub = stasis_subscribe_pool(mailbox_specific_topic, stasis_subscription_cb_noop, NULL);
                }
        }
 
@@ -13064,14 +13115,14 @@ static struct iax2_user *build_user(const char *name, struct ast_variable *v, st
                        }
                        user->maxauthreq = maxauthreq;
                        user->curauthreq = oldcurauthreq;
-                       user->prefs = prefs;
+                       user->prefs = prefs_global;
                        user->capability = iax2_capability;
                        user->encmethods = iax2_encryption;
                        user->adsi = adsi;
                        user->calltoken_required = CALLTOKEN_DEFAULT;
                        ast_string_field_set(user, name, name);
                        ast_string_field_set(user, language, language);
-                       ast_copy_flags64(user, &globalflags, IAX_USEJITTERBUF | IAX_FORCEJITTERBUF | IAX_CODEC_USER_FIRST | IAX_CODEC_NOPREFS | IAX_CODEC_NOCAP | IAX_SENDCONNECTEDLINE | IAX_RECVCONNECTEDLINE | IAX_FORCE_ENCRYPT);
+                       ast_copy_flags64(user, &globalflags, IAX_USEJITTERBUF | IAX_CODEC_USER_FIRST | IAX_CODEC_NOPREFS | IAX_CODEC_NOCAP | IAX_SENDCONNECTEDLINE | IAX_RECVCONNECTEDLINE | IAX_FORCE_ENCRYPT);
                        ast_clear_flag64(user, IAX_HASCALLERID);
                        ast_string_field_set(user, cid_name, "");
                        ast_string_field_set(user, cid_num, "");
@@ -13153,8 +13204,6 @@ static struct iax2_user *build_user(const char *name, struct ast_variable *v, st
                                ast_set2_flag64(user, ast_true(v->value), IAX_IMMEDIATE);
                        } else if (!strcasecmp(v->name, "jitterbuffer")) {
                                ast_set2_flag64(user, ast_true(v->value), IAX_USEJITTERBUF);
-                       } else if (!strcasecmp(v->name, "forcejitterbuffer")) {
-                               ast_set2_flag64(user, ast_true(v->value), IAX_FORCEJITTERBUF);
                        } else if (!strcasecmp(v->name, "dbsecret")) {
                                ast_string_field_set(user, dbsecret, v->value);
                        } else if (!strcasecmp(v->name, "secret")) {
@@ -13367,7 +13416,7 @@ static void set_config_destroy(void)
        amaflags = 0;
        delayreject = 0;
        ast_clear_flag64((&globalflags), IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF |
-               IAX_FORCEJITTERBUF | IAX_SENDCONNECTEDLINE | IAX_RECVCONNECTEDLINE);
+               IAX_SENDCONNECTEDLINE | IAX_RECVCONNECTEDLINE);
        delete_users();
        ao2_callback(callno_limits, OBJ_NODATA, addr_range_delme_cb, NULL);
        ao2_callback(calltoken_ignores, OBJ_NODATA, addr_range_delme_cb, NULL);
@@ -13377,7 +13426,7 @@ static void set_config_destroy(void)
 static int set_config(const char *config_file, int reload, int forced)
 {
        struct ast_config *cfg, *ucfg;
-       iax2_format capability = iax2_capability;
+       iax2_format capability;
        struct ast_variable *v;
        char *cat;
        const char *utype;
@@ -13392,9 +13441,7 @@ static int set_config(const char *config_file, int reload, int forced)
        struct ast_netsock *ns;
        struct ast_flags config_flags = { (reload && !forced) ? CONFIG_FLAG_FILEUNCHANGED : 0 };
        struct ast_sockaddr bindaddr;
-#if 0
-       static unsigned short int last_port=0;
-#endif
+       struct iax2_codec_pref prefs_new;
 
        cfg = ast_config_load(config_file, config_flags);
 
@@ -13435,8 +13482,8 @@ static int set_config(const char *config_file, int reload, int forced)
 
        ast_sockaddr_parse(&bindaddr, "0.0.0.0:0", 0);
 
-       /* Reset global codec prefs */
-       memset(&prefs, 0 , sizeof(struct iax2_codec_pref));
+       /* Setup new codec prefs */
+       capability = iax2_codec_pref_from_bitfield(&prefs_new, IAX_CAPABILITY_FULLBANDWIDTH);
 
        /* Reset Global Flags */
        memset(&globalflags, 0, sizeof(globalflags));
@@ -13600,8 +13647,6 @@ static int set_config(const char *config_file, int reload, int forced)
                        }
                } else if (!strcasecmp(v->name, "jitterbuffer"))
                        ast_set2_flag64((&globalflags), ast_true(v->value), IAX_USEJITTERBUF);
-               else if (!strcasecmp(v->name, "forcejitterbuffer"))
-                       ast_set2_flag64((&globalflags), ast_true(v->value), IAX_FORCEJITTERBUF);
                else if (!strcasecmp(v->name, "delayreject"))
                        delayreject = ast_true(v->value);
                else if (!strcasecmp(v->name, "allowfwdownload"))
@@ -13661,17 +13706,21 @@ static int set_config(const char *config_file, int reload, int forced)
                        }
                } else if (!strcasecmp(v->name, "bandwidth")) {
                        if (!strcasecmp(v->value, "low")) {
-                               capability = IAX_CAPABILITY_LOWBANDWIDTH;
+                               capability = iax2_codec_pref_from_bitfield(&prefs_new,
+                                       IAX_CAPABILITY_LOWBANDWIDTH);
                        } else if (!strcasecmp(v->value, "medium")) {
-                               capability = IAX_CAPABILITY_MEDBANDWIDTH;
+                               capability = iax2_codec_pref_from_bitfield(&prefs_new,
+                                       IAX_CAPABILITY_MEDBANDWIDTH);
                        } else if (!strcasecmp(v->value, "high")) {
-                               capability = IAX_CAPABILITY_FULLBANDWIDTH;
-                       } else
+                               capability = iax2_codec_pref_from_bitfield(&prefs_new,
+                                       IAX_CAPABILITY_FULLBANDWIDTH);
+                       } else {
                                ast_log(LOG_WARNING, "bandwidth must be either low, medium, or high\n");
+                       }
                } else if (!strcasecmp(v->name, "allow")) {
-                       iax2_parse_allow_disallow(&prefs, &capability, v->value, 1);
+                       iax2_parse_allow_disallow(&prefs_new, &capability, v->value, 1);
                } else if (!strcasecmp(v->name, "disallow")) {
-                       iax2_parse_allow_disallow(&prefs, &capability, v->value, 0);
+                       iax2_parse_allow_disallow(&prefs_new, &capability, v->value, 0);
                } else if (!strcasecmp(v->name, "register")) {
                        iax2_register(v->value, v->lineno);
                } else if (!strcasecmp(v->name, "iaxcompat")) {
@@ -13734,8 +13783,17 @@ static int set_config(const char *config_file, int reload, int forced)
                } else if (!strcasecmp(v->name, "calltokenoptional")) {
                        if (add_calltoken_ignore(v->value)) {
                                ast_log(LOG_WARNING, "Invalid calltokenoptional address range - '%s' line %d\n", v->value, v->lineno);
+                               return -1;
+                       }
+               } else if (!strcasecmp(v->name, "calltokenexpiration")) {
+                       int temp = -1;
+                       sscanf(v->value, "%u", &temp);
+                       if( temp <= 0 ){
+                               ast_log(LOG_WARNING, "Invalid calltokenexpiration value %s. Should be integer greater than 0.\n", v->value);
+                       } else {
+                               max_calltoken_delay = temp;
                        }
-               } else if (!strcasecmp(v->name, "subscribe_network_change_event")) {
+               }  else if (!strcasecmp(v->name, "subscribe_network_change_event")) {
                        if (ast_true(v->value)) {
                                subscribe_network_change = 1;
                        } else if (ast_false(v->value)) {
@@ -13789,6 +13847,7 @@ static int set_config(const char *config_file, int reload, int forced)
                        min_reg_expire, max_reg_expire, max_reg_expire);
                min_reg_expire = max_reg_expire;
        }
+       prefs_global = prefs_new;
        iax2_capability = capability;
 
        if (ucfg) {
@@ -14315,7 +14374,7 @@ static int function_iaxpeer(struct ast_channel *chan, const char *cmd, char *dat
        } else  if (!strcasecmp(colname, "callerid_num")) {
                ast_copy_string(buf, peer->cid_num, len);
        } else  if (!strcasecmp(colname, "codecs")) {
-               struct ast_str *codec_buf;
+               struct ast_str *codec_buf = ast_str_alloca(256);
 
                iax2_getformatname_multiple(peer->capability, &codec_buf);
                ast_copy_string(buf, ast_str_buffer(codec_buf), len);
@@ -14608,7 +14667,6 @@ static void cleanup_thread_list(void *head)
 
 static int __unload_module(void)
 {
-       struct ast_context *con;
        int x;
 
        network_change_stasis_unsubscribe();
@@ -14672,7 +14730,6 @@ static int __unload_module(void)
        ao2_ref(users, -1);
        ao2_ref(iax_peercallno_pvts, -1);
        ao2_ref(iax_transfercallno_pvts, -1);
-       ao2_ref(peercnts, -1);
        ao2_ref(callno_limits, -1);
        ao2_ref(calltoken_ignores, -1);
        if (timer) {
@@ -14680,12 +14737,13 @@ static int __unload_module(void)
                timer = NULL;
        }
        transmit_processor = ast_taskprocessor_unreference(transmit_processor);
+
+       ast_sched_clean_by_callback(sched, peercnt_remove_cb, peercnt_remove_cb);
        ast_sched_context_destroy(sched);
        sched = NULL;
+       ao2_ref(peercnts, -1);
 
-       con = ast_context_find(regcontext);
-       if (con)
-               ast_context_destroy(con, "IAX2");
+       ast_context_destroy_by_name(regcontext, "IAX2");
        ast_unload_realtime("iaxpeers");
 
        ao2_ref(iax2_tech.capabilities, -1);
@@ -15126,9 +15184,10 @@ static int load_module(void)
 }
 
 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "Inter Asterisk eXchange (Ver 2)",
-               .load = load_module,
-               .unload = unload_module,
-               .reload = reload,
-               .load_pri = AST_MODPRI_CHANNEL_DRIVER,
-               .nonoptreq = "res_crypto",
-               );
+       .support_level = AST_MODULE_SUPPORT_CORE,
+       .load = load_module,
+       .unload = unload_module,
+       .reload = reload,
+       .load_pri = AST_MODPRI_CHANNEL_DRIVER,
+       .nonoptreq = "res_crypto",
+);