Index: channels/chan_iax2.c =================================================================== --- channels/chan_iax2.c (revision 80048) +++ channels/chan_iax2.c (working copy) @@ -2913,7 +2913,7 @@ char mohsuggest[MAX_MUSICCLASS]; }; -static int create_addr(const char *peername, struct sockaddr_in *sin, struct create_addr_info *cai) +static int create_addr(const char *peername, struct ast_channel *c, struct sockaddr_in *sin, struct create_addr_info *cai) { struct iax2_peer *peer; @@ -2921,6 +2921,7 @@ cai->sockfd = defaultsockfd; cai->maxtime = 0; sin->sin_family = AF_INET; + struct ast_codec_pref ourprefs; if (!(peer = find_peer(peername, 1))) { cai->found = 0; @@ -2930,7 +2931,11 @@ } sin->sin_port = htons(IAX_DEFAULT_PORTNO); /* use global iax prefs for unknown peer/user */ - ast_codec_pref_convert(&prefs, cai->prefs, sizeof(cai->prefs), 1); + /* But move the calling channel's native codec to the top of the preference list */ + memcpy(&ourprefs, &prefs, sizeof(ourprefs)); + if (c) + ast_codec_pref_prepend(&ourprefs, c->nativeformats, 1); + ast_codec_pref_convert(&ourprefs, cai->prefs, sizeof(cai->prefs), 1); return 0; } @@ -2956,7 +2961,13 @@ cai->encmethods = peer->encmethods; cai->sockfd = peer->sockfd; cai->adsi = peer->adsi; - ast_codec_pref_convert(&peer->prefs, cai->prefs, sizeof(cai->prefs), 1); + memcpy(&ourprefs, &peer->prefs, sizeof(ourprefs)); + /* Move the calling channel's native codec to the top of the preference list */ + if (c) { + ast_log(LOG_DEBUG, "prepending %x to prefs\n", c->nativeformats); + ast_codec_pref_prepend(&ourprefs, c->nativeformats, 1); + } + ast_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)); @@ -3134,7 +3145,7 @@ if (!pds.exten) pds.exten = defaultrdest; - if (create_addr(pds.peer, &sin, &cai)) { + if (create_addr(pds.peer, c, &sin, &cai)) { ast_log(LOG_WARNING, "No address associated with '%s'\n", pds.peer); return -1; } @@ -8806,7 +8817,7 @@ if (end) { memcpy(&sin, end, sizeof(sin)); cai.sockfd = sockfd; - } else if (create_addr(dest, &sin, &cai)) + } else if (create_addr(dest, NULL, &sin, &cai)) return -1; /* Build the rest of the message */ @@ -9007,7 +9018,7 @@ /* Populate our address from the given */ - if (create_addr(pds.peer, &sin, &cai)) { + if (create_addr(pds.peer, NULL, &sin, &cai)) { *cause = AST_CAUSE_UNREGISTERED; return NULL; } @@ -10378,7 +10389,7 @@ parse_dial_string(tmpstr, &pds); /* Populate our address from the given */ - if (create_addr(pds.peer, &sin, &cai)) + if (create_addr(pds.peer, NULL, &sin, &cai)) return -1; ast_debug(1, "peer: %s, username: %s, password: %s, context: %s\n", Index: main/frame.c =================================================================== --- main/frame.c (revision 80048) +++ main/frame.c (working copy) @@ -1024,7 +1024,7 @@ /*! \brief Append codec to list */ int ast_codec_pref_append(struct ast_codec_pref *pref, int format) { - int x, newindex = -1; + int x, newindex = 0; ast_codec_pref_remove(pref, format); @@ -1047,7 +1047,44 @@ return x; } +/*! \brief Prepend codec to list */ +void ast_codec_pref_prepend(struct ast_codec_pref *pref, int format, int only_if_existing) +{ + int x, newindex = 0; + /* First step is to get the codecs "index number" */ + for (x = 0; x < sizeof(AST_FORMAT_LIST) / sizeof(AST_FORMAT_LIST[0]); x++) { + if (AST_FORMAT_LIST[x].bits == format) { + newindex = x + 1; + break; + } + } + /* Done if its unknown */ + if (newindex == 0) + return; + + /* Now find any existing occurrence, or the end */ + for (x = 0; x < 32; x++) { + if (pref->order[x] == 0 || pref->order[x] == newindex) + break; + } + + if (only_if_existing && (pref->order[x] == 0)) + return; + + /* Move down to make space to insert - either all the way to the end, + or as far as the existing location (which will be overwritten) */ + for (; x > 0; x--) { + pref->order[x] = pref->order[x-1]; + pref->framing[x] = pref->framing[x-1]; + } + + /* And insert the new entry */ + pref->order[0] = newindex; + pref->framing[0] = 0; /* ? */ +} + + /*! \brief Set packet size for codec */ int ast_codec_pref_setsize(struct ast_codec_pref *pref, int format, int framems) { Index: include/asterisk/frame.h =================================================================== --- include/asterisk/frame.h (revision 80048) +++ include/asterisk/frame.h (working copy) @@ -527,6 +527,10 @@ */ int ast_codec_pref_append(struct ast_codec_pref *pref, int format); +/*! \brief Prepend an audio codec to a preference list, removing it first if it was already there +*/ +void ast_codec_pref_prepend(struct ast_codec_pref *pref, int format, int only_if_existing); + /*! \brief Select the best audio format according to preference list from supplied options. If "find_best" is non-zero then if nothing is found, the "Best" format of the format list is selected, otherwise 0 is returned. */