summaryrefslogtreecommitdiff
path: root/channels/chan_sip.c
diff options
context:
space:
mode:
Diffstat (limited to 'channels/chan_sip.c')
-rw-r--r--channels/chan_sip.c627
1 files changed, 379 insertions, 248 deletions
diff --git a/channels/chan_sip.c b/channels/chan_sip.c
index d5ee01345..e80f387cc 100644
--- a/channels/chan_sip.c
+++ b/channels/chan_sip.c
@@ -1199,7 +1199,7 @@ static struct ast_config *notify_types = NULL; /*!< The list of manual NOTIFY
in coming releases. */
/*--- PBX interface functions */
-static struct ast_channel *sip_request_call(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause);
+static struct ast_channel *sip_request_call(const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor, void *data, int *cause);
static int sip_devicestate(void *data);
static int sip_sendtext(struct ast_channel *ast, const char *text);
static int sip_call(struct ast_channel *ast, char *dest, int timeout);
@@ -1291,7 +1291,7 @@ static int process_sdp_a_audio(const char *a, struct sip_pvt *p, struct ast_rtp_
static int process_sdp_a_video(const char *a, struct sip_pvt *p, struct ast_rtp_codecs *newvideortp, int *last_rtpmap_codec);
static int process_sdp_a_text(const char *a, struct sip_pvt *p, struct ast_rtp_codecs *newtextrtp, char *red_fmtp, int *red_num_gen, int *red_data_pt, int *last_rtpmap_codec);
static int process_sdp_a_image(const char *a, struct sip_pvt *p);
-static void add_codec_to_sdp(const struct sip_pvt *p, format_t codec,
+static void add_codec_to_sdp(const struct sip_pvt *p, struct ast_format *codec,
struct ast_str **m_buf, struct ast_str **a_buf,
int debug, int *min_packet_size);
static void add_noncodec_to_sdp(const struct sip_pvt *p, int format,
@@ -1565,7 +1565,7 @@ static enum st_mode st_get_mode(struct sip_pvt *);
static struct sip_st_dlg* sip_st_alloc(struct sip_pvt *const p);
/*------- RTP Glue functions -------- */
-static int sip_set_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance *instance, struct ast_rtp_instance *vinstance, struct ast_rtp_instance *tinstance, format_t codecs, int nat_active);
+static int sip_set_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance *instance, struct ast_rtp_instance *vinstance, struct ast_rtp_instance *tinstance, const struct ast_format_cap *cap, int nat_active);
/*!--- SIP MWI Subscription support */
static int sip_subscribe_mwi(const char *value, int lineno);
@@ -1575,10 +1575,9 @@ static int sip_subscribe_mwi_do(const void *data);
static int __sip_subscribe_mwi_do(struct sip_subscription_mwi *mwi);
/*! \brief Definition of this channel for PBX channel registration */
-const struct ast_channel_tech sip_tech = {
+struct ast_channel_tech sip_tech = {
.type = "SIP",
.description = "Session Initiation Protocol (SIP)",
- .capabilities = AST_FORMAT_AUDIO_MASK, /* all audio formats */
.properties = AST_CHAN_TP_WANTSJITTER | AST_CHAN_TP_CREATESJITTER,
.requester = sip_request_call, /* called with chan unlocked */
.devicestate = sip_devicestate, /* called with chan unlocked (not chan-specific) */
@@ -4038,10 +4037,10 @@ static int sip_setoption(struct ast_channel *chan, int option, void *data, int d
switch (option) {
case AST_OPTION_FORMAT_READ:
- res = ast_rtp_instance_set_read_format(p->rtp, *(int *) data);
+ res = ast_rtp_instance_set_read_format(p->rtp, (struct ast_format *) data);
break;
case AST_OPTION_FORMAT_WRITE:
- res = ast_rtp_instance_set_write_format(p->rtp, *(int *) data);
+ res = ast_rtp_instance_set_write_format(p->rtp, (struct ast_format *) data);
break;
case AST_OPTION_MAKE_COMPATIBLE:
res = ast_rtp_instance_make_compatible(chan, p->rtp, (struct ast_channel *) data);
@@ -4385,6 +4384,8 @@ static void sip_destroy_peer(struct sip_peer *peer)
ast_cc_config_params_destroy(peer->cc_params);
ast_string_field_free_memory(peer);
+
+ peer->caps = ast_format_cap_destroy(peer->caps);
}
/*! \brief Update peer data in database (if used) */
@@ -4826,7 +4827,7 @@ static int dialog_initialize_rtp(struct sip_pvt *dialog)
}
if (ast_test_flag(&dialog->flags[1], SIP_PAGE2_VIDEOSUPPORT_ALWAYS) ||
- (ast_test_flag(&dialog->flags[1], SIP_PAGE2_VIDEOSUPPORT) && (dialog->capability & AST_FORMAT_VIDEO_MASK))) {
+ (ast_test_flag(&dialog->flags[1], SIP_PAGE2_VIDEOSUPPORT) && (ast_format_cap_has_type(dialog->caps, AST_FORMAT_TYPE_VIDEO)))) {
if (!(dialog->vrtp = ast_rtp_instance_new(dialog->engine, sched, &bindaddr_tmp, NULL))) {
return -1;
}
@@ -4887,7 +4888,7 @@ static int create_addr_from_peer(struct sip_pvt *dialog, struct sip_peer *peer)
ast_copy_flags(&dialog->flags[0], &peer->flags[0], SIP_FLAGS_TO_COPY);
ast_copy_flags(&dialog->flags[1], &peer->flags[1], SIP_PAGE2_FLAGS_TO_COPY);
ast_copy_flags(&dialog->flags[2], &peer->flags[2], SIP_PAGE3_FLAGS_TO_COPY);
- dialog->capability = peer->capability;
+ ast_format_cap_append(dialog->caps, peer->caps);
dialog->prefs = peer->prefs;
if (ast_test_flag(&dialog->flags[1], SIP_PAGE2_T38SUPPORT)) {
/* t38pt_udptl was enabled in the peer and not in [general] */
@@ -5253,11 +5254,11 @@ static int sip_call(struct ast_channel *ast, char *dest, int timeout)
return res;
}
p->callingpres = ast_party_id_presentation(&ast->caller.id);
- p->jointcapability = ast_rtp_instance_available_formats(p->rtp, p->capability, p->prefcodec);
+ ast_rtp_instance_available_formats(p->rtp, p->caps, p->prefcaps, p->jointcaps);
p->jointnoncodeccapability = p->noncodeccapability;
/* If there are no audio formats left to offer, punt */
- if (!(p->jointcapability & AST_FORMAT_AUDIO_MASK)) {
+ if (!(ast_format_cap_has_type(p->jointcaps, AST_FORMAT_TYPE_AUDIO))) {
ast_log(LOG_WARNING, "No audio format found to offer. Cancelling call to %s\n", p->username);
res = -1;
} else {
@@ -5463,6 +5464,11 @@ void __sip_destroy(struct sip_pvt *p, int lockowner, int lockdialoglist)
ao2_ref(p->socket.tcptls_session, -1);
p->socket.tcptls_session = NULL;
}
+ p->caps = ast_format_cap_destroy(p->caps);
+ p->jointcaps = ast_format_cap_destroy(p->jointcaps);
+ p->peercaps = ast_format_cap_destroy(p->peercaps);
+ p->redircaps = ast_format_cap_destroy(p->redircaps);
+ p->prefcaps = ast_format_cap_destroy(p->prefcaps);
}
/*! \brief update_call_counter: Handle call_limit for SIP devices
@@ -6025,9 +6031,11 @@ static int sip_hangup(struct ast_channel *ast)
/*! \brief Try setting codec suggested by the SIP_CODEC channel variable */
static void try_suggested_sip_codec(struct sip_pvt *p)
{
- format_t fmt;
+ struct ast_format fmt;
const char *codec;
+ ast_format_clear(&fmt);
+
if (p->outgoing_call) {
codec = pbx_builtin_getvar_helper(p->owner, "SIP_CODEC_OUTBOUND");
} else if (!(codec = pbx_builtin_getvar_helper(p->owner, "SIP_CODEC_INBOUND"))) {
@@ -6037,12 +6045,12 @@ static void try_suggested_sip_codec(struct sip_pvt *p)
if (!codec)
return;
- fmt = ast_getformatbyname(codec);
- if (fmt) {
+ ast_getformatbyname(codec, &fmt);
+ if (fmt.id) {
ast_log(LOG_NOTICE, "Changing codec to '%s' for this call because of ${SIP_CODEC} variable\n", codec);
- if (p->jointcapability & fmt) {
- p->jointcapability &= fmt;
- p->capability &= fmt;
+ if (ast_format_cap_iscompatible(p->jointcaps, &fmt)) {
+ ast_format_cap_set(p->jointcaps, &fmt);
+ ast_format_cap_set(p->caps, &fmt);
} else
ast_log(LOG_NOTICE, "Ignoring ${SIP_CODEC} variable because it is not shared by both ends.\n");
} else
@@ -6079,13 +6087,13 @@ static int sip_write(struct ast_channel *ast, struct ast_frame *frame)
switch (frame->frametype) {
case AST_FRAME_VOICE:
- if (!(frame->subclass.codec & ast->nativeformats)) {
- char s1[512], s2[512], s3[512];
+ if (!(ast_format_cap_iscompatible(ast->nativeformats, &frame->subclass.format))) {
+ char s1[512];
ast_log(LOG_WARNING, "Asked to transmit frame type %s, while native formats is %s read/write = %s/%s\n",
- ast_getformatname(frame->subclass.codec),
- ast_getformatname_multiple(s1, sizeof(s1), ast->nativeformats & AST_FORMAT_AUDIO_MASK),
- ast_getformatname_multiple(s2, sizeof(s2), ast->readformat),
- ast_getformatname_multiple(s3, sizeof(s3), ast->writeformat));
+ ast_getformatname(&frame->subclass.format),
+ ast_getformatname_multiple(s1, sizeof(s1), ast->nativeformats),
+ ast_getformatname(&ast->readformat),
+ ast_getformatname(&ast->writeformat));
return 0;
}
if (p) {
@@ -6538,11 +6546,9 @@ static struct ast_channel *sip_new(struct sip_pvt *i, int state, const char *tit
{
struct ast_channel *tmp;
struct ast_variable *v = NULL;
- format_t fmt;
- format_t what;
- format_t video;
- format_t text;
- format_t needvideo = 0;
+ struct ast_format fmt;
+ struct ast_format_cap *what = NULL; /* SHALLOW COPY DO NOT DESTROY! */
+ int needvideo = 0;
int needtext = 0;
char buf[SIPBUFSIZE];
char *decoded_exten;
@@ -6575,51 +6581,47 @@ static struct ast_channel *sip_new(struct sip_pvt *i, int state, const char *tit
/* Select our native format based on codec preference until we receive
something from another device to the contrary. */
- if (i->jointcapability) { /* The joint capabilities of us and peer */
- what = i->jointcapability;
- video = i->jointcapability & AST_FORMAT_VIDEO_MASK;
- text = i->jointcapability & AST_FORMAT_TEXT_MASK;
- } else if (i->capability) { /* Our configured capability for this peer */
- what = i->capability;
- video = i->capability & AST_FORMAT_VIDEO_MASK;
- text = i->capability & AST_FORMAT_TEXT_MASK;
+ if (!(ast_format_cap_is_empty(i->jointcaps))) { /* The joint capabilities of us and peer */
+ what = i->jointcaps;
+ } else if (!(ast_format_cap_is_empty(i->caps))) { /* Our configured capability for this peer */
+ what = i->caps;
} else {
- what = sip_cfg.capability; /* Global codec support */
- video = sip_cfg.capability & AST_FORMAT_VIDEO_MASK;
- text = sip_cfg.capability & AST_FORMAT_TEXT_MASK;
+ what = sip_cfg.caps;
}
- /* Set the native formats for audio and merge in video */
- tmp->nativeformats = ast_codec_choose(&i->prefs, what, 1) | video | text;
+ /* Set the native formats */
+ ast_format_cap_copy(tmp->nativeformats, what);
+ /* choose and use only the best audio format for our native formats */
+ ast_codec_choose(&i->prefs, tmp->nativeformats, 1, &fmt); /* get the best audio format */
+ ast_format_cap_remove_bytype(tmp->nativeformats, AST_FORMAT_TYPE_AUDIO); /* remove only the other audio formats */
+ ast_format_cap_add(tmp->nativeformats, &fmt); /* add our best choice back */
+
ast_debug(3, "*** Our native formats are %s \n", ast_getformatname_multiple(buf, SIPBUFSIZE, tmp->nativeformats));
- ast_debug(3, "*** Joint capabilities are %s \n", ast_getformatname_multiple(buf, SIPBUFSIZE, i->jointcapability));
- ast_debug(3, "*** Our capabilities are %s \n", ast_getformatname_multiple(buf, SIPBUFSIZE, i->capability));
- ast_debug(3, "*** AST_CODEC_CHOOSE formats are %s \n", ast_getformatname_multiple(buf, SIPBUFSIZE, ast_codec_choose(&i->prefs, what, 1)));
- if (i->prefcodec) {
- ast_debug(3, "*** Our preferred formats from the incoming channel are %s \n", ast_getformatname_multiple(buf, SIPBUFSIZE, i->prefcodec));
+ ast_debug(3, "*** Joint capabilities are %s \n", ast_getformatname_multiple(buf, SIPBUFSIZE, i->jointcaps));
+ ast_debug(3, "*** Our capabilities are %s \n", ast_getformatname_multiple(buf, SIPBUFSIZE, i->caps));
+ ast_debug(3, "*** AST_CODEC_CHOOSE formats are %s \n", ast_getformatname(&fmt));
+ if (!ast_format_cap_is_empty(i->prefcaps)) {
+ ast_debug(3, "*** Our preferred formats from the incoming channel are %s \n", ast_getformatname_multiple(buf, SIPBUFSIZE, i->prefcaps));
}
- /* XXX Why are we choosing a codec from the native formats?? */
- fmt = ast_best_codec(tmp->nativeformats);
-
/* If we have a prefcodec setting, we have an inbound channel that set a
preferred format for this call. Otherwise, we check the jointcapability
We also check for vrtp. If it's not there, we are not allowed do any video anyway.
*/
if (i->vrtp) {
if (ast_test_flag(&i->flags[1], SIP_PAGE2_VIDEOSUPPORT))
- needvideo = AST_FORMAT_VIDEO_MASK;
- else if (i->prefcodec)
- needvideo = i->prefcodec & AST_FORMAT_VIDEO_MASK; /* Outbound call */
+ needvideo = 1;
+ else if (!ast_format_cap_is_empty(i->prefcaps))
+ needvideo = ast_format_cap_has_type(i->prefcaps, AST_FORMAT_TYPE_VIDEO); /* Outbound call */
else
- needvideo = i->jointcapability & AST_FORMAT_VIDEO_MASK; /* Inbound call */
+ needvideo = ast_format_cap_has_type(i->jointcaps, AST_FORMAT_TYPE_VIDEO); /* Inbound call */
}
if (i->trtp) {
- if (i->prefcodec)
- needtext = i->prefcodec & AST_FORMAT_TEXT_MASK; /* Outbound call */
+ if (!ast_format_cap_is_empty(i->prefcaps))
+ needtext = ast_format_cap_has_type(i->prefcaps, AST_FORMAT_TYPE_TEXT); /* Outbound call */
else
- needtext = i->jointcapability & AST_FORMAT_TEXT_MASK; /* Inbound call */
+ needtext = ast_format_cap_has_type(i->jointcaps, AST_FORMAT_TYPE_TEXT); /* Inbound call */
}
if (needvideo) {
@@ -6662,13 +6664,13 @@ static struct ast_channel *sip_new(struct sip_pvt *i, int state, const char *tit
}
tmp->adsicpe = AST_ADSI_UNAVAILABLE;
- tmp->writeformat = fmt;
- tmp->rawwriteformat = fmt;
- ast_rtp_instance_set_write_format(i->rtp, fmt);
+ ast_format_copy(&tmp->writeformat, &fmt);
+ ast_format_copy(&tmp->rawwriteformat, &fmt);
+ ast_rtp_instance_set_write_format(i->rtp, &fmt);
- tmp->readformat = fmt;
- tmp->rawreadformat = fmt;
- ast_rtp_instance_set_read_format(i->rtp, fmt);
+ ast_format_copy(&tmp->readformat, &fmt);
+ ast_format_copy(&tmp->rawreadformat, &fmt);
+ ast_rtp_instance_set_read_format(i->rtp, &fmt);
tmp->tech_pvt = dialog_ref(i, "sip_new: set chan->tech_pvt to i");
@@ -6976,17 +6978,18 @@ static struct ast_frame *sip_rtp_read(struct ast_channel *ast, struct sip_pvt *p
return f;
}
- if (f && f->subclass.codec != (p->owner->nativeformats & AST_FORMAT_AUDIO_MASK)) {
- if (!(f->subclass.codec & p->jointcapability)) {
+ if (f && !ast_format_cap_iscompatible(p->owner->nativeformats, &f->subclass.format)) {
+ if (!ast_format_cap_iscompatible(p->jointcaps, &f->subclass.format)) {
ast_debug(1, "Bogus frame of format '%s' received from '%s'!\n",
- ast_getformatname(f->subclass.codec), p->owner->name);
+ ast_getformatname(&f->subclass.format), p->owner->name);
return &ast_null_frame;
}
ast_debug(1, "Oooh, format changed to %s\n",
- ast_getformatname(f->subclass.codec));
- p->owner->nativeformats = (p->owner->nativeformats & (AST_FORMAT_VIDEO_MASK | AST_FORMAT_TEXT_MASK)) | f->subclass.codec;
- ast_set_read_format(p->owner, p->owner->readformat);
- ast_set_write_format(p->owner, p->owner->writeformat);
+ ast_getformatname(&f->subclass.format));
+ ast_format_cap_remove_bytype(p->owner->nativeformats, AST_FORMAT_TYPE_AUDIO);
+ ast_format_cap_add(p->owner->nativeformats, &f->subclass.format);
+ ast_set_read_format(p->owner, &p->owner->readformat);
+ ast_set_write_format(p->owner, &p->owner->writeformat);
}
if (f && p->dsp) {
@@ -7149,6 +7152,22 @@ struct sip_pvt *sip_alloc(ast_string_field callid, struct ast_sockaddr *addr,
ao2_t_ref(p, -1, "Yuck, couldn't allocate cc_params struct. Get rid o' p");
return NULL;
}
+ p->caps = ast_format_cap_alloc_nolock();
+ p->jointcaps = ast_format_cap_alloc_nolock();
+ p->peercaps = ast_format_cap_alloc_nolock();
+ p->redircaps = ast_format_cap_alloc_nolock();
+ p->prefcaps = ast_format_cap_alloc_nolock();
+
+ if (!p->caps|| !p->jointcaps || !p->peercaps || !p->redircaps) {
+ p->caps = ast_format_cap_destroy(p->caps);
+ p->jointcaps = ast_format_cap_destroy(p->jointcaps);
+ p->peercaps = ast_format_cap_destroy(p->peercaps);
+ p->redircaps = ast_format_cap_destroy(p->redircaps);
+ p->prefcaps = ast_format_cap_destroy(p->prefcaps);
+ ao2_t_ref(p, -1, "Yuck, couldn't allocate cc_params struct. Get rid o' p");
+ return NULL;
+ }
+
/* If this dialog is created as a result of a request or response, lets store
* some information about it in the dialog. */
@@ -7255,7 +7274,7 @@ struct sip_pvt *sip_alloc(ast_string_field callid, struct ast_sockaddr *addr,
/* Assign default music on hold class */
ast_string_field_set(p, mohinterpret, default_mohinterpret);
ast_string_field_set(p, mohsuggest, default_mohsuggest);
- p->capability = sip_cfg.capability;
+ ast_format_cap_append(p->caps, sip_cfg.caps);
p->allowtransfer = sip_cfg.allowtransfer;
if ((ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_RFC2833) ||
(ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_AUTO))
@@ -8262,6 +8281,8 @@ static int get_ip_and_port_from_sdp(struct sip_request *req, const enum media_ty
*/
static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action)
{
+ int res = 0;
+
/* Iterators for SDP parsing */
int start = req->sdp_start;
int next = start;
@@ -8284,18 +8305,21 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action
struct ast_sockaddr *vsa = NULL; /*!< RTP video host IP */
struct ast_sockaddr *tsa = NULL; /*!< RTP text host IP */
struct ast_sockaddr *isa = NULL; /*!< UDPTL host ip */
- int portno = -1; /*!< RTP Audio port number */
- int vportno = -1; /*!< RTP Video port number */
+ int portno = -1; /*!< RTP Audio port number */
+ int vportno = -1; /*!< RTP Video port number */
int tportno = -1; /*!< RTP Text port number */
int udptlportno = -1; /*!< UDPTL Image port number */
/* Peer capability is the capability in the SDP, non codec is RFC2833 DTMF (101) */
- format_t peercapability = 0, vpeercapability = 0, tpeercapability = 0;
+ struct ast_format_cap *peercapability = ast_format_cap_alloc_nolock();
+ struct ast_format_cap *vpeercapability = ast_format_cap_alloc_nolock();
+ struct ast_format_cap *tpeercapability = ast_format_cap_alloc_nolock();
+
int peernoncodeccapability = 0, vpeernoncodeccapability = 0, tpeernoncodeccapability = 0;
struct ast_rtp_codecs newaudiortp, newvideortp, newtextrtp;
- format_t newjointcapability; /* Negotiated capability */
- format_t newpeercapability;
+ struct ast_format_cap *newjointcapability = ast_format_cap_alloc_nolock(); /* Negotiated capability */
+ struct ast_format_cap *newpeercapability = ast_format_cap_alloc_nolock();
int newnoncodeccapability;
const char *codecs;
@@ -8318,12 +8342,18 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action
/* START UNKNOWN */
char buf[SIPBUFSIZE];
+ struct ast_format tmp_fmt;
/* END UNKNOWN */
/* Initial check */
if (!p->rtp) {
ast_log(LOG_ERROR, "Got SDP but have no RTP session allocated.\n");
- return -1;
+ res = -1;
+ goto process_sdp_cleanup;
+ }
+ if (!peercapability || !vpeercapability || !tpeercapability || !newpeercapability || !newjointcapability) {
+ res = -1;
+ goto process_sdp_cleanup;
}
/* Make sure that the codec structures are all cleared out */
@@ -8353,7 +8383,8 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action
nextm = get_sdp_iterate(&next, req, "m");
if (ast_strlen_zero(nextm)) {
ast_log(LOG_WARNING, "Insufficient information for SDP (m= not found)\n");
- return -1;
+ res = -1;
+ goto process_sdp_cleanup;
}
/* Scan session level SDP parameters (lines before first media stream) */
@@ -8364,8 +8395,10 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action
/* If we end up receiving SDP that doesn't actually modify the session we don't want to treat this as a fatal
* error. We just want to ignore the SDP and let the rest of the packet be handled as normal.
*/
- if (!process_sdp_o(value, p))
- return (p->session_modify == FALSE) ? 0 : -1;
+ if (!process_sdp_o(value, p)) {
+ res = (p->session_modify == FALSE) ? 0 : -1;
+ goto process_sdp_cleanup;
+ }
break;
case 'c':
if (process_sdp_c(value, &sessionsa)) {
@@ -8433,7 +8466,8 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action
for (; !ast_strlen_zero(codecs); codecs = ast_skip_blanks(codecs + len)) {
if (sscanf(codecs, "%30u%n", &codec, &len) != 1) {
ast_log(LOG_WARNING, "Error in codec string '%s'\n", codecs);
- return -1;
+ res = -1;
+ goto process_sdp_cleanup;
}
if (debug)
ast_verbose("Found RTP audio format %d\n", codec);
@@ -8461,7 +8495,8 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action
for (; !ast_strlen_zero(codecs); codecs = ast_skip_blanks(codecs + len)) {
if (sscanf(codecs, "%30u%n", &codec, &len) != 1) {
ast_log(LOG_WARNING, "Error in codec string '%s'\n", codecs);
- return -1;
+ res = -1;
+ goto process_sdp_cleanup;
}
if (debug)
ast_verbose("Found RTP video format %d\n", codec);
@@ -8482,7 +8517,8 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action
for (; !ast_strlen_zero(codecs); codecs = ast_skip_blanks(codecs + len)) {
if (sscanf(codecs, "%30u%n", &codec, &len) != 1) {
ast_log(LOG_WARNING, "Error in codec string '%s'\n", codecs);
- return -1;
+ res = -1;
+ goto process_sdp_cleanup;
}
if (debug)
ast_verbose("Found RTP text format %d\n", codec);
@@ -8587,45 +8623,53 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action
/* Sanity checks */
if (!sa && !vsa && !tsa && !isa) {
ast_log(LOG_WARNING, "Insufficient information in SDP (c=)...\n");
- return -1;
+ res = -1;
+ goto process_sdp_cleanup;
}
if (portno == -1 && vportno == -1 && udptlportno == -1 && tportno == -1) {
/* No acceptable offer found in SDP - we have no ports */
/* Do not change RTP or VRTP if this is a re-invite */
ast_log(LOG_WARNING, "Failing due to no acceptable offer found\n");
- return -2;
+ res = -2;
+ goto process_sdp_cleanup;
}
if (numberofmediastreams > 3) {
/* We have too many fax, audio and/or video and/or text media streams, fail this offer */
ast_log(LOG_WARNING, "Faling due to too many media streams\n");
- return -3;
+ res = -3;
+ goto process_sdp_cleanup;
}
if (secure_audio && !(p->srtp && (ast_test_flag(p->srtp, SRTP_CRYPTO_OFFER_OK)))) {
ast_log(LOG_WARNING, "Can't provide secure audio requested in SDP offer\n");
- return -4;
+ res = -4;
+ goto process_sdp_cleanup;
}
if (!secure_audio && p->srtp) {
ast_log(LOG_WARNING, "We are requesting SRTP, but they responded without it!\n");
- return -4;
+ res = -4;
+ goto process_sdp_cleanup;
}
if (secure_video && !(p->vsrtp && (ast_test_flag(p->vsrtp, SRTP_CRYPTO_OFFER_OK)))) {
ast_log(LOG_WARNING, "Can't provide secure video requested in SDP offer\n");
- return -4;
+ res = -4;
+ goto process_sdp_cleanup;
}
if (!p->novideo && !secure_video && p->vsrtp) {
ast_log(LOG_WARNING, "We are requesting SRTP, but they responded without it!\n");
- return -4;
+ res = -4;
+ goto process_sdp_cleanup;
}
if (!(secure_audio || secure_video) && ast_test_flag(&p->flags[1], SIP_PAGE2_USE_SRTP)) {
ast_log(LOG_WARNING, "Matched device setup to use SRTP, but request was not!\n");
- return -4;
+ res = -4;
+ goto process_sdp_cleanup;
}
if (udptlportno == -1) {
@@ -8633,12 +8677,22 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action
}
/* Now gather all of the codecs that we are asked for: */
- ast_rtp_codecs_payload_formats(&newaudiortp, &peercapability, &peernoncodeccapability);
- ast_rtp_codecs_payload_formats(&newvideortp, &vpeercapability, &vpeernoncodeccapability);
- ast_rtp_codecs_payload_formats(&newtextrtp, &tpeercapability, &tpeernoncodeccapability);
+ ast_rtp_codecs_payload_formats(&newaudiortp, peercapability, &peernoncodeccapability);
+ ast_rtp_codecs_payload_formats(&newvideortp, vpeercapability, &vpeernoncodeccapability);
+ ast_rtp_codecs_payload_formats(&newtextrtp, tpeercapability, &tpeernoncodeccapability);
+
+ ast_format_cap_append(newpeercapability, peercapability);
+ ast_format_cap_append(newpeercapability, vpeercapability);
+ ast_format_cap_append(newpeercapability, tpeercapability);
+
+ ast_format_cap_joint_copy(p->caps, newpeercapability, newjointcapability);
+ if (ast_format_cap_is_empty(newjointcapability) && (portno != -1)) {
+ ast_log(LOG_NOTICE, "No compatible codecs, not accepting this offer!\n");
+ /* Do NOT Change current setting */
+ res = -1;
+ goto process_sdp_cleanup;
+ }
- newjointcapability = p->capability & (peercapability | vpeercapability | tpeercapability);
- newpeercapability = (peercapability | vpeercapability | tpeercapability);
newnoncodeccapability = p->noncodeccapability & peernoncodeccapability;
if (debug) {
@@ -8646,7 +8700,7 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action
char s1[SIPBUFSIZE], s2[SIPBUFSIZE], s3[SIPBUFSIZE], s4[SIPBUFSIZE], s5[SIPBUFSIZE];
ast_verbose("Capabilities: us - %s, peer - audio=%s/video=%s/text=%s, combined - %s\n",
- ast_getformatname_multiple(s1, SIPBUFSIZE, p->capability),
+ ast_getformatname_multiple(s1, SIPBUFSIZE, p->caps),
ast_getformatname_multiple(s2, SIPBUFSIZE, peercapability),
ast_getformatname_multiple(s3, SIPBUFSIZE, vpeercapability),
ast_getformatname_multiple(s4, SIPBUFSIZE, tpeercapability),
@@ -8658,14 +8712,9 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action
struct ast_str *s3 = ast_str_alloca(SIPBUFSIZE);
ast_verbose("Non-codec capabilities (dtmf): us - %s, peer - %s, combined - %s\n",
- ast_rtp_lookup_mime_multiple2(s1, p->noncodeccapability, 0, 0),
- ast_rtp_lookup_mime_multiple2(s2, peernoncodeccapability, 0, 0),
- ast_rtp_lookup_mime_multiple2(s3, newnoncodeccapability, 0, 0));
- }
- if (!newjointcapability && (portno != -1)) {
- ast_log(LOG_NOTICE, "No compatible codecs, not accepting this offer!\n");
- /* Do NOT Change current setting */
- return -1;
+ ast_rtp_lookup_mime_multiple2(s1, NULL, p->noncodeccapability, 0, 0),
+ ast_rtp_lookup_mime_multiple2(s2, NULL, peernoncodeccapability, 0, 0),
+ ast_rtp_lookup_mime_multiple2(s3, NULL, newnoncodeccapability, 0, 0));
}
/* Setup audio address and port */
@@ -8679,12 +8728,13 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action
}
/* We are now ready to change the sip session and p->rtp and p->vrtp with the offered codecs, since
they are acceptable */
- p->jointcapability = newjointcapability; /* Our joint codec profile for this call */
- p->peercapability = newpeercapability; /* The other sides capability in latest offer */
+ ast_format_cap_copy(p->jointcaps, newjointcapability); /* Our joint codec profile for this call */
+ ast_format_cap_copy(p->peercaps, newpeercapability); /* The other sides capability in latest offer */
p->jointnoncodeccapability = newnoncodeccapability; /* DTMF capabilities */
if (ast_test_flag(&p->flags[1], SIP_PAGE2_PREFERRED_CODEC)) { /* respond with single most preferred joint codec, limiting the other side's choice */
- p->jointcapability = ast_codec_choose(&p->prefs, p->jointcapability, 1);
+ ast_codec_choose(&p->prefs, p->jointcaps, 1, &tmp_fmt);
+ ast_format_cap_set(p->jointcaps, &tmp_fmt);
}
ast_rtp_codecs_payloads_copy(&newaudiortp, ast_rtp_instance_get_codecs(p->rtp), p->rtp);
@@ -8737,7 +8787,7 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action
ast_verbose("Peer T.140 RTP is at port %s\n",
ast_sockaddr_stringify(tsa));
}
- if ((p->jointcapability & AST_FORMAT_T140RED)) {
+ if (ast_format_cap_iscompatible(p->jointcaps, ast_format_set(&tmp_fmt, AST_FORMAT_T140RED, 0))) {
p->red = 1;
ast_rtp_red_init(p->trtp, 300, red_data_pt, 2);
} else {
@@ -8807,27 +8857,36 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action
if ((portno == -1) && (p->t38.state != T38_DISABLED)) {
ast_debug(3, "Have T.38 but no audio, accepting offer anyway\n");
- return 0;
- }
+ res = 0;
+ goto process_sdp_cleanup;
+ }
/* Ok, we're going with this offer */
- ast_debug(2, "We're settling with these formats: %s\n", ast_getformatname_multiple(buf, SIPBUFSIZE, p->jointcapability));
+ ast_debug(2, "We're settling with these formats: %s\n", ast_getformatname_multiple(buf, SIPBUFSIZE, p->jointcaps));
- if (!p->owner) /* There's no open channel owning us so we can return here. For a re-invite or so, we proceed */
- return 0;
+ if (!p->owner) { /* There's no open channel owning us so we can return here. For a re-invite or so, we proceed */
+ res = 0;
+ goto process_sdp_cleanup;
+ }
ast_debug(4, "We have an owner, now see if we need to change this call\n");
- if (!(p->owner->nativeformats & p->jointcapability) && (p->jointcapability & AST_FORMAT_AUDIO_MASK)) {
+ if (!(ast_format_cap_has_joint(p->owner->nativeformats, p->jointcaps)) && ast_format_cap_has_type(p->jointcaps, AST_FORMAT_TYPE_AUDIO)) {
if (debug) {
char s1[SIPBUFSIZE], s2[SIPBUFSIZE];
ast_debug(1, "Oooh, we need to change our audio formats since our peer supports only %s and not %s\n",
- ast_getformatname_multiple(s1, SIPBUFSIZE, p->jointcapability),
+ ast_getformatname_multiple(s1, SIPBUFSIZE, p->jointcaps),
ast_getformatname_multiple(s2, SIPBUFSIZE, p->owner->nativeformats));
}
- p->owner->nativeformats = ast_codec_choose(&p->prefs, p->jointcapability, 1) | (p->capability & vpeercapability) | (p->capability & tpeercapability);
- ast_set_read_format(p->owner, p->owner->readformat);
- ast_set_write_format(p->owner, p->owner->writeformat);
+
+ ast_codec_choose(&p->prefs, p->jointcaps, 1, &tmp_fmt);
+
+ ast_format_cap_set(p->owner->nativeformats, &tmp_fmt);
+ ast_format_cap_joint_copy(p->caps, vpeercapability, p->owner->nativeformats);
+ ast_format_cap_joint_copy(p->caps, tpeercapability, p->owner->nativeformats);
+
+ ast_set_read_format(p->owner, &p->owner->readformat);
+ ast_set_write_format(p->owner, &p->owner->writeformat);
}
if (ast_test_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD) && (!ast_sockaddr_isnull(sa) || !ast_sockaddr_isnull(vsa) || !ast_sockaddr_isnull(tsa) || !ast_sockaddr_isnull(isa)) && (!sendonly || sendonly == -1)) {
@@ -8846,8 +8905,14 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action
ast_queue_frame(p->owner, &ast_null_frame);
change_hold_state(p, req, TRUE, sendonly);
}
-
- return 0;
+
+process_sdp_cleanup:
+ ast_format_cap_destroy(peercapability);
+ ast_format_cap_destroy(vpeercapability);
+ ast_format_cap_destroy(tpeercapability);
+ ast_format_cap_destroy(newjointcapability);
+ ast_format_cap_destroy(newpeercapability);
+ return res;
}
static int process_sdp_o(const char *o, struct sip_pvt *p)
@@ -9001,10 +9066,10 @@ static int process_sdp_a_audio(const char *a, struct sip_pvt *p, struct ast_rtp_
int codec_n;
for (codec_n = 0; codec_n < AST_RTP_MAX_PT; codec_n++) {
struct ast_rtp_payload_type format = ast_rtp_codecs_payload_lookup(ast_rtp_instance_get_codecs(p->rtp), codec_n);
- if (!format.asterisk_format || !format.code) /* non-codec or not found */
+ if (!format.asterisk_format) /* non-codec or not found */
continue;
- ast_debug(1, "Setting framing for %s to %ld\n", ast_getformatname(format.code), framing);
- ast_codec_pref_setsize(pref, format.code, framing);
+ ast_debug(1, "Setting framing for %s to %ld\n", ast_getformatname(&format.format), framing);
+ ast_codec_pref_setsize(pref, &format.format, framing);
}
ast_rtp_codecs_packetization_set(ast_rtp_instance_get_codecs(p->rtp), p->rtp, pref);
}
@@ -9032,10 +9097,10 @@ static int process_sdp_a_audio(const char *a, struct sip_pvt *p, struct ast_rtp_
struct ast_rtp_payload_type payload;
payload = ast_rtp_codecs_payload_lookup(newaudiortp, codec);
- if (payload.code && payload.asterisk_format) {
+ if (payload.format.id && payload.asterisk_format) {
unsigned int bit_rate;
- switch (payload.code) {
+ switch ((int) payload.format.id) {
case AST_FORMAT_SIREN7:
if (sscanf(fmtp_string, "bitrate=%30u", &bit_rate) == 1) {
if (bit_rate != 32000) {
@@ -10373,31 +10438,34 @@ static int add_vidupdate(struct sip_request *req)
}
/*! \brief Add codec offer to SDP offer/answer body in INVITE or 200 OK */
-static void add_codec_to_sdp(const struct sip_pvt *p, format_t codec,
- struct ast_str **m_buf, struct ast_str **a_buf,
- int debug, int *min_packet_size)
+static void add_codec_to_sdp(const struct sip_pvt *p,
+ struct ast_format *format,
+ struct ast_str **m_buf,
+ struct ast_str **a_buf,
+ int debug,
+ int *min_packet_size)
{
int rtp_code;
struct ast_format_list fmt;
if (debug)
- ast_verbose("Adding codec 0x%" PRIx64 " (%s) to SDP\n", codec, ast_getformatname(codec));
- if ((rtp_code = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(p->rtp), 1, codec)) == -1)
+ ast_verbose("Adding codec %d (%s) to SDP\n", format->id, ast_getformatname(format));
+ if ((rtp_code = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(p->rtp), 1, format, 0)) == -1)
return;
if (p->rtp) {
struct ast_codec_pref *pref = &ast_rtp_instance_get_codecs(p->rtp)->pref;
- fmt = ast_codec_pref_getsize(pref, codec);
+ fmt = ast_codec_pref_getsize(pref, format);
} else /* I don't see how you couldn't have p->rtp, but good to check for and error out if not there like earlier code */
return;
ast_str_append(m_buf, 0, " %d", rtp_code);
- ast_str_append(a_buf, 0, "a=rtpmap:%d %s/%d\r\n", rtp_code,
- ast_rtp_lookup_mime_subtype2(1, codec,
- ast_test_flag(&p->flags[0], SIP_G726_NONSTANDARD) ? AST_RTP_OPT_G726_NONSTANDARD : 0),
- ast_rtp_lookup_sample_rate2(1, codec));
+ ast_str_append(a_buf, 0, "a=rtpmap:%d %s/%d\r\n",
+ rtp_code,
+ ast_rtp_lookup_mime_subtype2(1, format, 0, ast_test_flag(&p->flags[0], SIP_G726_NONSTANDARD) ? AST_RTP_OPT_G726_NONSTANDARD : 0),
+ ast_rtp_lookup_sample_rate2(1, format, 0));
- switch (codec) {
+ switch ((int) format->id) {
case AST_FORMAT_G729A:
/* Indicate that we don't support VAD (G.729 annex B) */
ast_str_append(a_buf, 0, "a=fmtp:%d annexb=no\r\n", rtp_code);
@@ -10434,7 +10502,7 @@ static void add_codec_to_sdp(const struct sip_pvt *p, format_t codec,
/*! \brief Add video codec offer to SDP offer/answer body in INVITE or 200 OK */
/* This is different to the audio one now so we can add more caps later */
-static void add_vcodec_to_sdp(const struct sip_pvt *p, format_t codec,
+static void add_vcodec_to_sdp(const struct sip_pvt *p, struct ast_format *format,
struct ast_str **m_buf, struct ast_str **a_buf,
int debug, int *min_packet_size)
{
@@ -10444,20 +10512,20 @@ static void add_vcodec_to_sdp(const struct sip_pvt *p, format_t codec,
return;
if (debug)
- ast_verbose("Adding video codec 0x%" PRIx64 " (%s) to SDP\n", codec, ast_getformatname(codec));
+ ast_verbose("Adding video codec %d (%s) to SDP\n", format->id, ast_getformatname(format));
- if ((rtp_code = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(p->vrtp), 1, codec)) == -1)
+ if ((rtp_code = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(p->vrtp), 1, format, 0)) == -1)
return;
ast_str_append(m_buf, 0, " %d", rtp_code);
ast_str_append(a_buf, 0, "a=rtpmap:%d %s/%d\r\n", rtp_code,
- ast_rtp_lookup_mime_subtype2(1, codec, 0),
- ast_rtp_lookup_sample_rate2(1, codec));
+ ast_rtp_lookup_mime_subtype2(1, format, 0, 0),
+ ast_rtp_lookup_sample_rate2(1, format, 0));
/* Add fmtp code here */
}
/*! \brief Add text codec offer to SDP offer/answer body in INVITE or 200 OK */
-static void add_tcodec_to_sdp(const struct sip_pvt *p, int codec,
+static void add_tcodec_to_sdp(const struct sip_pvt *p, struct ast_format *format,
struct ast_str **m_buf, struct ast_str **a_buf,
int debug, int *min_packet_size)
{
@@ -10467,19 +10535,20 @@ static void add_tcodec_to_sdp(const struct sip_pvt *p, int codec,
return;
if (debug)
- ast_verbose("Adding text codec 0x%x (%s) to SDP\n", codec, ast_getformatname(codec));
+ ast_verbose("Adding text codec %d (%s) to SDP\n", format->id, ast_getformatname(format));
- if ((rtp_code = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(p->trtp), 1, codec)) == -1)
+ if ((rtp_code = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(p->trtp), 1, format, 0)) == -1)
return;
ast_str_append(m_buf, 0, " %d", rtp_code);
ast_str_append(a_buf, 0, "a=rtpmap:%d %s/%d\r\n", rtp_code,
- ast_rtp_lookup_mime_subtype2(1, codec, 0),
- ast_rtp_lookup_sample_rate2(1, codec));
+ ast_rtp_lookup_mime_subtype2(1, format, 0, 0),
+ ast_rtp_lookup_sample_rate2(1, format, 0));
/* Add fmtp code here */
- if (codec == AST_FORMAT_T140RED) {
- int t140code = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(p->trtp), 1, AST_FORMAT_T140);
+ if (format->id == AST_FORMAT_T140RED) {
+ struct ast_format tmp_fmt;
+ int t140code = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(p->trtp), 1, ast_format_set(&tmp_fmt, AST_FORMAT_T140, 0), 0);
ast_str_append(a_buf, 0, "a=fmtp:%d %d/%d/%d\r\n", rtp_code,
t140code,
t140code,
@@ -10518,14 +10587,14 @@ static void add_noncodec_to_sdp(const struct sip_pvt *p, int format,
int rtp_code;
if (debug)
- ast_verbose("Adding non-codec 0x%x (%s) to SDP\n", format, ast_rtp_lookup_mime_subtype2(0, format, 0));
- if ((rtp_code = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(p->rtp), 0, format)) == -1)
+ ast_verbose("Adding non-codec 0x%x (%s) to SDP\n", format, ast_rtp_lookup_mime_subtype2(0, NULL, format, 0));
+ if ((rtp_code = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(p->rtp), 0, NULL, format)) == -1)
return;
ast_str_append(m_buf, 0, " %d", rtp_code);
ast_str_append(a_buf, 0, "a=rtpmap:%d %s/%d\r\n", rtp_code,
- ast_rtp_lookup_mime_subtype2(0, format, 0),
- ast_rtp_lookup_sample_rate2(0, format));
+ ast_rtp_lookup_mime_subtype2(0, NULL, format, 0),
+ ast_rtp_lookup_sample_rate2(0, NULL, format));
if (format == AST_RTP_DTMF) /* Indicate we support DTMF and FLASH... */
ast_str_append(a_buf, 0, "a=fmtp:%d 0-16\r\n", rtp_code);
}
@@ -10651,9 +10720,10 @@ static void get_crypto_attrib(struct sip_srtp *srtp, const char **a_crypto)
*/
static enum sip_result add_sdp(struct sip_request *resp, struct sip_pvt *p, int oldsdp, int add_audio, int add_t38)
{
- format_t alreadysent = 0;
+ struct ast_format_cap *alreadysent = ast_format_cap_alloc_nolock();
+ struct ast_format_cap *tmpcap = ast_format_cap_alloc_nolock();
+ int res = AST_SUCCESS;
int doing_directmedia = FALSE;
-
struct ast_sockaddr addr = { {0,} };
struct ast_sockaddr vaddr = { {0,} };
struct ast_sockaddr taddr = { {0,} };
@@ -10683,8 +10753,8 @@ static enum sip_result add_sdp(struct sip_request *resp, struct sip_pvt *p, int
const char *v_a_crypto = NULL;
const char *t_a_crypto = NULL;
- format_t x;
- format_t capability = 0;
+ int x;
+ struct ast_format tmp_fmt;
int needaudio = FALSE;
int needvideo = FALSE;
int needtext = FALSE;
@@ -10700,9 +10770,15 @@ static enum sip_result add_sdp(struct sip_request *resp, struct sip_pvt *p, int
/* Set the SDP session name */
snprintf(subject, sizeof(subject), "s=%s\r\n", ast_strlen_zero(global_sdpsession) ? "-" : global_sdpsession);
+ if (!alreadysent || !tmpcap) {
+ res = AST_FAILURE;
+ goto add_sdp_cleanup;
+ }
if (!p->rtp) {
ast_log(LOG_WARNING, "No way to add SDP without an RTP structure\n");
- return AST_FAILURE;
+ res = AST_FAILURE;
+ goto add_sdp_cleanup;
+
}
/* XXX We should not change properties in the SIP dialog until
we have acceptance of the offer if this is a re-invite */
@@ -10717,9 +10793,9 @@ static enum sip_result add_sdp(struct sip_request *resp, struct sip_pvt *p, int
}
if (add_audio) {
- doing_directmedia = (!ast_sockaddr_isnull(&p->redirip) && p->redircodecs) ? TRUE : FALSE;
+ doing_directmedia = (!ast_sockaddr_isnull(&p->redirip) && !(ast_format_cap_is_empty(p->redircaps))) ? TRUE : FALSE;
/* Check if we need video in this call */
- if ((p->jointcapability & AST_FORMAT_VIDEO_MASK) && !p->novideo) {
+ if ((ast_format_cap_has_type(p->jointcaps, AST_FORMAT_TYPE_VIDEO)) && !p->novideo) {
if (p->vrtp) {
needvideo = TRUE;
ast_debug(2, "This call needs video offers!\n");
@@ -10727,7 +10803,7 @@ static enum sip_result add_sdp(struct sip_request *resp, struct sip_pvt *p, int
ast_debug(2, "This call needs video offers, but there's no video support enabled!\n");
}
/* Check if we need text in this call */
- if ((p->jointcapability & AST_FORMAT_TEXT_MASK) && !p->notext) {
+ if ((ast_format_cap_has_type(p->jointcaps, AST_FORMAT_TYPE_TEXT)) && !p->notext) {
if (sipdebug_text)
ast_verbose("We think we can do text\n");
if (p->trtp) {
@@ -10767,20 +10843,20 @@ static enum sip_result add_sdp(struct sip_request *resp, struct sip_pvt *p, int
hold = "a=sendrecv\r\n";
}
- capability = p->jointcapability;
+ ast_format_cap_copy(tmpcap, p->jointcaps);
/* XXX note, Video and Text are negated - 'true' means 'no' */
- ast_debug(1, "** Our capability: %s Video flag: %s Text flag: %s\n", ast_getformatname_multiple(codecbuf, sizeof(codecbuf), capability),
+ ast_debug(1, "** Our capability: %s Video flag: %s Text flag: %s\n", ast_getformatname_multiple(codecbuf, sizeof(codecbuf), tmpcap),
p->novideo ? "True" : "False", p->notext ? "True" : "False");
- ast_debug(1, "** Our prefcodec: %s \n", ast_getformatname_multiple(codecbuf, sizeof(codecbuf), p->prefcodec));
+ ast_debug(1, "** Our prefcodec: %s \n", ast_getformatname_multiple(codecbuf, sizeof(codecbuf), p->prefcaps));
if (doing_directmedia) {
- capability &= p->redircodecs;
- ast_debug(1, "** Our native-bridge filtered capablity: %s\n", ast_getformatname_multiple(codecbuf, sizeof(codecbuf), capability));
+ ast_format_cap_joint_copy(p->jointcaps, p->redircaps, tmpcap);
+ ast_debug(1, "** Our native-bridge filtered capablity: %s\n", ast_getformatname_multiple(codecbuf, sizeof(codecbuf), tmpcap));
}
/* Check if we need audio */
- if (capability & AST_FORMAT_AUDIO_MASK)
+ if (ast_format_cap_has_type(tmpcap, AST_FORMAT_TYPE_AUDIO))
needaudio = TRUE;
if (debug) {
@@ -10833,45 +10909,55 @@ static enum sip_result add_sdp(struct sip_request *resp, struct sip_pvt *p, int
/* Prefer the audio codec we were requested to use, first, no matter what
Note that p->prefcodec can include video codecs, so mask them out
*/
- if (capability & p->prefcodec) {
- format_t codec = p->prefcodec & AST_FORMAT_AUDIO_MASK;
-
- add_codec_to_sdp(p, codec, &m_audio, &a_audio, debug, &min_audio_packet_size);
- alreadysent |= codec;
+ if (ast_format_cap_has_joint(tmpcap, p->prefcaps)) {
+ ast_format_cap_iter_start(p->prefcaps);
+ while (!(ast_format_cap_iter_next(p->prefcaps, &tmp_fmt))) {
+ if (AST_FORMAT_GET_TYPE(tmp_fmt.id) != AST_FORMAT_TYPE_AUDIO) {
+ continue;
+ }
+ add_codec_to_sdp(p, &tmp_fmt, &m_audio, &a_audio, debug, &min_audio_packet_size);
+ ast_format_cap_add(alreadysent, &tmp_fmt);
+ }
+ ast_format_cap_iter_end(p->prefcaps);
}
/* Start by sending our preferred audio/video codecs */
- for (x = 0; x < 64; x++) {
- format_t codec;
-
- if (!(codec = ast_codec_pref_index(&p->prefs, x)))
+ for (x = 0; x < AST_CODEC_PREF_SIZE; x++) {
+ if (!(ast_codec_pref_index(&p->prefs, x, &tmp_fmt)))
break;
- if (!(capability & codec))
+ if (!(ast_format_cap_iscompatible(tmpcap, &tmp_fmt)))
continue;
- if (alreadysent & codec)
+ if (ast_format_cap_iscompatible(alreadysent, &tmp_fmt))
continue;
- add_codec_to_sdp(p, codec, &m_audio, &a_audio, debug, &min_audio_packet_size);
- alreadysent |= codec;
+ if (AST_FORMAT_GET_TYPE(tmp_fmt.id) == AST_FORMAT_TYPE_AUDIO) {
+ add_codec_to_sdp(p, &tmp_fmt, &m_audio, &a_audio, debug, &min_audio_packet_size);
+ } else if (needvideo && (AST_FORMAT_GET_TYPE(tmp_fmt.id) == AST_FORMAT_TYPE_VIDEO)) {
+ add_vcodec_to_sdp(p, &tmp_fmt, &m_video, &a_video, debug, &min_video_packet_size);
+ } else if (needtext && (AST_FORMAT_GET_TYPE(tmp_fmt.id) == AST_FORMAT_TYPE_TEXT)) {
+ add_tcodec_to_sdp(p, &tmp_fmt, &m_text, &a_text, debug, &min_text_packet_size);
+ }
+
+ ast_format_cap_add(alreadysent, &tmp_fmt);
}
/* Now send any other common audio and video codecs, and non-codec formats: */
- for (x = 1ULL; x <= (needtext ? AST_FORMAT_TEXT_MASK : (needvideo ? AST_FORMAT_VIDEO_MASK : AST_FORMAT_AUDIO_MASK)); x <<= 1) {
- if (!(capability & x)) /* Codec not requested */
+ ast_format_cap_iter_start(tmpcap);
+ while (!(ast_format_cap_iter_next(tmpcap, &tmp_fmt))) {
+ if (ast_format_cap_iscompatible(alreadysent, &tmp_fmt))
continue;
- if (alreadysent & x) /* Already added to SDP */
- continue;
-
- if (x & AST_FORMAT_AUDIO_MASK)
- add_codec_to_sdp(p, x, &m_audio, &a_audio, debug, &min_audio_packet_size);
- else if (x & AST_FORMAT_VIDEO_MASK)
- add_vcodec_to_sdp(p, x, &m_video, &a_video, debug, &min_video_packet_size);
- else if (x & AST_FORMAT_TEXT_MASK)
- add_tcodec_to_sdp(p, x, &m_text, &a_text, debug, &min_text_packet_size);
+ if (AST_FORMAT_GET_TYPE(tmp_fmt.id) == AST_FORMAT_TYPE_AUDIO) {
+ add_codec_to_sdp(p, &tmp_fmt, &m_audio, &a_audio, debug, &min_audio_packet_size);
+ } else if (needvideo && (AST_FORMAT_GET_TYPE(tmp_fmt.id) == AST_FORMAT_TYPE_VIDEO)) {
+ add_vcodec_to_sdp(p, &tmp_fmt, &m_video, &a_video, debug, &min_video_packet_size);
+ } else if (needtext && (AST_FORMAT_GET_TYPE(tmp_fmt.id) == AST_FORMAT_TYPE_TEXT)) {
+ add_tcodec_to_sdp(p, &tmp_fmt, &m_text, &a_text, debug, &min_text_packet_size);
+ }
}
+ ast_format_cap_iter_end(tmpcap);
/* Now add DTMF RFC2833 telephony-event as a codec */
for (x = 1LL; x <= AST_RTP_MAX; x <<= 1) {
@@ -11024,9 +11110,13 @@ static enum sip_result add_sdp(struct sip_request *resp, struct sip_pvt *p, int
ao2_t_unlink(dialogs_rtpcheck, p, "unlink pvt into dialogs_rtpcheck container");
ao2_t_link(dialogs_rtpcheck, p, "link pvt into dialogs_rtpcheck container");
- ast_debug(3, "Done building SDP. Settling with this capability: %s\n", ast_getformatname_multiple(buf, SIPBUFSIZE, capability));
+ ast_debug(3, "Done building SDP. Settling with this capability: %s\n", ast_getformatname_multiple(buf, SIPBUFSIZE, tmpcap));
- return AST_SUCCESS;
+add_sdp_cleanup:
+ alreadysent = ast_format_cap_destroy(alreadysent);
+ tmpcap = ast_format_cap_destroy(tmpcap);
+
+ return res;
}
/*! \brief Used for 200 OK and 183 early media */
@@ -15257,14 +15347,21 @@ static enum check_auth_result check_peer_ok(struct sip_pvt *p, char *of,
p->amaflags = peer->amaflags;
p->callgroup = peer->callgroup;
p->pickupgroup = peer->pickupgroup;
- p->capability = peer->capability;
+ ast_format_cap_copy(p->caps, peer->caps);
+ ast_format_cap_copy(p->jointcaps, peer->caps);
p->prefs = peer->prefs;
- p->jointcapability = peer->capability;
if (peer->maxforwards > 0) {
p->maxforwards = peer->maxforwards;
}
- if (p->peercapability)
- p->jointcapability &= p->peercapability;
+ if (!(ast_format_cap_is_empty(p->peercaps))) {
+ struct ast_format_cap *tmp = ast_format_cap_joint(p->jointcaps, p->peercaps);
+ struct ast_format_cap *tmp2;
+ if (tmp) {
+ tmp2 = p->jointcaps;
+ p->jointcaps = tmp;
+ ast_format_cap_destroy(tmp2);
+ }
+ }
p->maxcallbitrate = peer->maxcallbitrate;
if ((ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_RFC2833) ||
(ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_AUTO))
@@ -16333,15 +16430,15 @@ static char *sip_prune_realtime(struct ast_cli_entry *e, int cmd, struct ast_cli
static void print_codec_to_cli(int fd, struct ast_codec_pref *pref)
{
int x;
- format_t codec;
+ struct ast_format codec;
- for(x = 0; x < 64 ; x++) {
- codec = ast_codec_pref_index(pref, x);
- if (!codec)
+ for(x = 0; x < AST_CODEC_PREF_SIZE; x++) {
+ if (!(ast_codec_pref_index(pref, x, &codec))) {
break;
- ast_cli(fd, "%s", ast_getformatname(codec));
+ }
+ ast_cli(fd, "%s", ast_getformatname(&codec));
ast_cli(fd, ":%d", pref->framing[x]);
- if (x < 31 && ast_codec_pref_index(pref, x + 1))
+ if (x < 31 && ast_codec_pref_index(pref, x + 1, &codec))
ast_cli(fd, ",");
}
if (!x)
@@ -16529,7 +16626,7 @@ static char *_sip_show_peer(int type, int fd, struct mansession *s, const struct
struct ast_variable *v;
struct sip_auth *auth;
int x = 0, load_realtime;
- format_t codec = 0;
+ struct ast_format codec;
int realtimepeers;
realtimepeers = ast_check_realtime("sippeers");
@@ -16644,7 +16741,7 @@ static char *_sip_show_peer(int type, int fd, struct mansession *s, const struct
ast_cli(fd, "\n");
ast_cli(fd, " Codecs : ");
- ast_getformatname_multiple(codec_buf, sizeof(codec_buf) -1, peer->capability);
+ ast_getformatname_multiple(codec_buf, sizeof(codec_buf) -1, peer->caps);
ast_cli(fd, "%s\n", codec_buf);
ast_cli(fd, " Codec Order : (");
print_codec_to_cli(fd, &peer->prefs);
@@ -16738,16 +16835,16 @@ static char *_sip_show_peer(int type, int fd, struct mansession *s, const struct
if (!ast_strlen_zero(sip_cfg.regcontext))
astman_append(s, "RegExtension: %s\r\n", peer->regexten);
astman_append(s, "Codecs: ");
- ast_getformatname_multiple(codec_buf, sizeof(codec_buf) -1, peer->capability);
+ ast_getformatname_multiple(codec_buf, sizeof(codec_buf) -1, peer->caps);
astman_append(s, "%s\r\n", codec_buf);
astman_append(s, "CodecOrder: ");
pref = &peer->prefs;
- for(x = 0; x < 64 ; x++) {
- codec = ast_codec_pref_index(pref, x);
- if (!codec)
+ for(x = 0; x < AST_CODEC_PREF_SIZE ; x++) {
+ if (!(ast_codec_pref_index(pref, x, &codec))) {
break;
- astman_append(s, "%s", ast_getformatname(codec));
- if (x < 63 && ast_codec_pref_index(pref, x+1))
+ }
+ astman_append(s, "%s", ast_getformatname(&codec));
+ if ((x < (AST_CODEC_PREF_SIZE - 1)) && ast_codec_pref_index(pref, x+1, &codec))
astman_append(s, ",");
}
@@ -17243,7 +17340,7 @@ static char *sip_show_settings(struct ast_cli_entry *e, int cmd, struct ast_cli_
ast_cli(a->fd, "\nGlobal Signalling Settings:\n");
ast_cli(a->fd, "---------------------------\n");
ast_cli(a->fd, " Codecs: ");
- ast_getformatname_multiple(codec_buf, sizeof(codec_buf) -1, sip_cfg.capability);
+ ast_getformatname_multiple(codec_buf, sizeof(codec_buf) -1, sip_cfg.caps);
ast_cli(a->fd, "%s\n", codec_buf);
ast_cli(a->fd, " Codec Order: ");
print_codec_to_cli(a->fd, &default_prefs);
@@ -17400,7 +17497,7 @@ static int show_channels_cb(void *__cur, void *__arg, int flags)
ast_cli(arg->fd, FORMAT, ast_sockaddr_stringify_addr(dst),
S_OR(cur->username, S_OR(cur->cid_num, "(None)")),
cur->callid,
- ast_getformatname_multiple(formatbuf, sizeof(formatbuf), cur->owner ? cur->owner->nativeformats : 0),
+ cur->owner ? ast_getformatname_multiple(formatbuf, sizeof(formatbuf), cur->owner->nativeformats) : "(nothing)",
AST_CLI_YESNO(ast_test_flag(&cur->flags[1], SIP_PAGE2_CALL_ONHOLD)),
cur->needdestroy ? "(d)" : "",
cur->lastmsg ,
@@ -17649,11 +17746,11 @@ static char *sip_show_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_a
ast_cli(a->fd, " Curr. trans. direction: %s\n", ast_test_flag(&cur->flags[0], SIP_OUTGOING) ? "Outgoing" : "Incoming");
ast_cli(a->fd, " Call-ID: %s\n", cur->callid);
ast_cli(a->fd, " Owner channel ID: %s\n", cur->owner ? cur->owner->name : "<none>");
- ast_cli(a->fd, " Our Codec Capability: %s\n", ast_getformatname_multiple(formatbuf, sizeof(formatbuf), cur->capability));
+ ast_cli(a->fd, " Our Codec Capability: %s\n", ast_getformatname_multiple(formatbuf, sizeof(formatbuf), cur->caps));
ast_cli(a->fd, " Non-Codec Capability (DTMF): %d\n", cur->noncodeccapability);
- ast_cli(a->fd, " Their Codec Capability: %s\n", ast_getformatname_multiple(formatbuf, sizeof(formatbuf), cur->peercapability));
- ast_cli(a->fd, " Joint Codec Capability: %s\n", ast_getformatname_multiple(formatbuf, sizeof(formatbuf), cur->jointcapability));
- ast_cli(a->fd, " Format: %s\n", ast_getformatname_multiple(formatbuf, sizeof(formatbuf), cur->owner ? cur->owner->nativeformats : 0) );
+ ast_cli(a->fd, " Their Codec Capability: %s\n", ast_getformatname_multiple(formatbuf, sizeof(formatbuf), cur->peercaps));
+ ast_cli(a->fd, " Joint Codec Capability: %s\n", ast_getformatname_multiple(formatbuf, sizeof(formatbuf), cur->jointcaps));
+ ast_cli(a->fd, " Format: %s\n", cur->owner ? ast_getformatname_multiple(formatbuf, sizeof(formatbuf), cur->owner->nativeformats) : "(nothing)" );
ast_cli(a->fd, " T.38 support %s\n", AST_CLI_YESNO(cur->udptl != NULL));
ast_cli(a->fd, " Video support %s\n", AST_CLI_YESNO(cur->vrtp != NULL));
ast_cli(a->fd, " MaxCallBR: %d kbps\n", cur->maxcallbitrate);
@@ -18558,13 +18655,13 @@ static int function_sippeer(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")) {
- ast_getformatname_multiple(buf, len -1, peer->capability);
+ ast_getformatname_multiple(buf, len -1, peer->caps);
} else if (!strcasecmp(colname, "encryption")) {
snprintf(buf, len, "%d", ast_test_flag(&peer->flags[1], SIP_PAGE2_USE_SRTP));
} else if (!strncasecmp(colname, "chanvar[", 8)) {
char *chanvar=colname + 8;
struct ast_variable *v;
-
+
chanvar = strsep(&chanvar, "]");
for (v = peer->chanvars ; v ; v = v->next) {
if (!strcasecmp(v->name, chanvar)) {
@@ -18573,12 +18670,12 @@ static int function_sippeer(struct ast_channel *chan, const char *cmd, char *dat
}
} else if (!strncasecmp(colname, "codec[", 6)) {
char *codecnum;
- format_t codec = 0;
-
+ struct ast_format codec;
+
codecnum = colname + 6; /* move past the '[' */
codecnum = strsep(&codecnum, "]"); /* trim trailing ']' if any */
- if((codec = ast_codec_pref_index(&peer->prefs, atoi(codecnum)))) {
- ast_copy_string(buf, ast_getformatname(codec), len);
+ if((ast_codec_pref_index(&peer->prefs, atoi(codecnum), &codec))) {
+ ast_copy_string(buf, ast_getformatname(&codec), len);
} else {
buf[0] = '\0';
}
@@ -21484,7 +21581,7 @@ static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, int
}
ast_queue_control(p->owner, AST_CONTROL_SRCUPDATE);
} else {
- p->jointcapability = p->capability;
+ ast_format_cap_copy(p->jointcaps, p->caps);
ast_debug(1, "Hm.... No sdp for the moment\n");
/* Some devices signal they want to be put off hold by sending a re-invite
*without* an SDP, which is supposed to mean "Go back to your state"
@@ -21566,7 +21663,7 @@ static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, int
goto request_invite_cleanup;
}
} else { /* No SDP in invite, call control session */
- p->jointcapability = p->capability;
+ ast_format_cap_copy(p->jointcaps, p->caps);
ast_debug(2, "No SDP in Invite, third party call control\n");
}
@@ -21968,7 +22065,7 @@ static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, int
if (p && (p->autokillid == -1)) {
const char *msg;
- if (!p->jointcapability)
+ if ((ast_format_cap_is_empty(p->jointcaps)))
msg = "488 Not Acceptable Here (codec error)";
else {
ast_log(LOG_NOTICE, "Unable to create/find SIP channel for this INVITE\n");
@@ -25309,12 +25406,13 @@ static int sip_devicestate(void *data)
* or SIP/host!dnid
* \endverbatim
*/
-static struct ast_channel *sip_request_call(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause)
+static struct ast_channel *sip_request_call(const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor, void *data, int *cause)
{
struct sip_pvt *p;
struct ast_channel *tmpc = NULL;
char *ext = NULL, *host;
char tmp[256];
+ char tmp2[256];
char *dest = data;
char *dnid;
char *secret = NULL;
@@ -25325,7 +25423,6 @@ static struct ast_channel *sip_request_call(const char *type, format_t format, c
char *remote_address;
enum sip_transport transport = 0;
struct ast_sockaddr remote_address_sa = { {0,} };
- format_t oldformat = format;
AST_DECLARE_APP_ARGS(args,
AST_APP_ARG(peerorhost);
AST_APP_ARG(exten);
@@ -25339,13 +25436,14 @@ static struct ast_channel *sip_request_call(const char *type, format_t format, c
* configured from sip.conf, and sip_tech.capabilities, which is
* hardwired to all audio formats.
*/
- format &= AST_FORMAT_AUDIO_MASK;
- if (!format) {
- ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format %s while capability is %s\n", ast_getformatname(oldformat), ast_getformatname(sip_cfg.capability));
+ if (!(ast_format_cap_has_type(cap, AST_FORMAT_TYPE_AUDIO))) {
+ ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format %s while capability is %s\n",
+ ast_getformatname_multiple(tmp, sizeof(tmp), cap),
+ ast_getformatname_multiple(tmp2, sizeof(tmp2), sip_cfg.caps));
*cause = AST_CAUSE_BEARERCAPABILITY_NOTAVAIL; /* Can't find codec to connect to host */
return NULL;
}
- ast_debug(1, "Asked to create a SIP channel with formats: %s\n", ast_getformatname_multiple(tmp, sizeof(tmp), oldformat));
+ ast_debug(1, "Asked to create a SIP channel with formats: %s\n", ast_getformatname_multiple(tmp, sizeof(tmp), cap));
if (ast_strlen_zero(dest)) {
ast_log(LOG_ERROR, "Unable to create channel with empty destination.\n");
@@ -25488,8 +25586,9 @@ static struct ast_channel *sip_request_call(const char *type, format_t format, c
#if 0
printf("Setting up to call extension '%s' at '%s'\n", ext ? ext : "<none>", host);
#endif
- p->prefcodec = oldformat; /* Format for this call */
- p->jointcapability = oldformat & p->capability;
+ ast_format_cap_append(p->prefcaps, cap);
+ ast_format_cap_joint_copy(cap, p->caps, p->jointcaps);
+
sip_pvt_lock(p);
tmpc = sip_new(p, AST_STATE_DOWN, host, requestor ? requestor->linkedid : NULL); /* Place the call */
if (sip_cfg.callevents)
@@ -25915,7 +26014,7 @@ static void set_peer_defaults(struct sip_peer *peer)
ast_string_field_set(peer, engine, default_engine);
ast_sockaddr_setnull(&peer->addr);
ast_sockaddr_setnull(&peer->defaddr);
- peer->capability = sip_cfg.capability;
+ ast_format_cap_copy(peer->caps, sip_cfg.caps);
peer->maxcallbitrate = default_maxcallbitrate;
peer->rtptimeout = global_rtptimeout;
peer->rtpholdtimeout = global_rtpholdtimeout;
@@ -26063,9 +26162,13 @@ static struct sip_peer *build_peer(const char *name, struct ast_variable *v, str
if (!(peer->the_mark))
firstpass = 0;
} else {
- if (!(peer = ao2_t_alloc(sizeof(*peer), sip_destroy_peer_fn, "allocate a peer struct")))
+ if (!(peer = ao2_t_alloc(sizeof(*peer), sip_destroy_peer_fn, "allocate a peer struct"))) {
return NULL;
-
+ }
+ if (!(peer->caps = ast_format_cap_alloc_nolock())) {
+ ao2_t_ref(peer, -1, "failed to allocate format capabilities, drop peer");
+ return NULL;
+ }
if (ast_string_field_init(peer, 512)) {
ao2_t_ref(peer, -1, "failed to string_field_init, drop peer");
return NULL;
@@ -26356,12 +26459,12 @@ static struct sip_peer *build_peer(const char *name, struct ast_variable *v, str
} else if (!strcasecmp(v->name, "pickupgroup")) {
peer->pickupgroup = ast_get_group(v->value);
} else if (!strcasecmp(v->name, "allow")) {
- int error = ast_parse_allow_disallow(&peer->prefs, &peer->capability, v->value, TRUE);
+ int error = ast_parse_allow_disallow(&peer->prefs, peer->caps, v->value, TRUE);
if (error) {
ast_log(LOG_WARNING, "Codec configuration errors found in line %d : %s = %s\n", v->lineno, v->name, v->value);
}
} else if (!strcasecmp(v->name, "disallow")) {
- int error = ast_parse_allow_disallow(&peer->prefs, &peer->capability, v->value, FALSE);
+ int error = ast_parse_allow_disallow(&peer->prefs, peer->caps, v->value, FALSE);
if (error) {
ast_log(LOG_WARNING, "Codec configuration errors found in line %d : %s = %s\n", v->lineno, v->name, v->value);
}
@@ -26697,6 +26800,22 @@ static int peer_markall_func(void *device, void *arg, int flags)
return 0;
}
+/*!
+ * \internal
+ * \brief If no default formats are set in config, these are used
+ */
+static void sip_set_default_format_capabilities(struct ast_format_cap *cap)
+{
+ struct ast_format tmp_fmt;
+
+ ast_format_cap_remove_all(cap);
+ ast_format_cap_add(cap, ast_format_set(&tmp_fmt, AST_FORMAT_ULAW, 0));
+ ast_format_cap_add(cap, ast_format_set(&tmp_fmt, AST_FORMAT_TESTLAW, 0));
+ ast_format_cap_add(cap, ast_format_set(&tmp_fmt, AST_FORMAT_ALAW, 0));
+ ast_format_cap_add(cap, ast_format_set(&tmp_fmt, AST_FORMAT_GSM, 0));
+ ast_format_cap_add(cap, ast_format_set(&tmp_fmt, AST_FORMAT_H263, 0));
+}
+
/*! \brief Re-read SIP.conf config file
\note This function reloads all config data, except for
active peers (with registrations). They will only
@@ -26852,7 +26971,7 @@ static int reload_config(enum channelreloadreason reason)
/* Reset channel settings to default before re-configuring */
sip_cfg.allow_external_domains = DEFAULT_ALLOW_EXT_DOM; /* Allow external invites */
sip_cfg.regcontext[0] = '\0';
- sip_cfg.capability = DEFAULT_CAPABILITY;
+ sip_set_default_format_capabilities(sip_cfg.caps);
sip_cfg.regextenonqualify = DEFAULT_REGEXTENONQUALIFY;
sip_cfg.notifyringing = DEFAULT_NOTIFYRINGING;
sip_cfg.notifycid = DEFAULT_NOTIFYCID;
@@ -27258,12 +27377,12 @@ static int reload_config(enum channelreloadreason reason)
ast_log(LOG_WARNING, "Invalid externtlsport value, must be a positive integer between 1 and 65535 at line %d\n", v->lineno);
}
} else if (!strcasecmp(v->name, "allow")) {
- int error = ast_parse_allow_disallow(&default_prefs, &sip_cfg.capability, v->value, TRUE);
+ int error = ast_parse_allow_disallow(&default_prefs, sip_cfg.caps, v->value, TRUE);
if (error) {
ast_log(LOG_WARNING, "Codec configuration errors found in line %d : %s = %s\n", v->lineno, v->name, v->value);
}
} else if (!strcasecmp(v->name, "disallow")) {
- int error = ast_parse_allow_disallow(&default_prefs, &sip_cfg.capability, v->value, FALSE);
+ int error = ast_parse_allow_disallow(&default_prefs, sip_cfg.caps, v->value, FALSE);
if (error) {
ast_log(LOG_WARNING, "Codec configuration errors found in line %d : %s = %s\n", v->lineno, v->name, v->value);
}
@@ -27918,7 +28037,7 @@ static enum ast_rtp_glue_result sip_get_trtp_peer(struct ast_channel *chan, stru
return res;
}
-static int sip_set_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance *instance, struct ast_rtp_instance *vinstance, struct ast_rtp_instance *tinstance, format_t codecs, int nat_active)
+static int sip_set_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance *instance, struct ast_rtp_instance *vinstance, struct ast_rtp_instance *tinstance, const struct ast_format_cap *cap, int nat_active)
{
struct sip_pvt *p;
int changed = 0;
@@ -27966,8 +28085,8 @@ static int sip_set_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance *i
memset(&p->tredirip, 0, sizeof(p->tredirip));
changed = 1;
}
- if (codecs && (p->redircodecs != codecs)) {
- p->redircodecs = codecs;
+ if (cap && !(ast_format_cap_is_empty(cap) && !(ast_format_cap_identical(p->redircaps, cap)))) {
+ ast_format_cap_copy(p->redircaps, cap);
changed = 1;
}
if (changed && !ast_test_flag(&p->flags[0], SIP_GOTREFER) && !ast_test_flag(&p->flags[0], SIP_DEFER_BYE_ON_TRANSFER)) {
@@ -27990,10 +28109,10 @@ static int sip_set_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance *i
return 0;
}
-static format_t sip_get_codec(struct ast_channel *chan)
+static void sip_get_codec(struct ast_channel *chan, struct ast_format_cap *result)
{
struct sip_pvt *p = chan->tech_pvt;
- return p->peercapability ? p->peercapability : p->capability;
+ ast_format_cap_append(result, ast_format_cap_is_empty(p->peercaps) ? p->caps : p->peercaps);
}
static struct ast_rtp_glue sip_rtp_glue = {
@@ -28955,7 +29074,7 @@ static int peers_data_provider_get(const struct ast_data_search *search,
ast_data_add_str(enum_node, "text", ast_describe_caller_presentation(peer->callingpres));
/* codecs */
- ast_data_add_codecs(data_peer, "codecs", peer->capability);
+ ast_data_add_codecs(data_peer, "codecs", peer->caps);
if (!ast_data_search_match(search, data_peer)) {
ast_data_remove_node(data_root, data_peer);
@@ -28982,6 +29101,10 @@ static const struct ast_data_entry sip_data_providers[] = {
static int load_module(void)
{
ast_verbose("SIP channel loading...\n");
+
+ if (!(sip_tech.capabilities = ast_format_cap_alloc())) {
+ return AST_MODULE_LOAD_FAILURE;
+ }
/* the fact that ao2_containers can't resize automatically is a major worry! */
/* if the number of objects gets above MAX_XXX_BUCKETS, things will slow down */
peers = ao2_t_container_alloc(HASH_PEER_SIZE, peer_hash_cb, peer_cmp_cb, "allocate peers");
@@ -28990,7 +29113,12 @@ static int load_module(void)
dialogs_needdestroy = ao2_t_container_alloc(HASH_DIALOG_SIZE, dialog_hash_cb, dialog_cmp_cb, "allocate dialogs_needdestroy");
dialogs_rtpcheck = ao2_t_container_alloc(HASH_DIALOG_SIZE, dialog_hash_cb, dialog_cmp_cb, "allocate dialogs for rtpchecks");
threadt = ao2_t_container_alloc(HASH_DIALOG_SIZE, threadt_hash_cb, threadt_cmp_cb, "allocate threadt table");
-
+
+ if (!(sip_cfg.caps = ast_format_cap_alloc())) {
+ return AST_MODULE_LOAD_FAILURE;
+ }
+ ast_format_cap_add_all_by_type(sip_tech.capabilities, AST_FORMAT_TYPE_AUDIO);
+
ASTOBJ_CONTAINER_INIT(&regl); /* Registry object list -- not searched for anything */
ASTOBJ_CONTAINER_INIT(&submwil); /* MWI subscription object list */
@@ -29257,6 +29385,9 @@ static int unload_module(void)
sip_reqresp_parser_exit();
sip_unregister_tests();
+ ast_format_cap_destroy(sip_tech.capabilities);
+ sip_cfg.caps = ast_format_cap_destroy(sip_cfg.caps);
+
return 0;
}