summaryrefslogtreecommitdiff
path: root/channels/chan_iax2.c
diff options
context:
space:
mode:
Diffstat (limited to 'channels/chan_iax2.c')
-rw-r--r--channels/chan_iax2.c268
1 files changed, 123 insertions, 145 deletions
diff --git a/channels/chan_iax2.c b/channels/chan_iax2.c
index 831f2c266..630a66342 100644
--- a/channels/chan_iax2.c
+++ b/channels/chan_iax2.c
@@ -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 */
@@ -1820,16 +1820,20 @@ static struct ast_format *codec_choose_from_prefs(struct iax2_codec_pref *pref,
int x;
struct ast_format *found_format = NULL;
- for (x = 0; x < IAX2_CODEC_PREF_SIZE; x++) {
+ for (x = 0; x < ARRAY_LEN(pref->order); ++x) {
struct ast_format *pref_format;
- uint64_t pref_as_bitfield = iax2_codec_pref_order_value_to_format_bitfield(pref->order[x]);
+ uint64_t pref_bitfield;
- if (!pref_as_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_as_bitfield);
-
+ 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;
@@ -1867,61 +1871,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)
-{
- /* This just our opinion, expressed in code. We are asked to choose
- the best codec to use, given no information */
- static const iax2_format prefs[] =
- {
- /*! Okay, ulaw is used by all telephony equipment, so start with it */
- AST_FORMAT_ULAW,
- /*! Unless of course, you're a silly European, so then prefer ALAW */
- AST_FORMAT_ALAW,
- AST_FORMAT_G719,
- AST_FORMAT_SIREN14,
- AST_FORMAT_SIREN7,
- AST_FORMAT_TESTLAW,
- /*! G.722 is better then all below, but not as common as the above... so give ulaw and alaw priority */
- AST_FORMAT_G722,
- /*! Okay, well, signed linear is easy to translate into other stuff */
- AST_FORMAT_SLIN16,
- AST_FORMAT_SLIN,
- /*! G.726 is standard ADPCM, in RFC3551 packing order */
- AST_FORMAT_G726,
- /*! G.726 is standard ADPCM, in AAL2 packing order */
- AST_FORMAT_G726_AAL2,
- /*! ADPCM has great sound quality and is still pretty easy to translate */
- AST_FORMAT_ADPCM,
- /*! Okay, we're down to vocoders now, so pick GSM because it's small and easier to
- translate and sounds pretty good */
- AST_FORMAT_GSM,
- /*! iLBC is not too bad */
- AST_FORMAT_ILBC,
- /*! Speex is free, but computationally more expensive than GSM */
- AST_FORMAT_SPEEX16,
- AST_FORMAT_SPEEX,
- /*! Opus */
- AST_FORMAT_OPUS,
- /*! Ick, LPC10 sounds terrible, but at least we have code for it, if you're tacky enough
- to use it */
- AST_FORMAT_LPC10,
- /*! G.729a is faster than 723 and slightly less expensive */
- AST_FORMAT_G729,
- /*! Down to G.723.1 which is proprietary but at least designed for voice */
- AST_FORMAT_G723,
- };
- int x;
-
- /* Find the first preferred codec in the format given */
- for (x = 0; x < ARRAY_LEN(prefs); x++) {
- if (formats & prefs[x]) {
- return prefs[x];
- }
- }
-
- return 0;
-}
-
const char *iax2_getformatname(iax2_format format)
{
struct ast_format *tmpfmt;
@@ -1951,33 +1900,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);
}
@@ -2283,7 +2223,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;
@@ -3844,7 +3784,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;
@@ -3895,17 +3835,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);
@@ -4654,6 +4592,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;
@@ -4663,7 +4602,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];
@@ -4676,7 +4614,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;
@@ -4697,20 +4634,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;
}
@@ -4731,7 +4672,7 @@ static int create_addr(const char *peername, struct ast_channel *c, struct ast_s
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;
@@ -4739,11 +4680,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));
@@ -5150,6 +5092,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)) {
@@ -5218,7 +5161,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);
@@ -5877,7 +5821,9 @@ 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 = NULL;
struct chan_iax2_pvt *i;
@@ -5893,10 +5839,22 @@ static struct ast_channel *ast_iax2_new(int callno, int state, iax2_format capab
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);
@@ -5910,13 +5868,17 @@ static struct ast_channel *ast_iax2_new(int callno, int state, iax2_format capab
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);
+ 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);
+ 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]);
@@ -5945,9 +5907,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);
@@ -6046,8 +6007,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;
}
}
@@ -7907,8 +7870,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;
@@ -10556,8 +10521,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;
@@ -10893,7 +10859,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 {
@@ -10909,7 +10875,7 @@ static int socket_process_helper(struct iax2_thread *thread)
}
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);
}
}
@@ -11111,7 +11077,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));
@@ -11351,8 +11319,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 {
@@ -11368,7 +11337,7 @@ static int socket_process_helper(struct iax2_thread *thread)
}
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) {
@@ -11429,9 +11398,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;
@@ -11503,9 +11474,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;
@@ -12528,7 +12502,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]);
@@ -12840,7 +12815,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;
@@ -13157,7 +13132,7 @@ 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;
@@ -13470,7 +13445,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;
@@ -13485,9 +13460,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);
@@ -13528,8 +13501,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));
@@ -13754,17 +13727,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")) {
@@ -13882,6 +13859,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) {
@@ -14408,7 +14386,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);