Major RTP fixes for using inbound SDP on outbound connection, get rid of
old local rtp stuff... git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@7551 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
parent
93d1d0dcfb
commit
0d32a85be1
|
@ -53,6 +53,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
|||
#include "asterisk/utils.h"
|
||||
#include "asterisk/app.h"
|
||||
#include "asterisk/causes.h"
|
||||
#include "asterisk/rtp.h"
|
||||
#include "asterisk/manager.h"
|
||||
#include "asterisk/privacy.h"
|
||||
|
||||
|
@ -310,7 +311,7 @@ static void hanguptree(struct localuser *outgoing, struct ast_channel *exception
|
|||
} while (0)
|
||||
|
||||
|
||||
static int onedigit_goto(struct ast_channel *chan, char *context, char exten, int pri)
|
||||
static int onedigit_goto(struct ast_channel *chan, const char *context, char exten, int pri)
|
||||
{
|
||||
char rexten[2] = { exten, '\0' };
|
||||
|
||||
|
@ -380,7 +381,7 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in, struct localu
|
|||
int pos;
|
||||
int single;
|
||||
struct ast_channel *winner;
|
||||
char *context = NULL;
|
||||
const char *context = NULL;
|
||||
char cidname[AST_MAX_EXTENSION];
|
||||
|
||||
single = (outgoing && !outgoing->next && !ast_test_flag(outgoing, OPT_MUSICBACK | OPT_RINGBACK));
|
||||
|
@ -475,6 +476,7 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in, struct localu
|
|||
ast_clear_flag(o, DIAL_STILLGOING);
|
||||
HANDLE_CAUSE(cause, in);
|
||||
} else {
|
||||
ast_rtp_make_compatible(o->chan, in);
|
||||
if (o->chan->cid.cid_num)
|
||||
free(o->chan->cid.cid_num);
|
||||
o->chan->cid.cid_num = NULL;
|
||||
|
@ -744,16 +746,17 @@ static int dial_exec_full(struct ast_channel *chan, void *data, struct ast_flags
|
|||
long timelimit = 0;
|
||||
long play_warning = 0;
|
||||
long warning_freq=0;
|
||||
char *warning_sound=NULL;
|
||||
char *end_sound=NULL;
|
||||
char *start_sound=NULL;
|
||||
const char *warning_sound=NULL;
|
||||
const char *end_sound=NULL;
|
||||
const char *start_sound=NULL;
|
||||
char *dtmfcalled=NULL, *dtmfcalling=NULL;
|
||||
char *var;
|
||||
const char *var;
|
||||
char status[256];
|
||||
int play_to_caller=0,play_to_callee=0;
|
||||
int sentringing=0, moh=0;
|
||||
char *outbound_group = NULL;
|
||||
char *macro_result = NULL, *macro_transfer_dest = NULL;
|
||||
const char *outbound_group = NULL;
|
||||
const char *macro_result = NULL;
|
||||
char *macro_transfer_dest = NULL;
|
||||
int digit = 0, result = 0;
|
||||
time_t start_time, answer_time, end_time;
|
||||
struct ast_app *app = NULL;
|
||||
|
@ -1052,6 +1055,9 @@ static int dial_exec_full(struct ast_channel *chan, void *data, struct ast_flags
|
|||
}
|
||||
}
|
||||
|
||||
/* Setup outgoing SDP to match incoming one */
|
||||
ast_rtp_make_compatible(tmp->chan, chan);
|
||||
|
||||
/* Inherit specially named variables from parent channel */
|
||||
ast_channel_inherit_variables(chan, tmp->chan);
|
||||
|
||||
|
@ -1190,7 +1196,7 @@ static int dial_exec_full(struct ast_channel *chan, void *data, struct ast_flags
|
|||
if (peer->name)
|
||||
pbx_builtin_setvar_helper(chan, "DIALEDPEERNAME", peer->name);
|
||||
|
||||
number = pbx_builtin_getvar_helper(peer, "DIALEDPEERNUMBER");
|
||||
number = (char *)pbx_builtin_getvar_helper(peer, "DIALEDPEERNUMBER");
|
||||
if (!number)
|
||||
number = numsubst;
|
||||
pbx_builtin_setvar_helper(chan, "DIALEDPEERNUMBER", number);
|
||||
|
@ -1602,7 +1608,8 @@ static int dial_exec(struct ast_channel *chan, void *data)
|
|||
|
||||
static int retrydial_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
char *announce = NULL, *context = NULL, *dialdata = NULL;
|
||||
char *announce = NULL, *dialdata = NULL;
|
||||
const char *context = NULL;
|
||||
int sleep = 0, loops = 0, res = 0;
|
||||
struct localuser *u;
|
||||
struct ast_flags peerflags;
|
||||
|
|
|
@ -2095,7 +2095,6 @@ static int transmit_modify_with_sdp(struct mgcp_subchannel *sub, struct ast_rtp
|
|||
add_header(&resp, "X", sub->txident);
|
||||
add_header(&resp, "I", sub->cxident);
|
||||
/*add_header(&resp, "S", "");*/
|
||||
ast_rtp_offered_from_local(sub->rtp, 0);
|
||||
add_sdp(&resp, sub, rtp);
|
||||
/* SC: fill in new fields */
|
||||
resp.cmd = MGCP_CMD_MDCX;
|
||||
|
@ -2129,7 +2128,6 @@ static int transmit_connect_with_sdp(struct mgcp_subchannel *sub, struct ast_rtp
|
|||
/* SC: X header should not be sent. kept for compatibility */
|
||||
add_header(&resp, "X", sub->txident);
|
||||
/*add_header(&resp, "S", "");*/
|
||||
ast_rtp_offered_from_local(sub->rtp, 1);
|
||||
add_sdp(&resp, sub, rtp);
|
||||
/* SC: fill in new fields */
|
||||
resp.cmd = MGCP_CMD_CRCX;
|
||||
|
@ -3948,7 +3946,7 @@ static int mgcp_set_rtp_peer(struct ast_channel *chan, struct ast_rtp *rtp, stru
|
|||
/* XXX Is there such thing as video support with MGCP? XXX */
|
||||
struct mgcp_subchannel *sub;
|
||||
sub = chan->tech_pvt;
|
||||
if (sub) {
|
||||
if (sub && !sub->alreadygone) {
|
||||
transmit_modify_with_sdp(sub, rtp, codecs);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -4509,7 +4509,6 @@ static int transmit_response_with_sdp(struct sip_pvt *p, char *msg, struct sip_r
|
|||
}
|
||||
respprep(&resp, p, msg, req);
|
||||
if (p->rtp) {
|
||||
ast_rtp_offered_from_local(p->rtp, 0);
|
||||
add_sdp(&resp, p);
|
||||
} else {
|
||||
ast_log(LOG_ERROR, "Can't add SDP to response, since we have no RTP session allocated. Call-ID %s\n", p->callid);
|
||||
|
@ -4583,7 +4582,6 @@ static int transmit_reinvite_with_sdp(struct sip_pvt *p)
|
|||
add_header(&req, "Allow", ALLOWED_METHODS);
|
||||
if (sipdebug)
|
||||
add_header(&req, "X-asterisk-info", "SIP re-invite (RTP bridge)");
|
||||
ast_rtp_offered_from_local(p->rtp, 1);
|
||||
add_sdp(&req, p);
|
||||
/* Use this as the basis */
|
||||
copy_request(&p->initreq, &req);
|
||||
|
@ -4924,7 +4922,6 @@ static int transmit_invite(struct sip_pvt *p, int sipmethod, int sdp, int init)
|
|||
}
|
||||
}
|
||||
if (sdp && p->rtp) {
|
||||
ast_rtp_offered_from_local(p->rtp, 1);
|
||||
add_sdp(&req, p);
|
||||
} else {
|
||||
add_header_contentLength(&req, 0);
|
||||
|
@ -12691,6 +12688,11 @@ static int sip_set_rtp_peer(struct ast_channel *chan, struct ast_rtp *rtp, struc
|
|||
if (!p)
|
||||
return -1;
|
||||
ast_mutex_lock(&p->lock);
|
||||
if (ast_test_flag(p, SIP_ALREADYGONE)) {
|
||||
/* If we're destroyed, don't bother */
|
||||
ast_mutex_unlock(&p->lock);
|
||||
return 0;
|
||||
}
|
||||
if (rtp)
|
||||
ast_rtp_get_peer(rtp, &p->redirip);
|
||||
else
|
||||
|
|
25
frame.c
25
frame.c
|
@ -1299,3 +1299,28 @@ int ast_frame_slinear_sum(struct ast_frame *f1, struct ast_frame *f2)
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct ast_frame *ast_frame_enqueue(struct ast_frame *head, struct ast_frame *f, int maxlen, int dupe)
|
||||
{
|
||||
struct ast_frame *cur, *oldhead;
|
||||
int len=0;
|
||||
if (f && dupe)
|
||||
f = ast_frdup(f);
|
||||
if (!f)
|
||||
return head;
|
||||
|
||||
f->next = NULL;
|
||||
if (!head)
|
||||
return f;
|
||||
cur = head;
|
||||
while(cur->next) {
|
||||
cur = cur->next;
|
||||
len++;
|
||||
if (len >= maxlen) {
|
||||
oldhead = head;
|
||||
head = head->next;
|
||||
ast_frfree(oldhead);
|
||||
}
|
||||
}
|
||||
return head;
|
||||
}
|
||||
|
|
|
@ -452,6 +452,10 @@ extern int ast_codec_get_samples(struct ast_frame *f);
|
|||
/*! \brief Returns the number of bytes for the number of samples of the given format */
|
||||
extern int ast_codec_get_len(int format, int samples);
|
||||
|
||||
/*! \brief Appends a frame to the end of a list of frames, truncating the maximum length of the list */
|
||||
extern struct ast_frame *ast_frame_enqueue(struct ast_frame *head, struct ast_frame *f, int maxlen, int dupe);
|
||||
|
||||
|
||||
/*! \brief Gets duration in ms of interpolation frame for a format */
|
||||
static inline int ast_codec_interp_len(int format)
|
||||
{
|
||||
|
|
|
@ -135,7 +135,6 @@ void ast_rtp_set_rtpmap_type(struct ast_rtp* rtp, int pt,
|
|||
/* Mapping between RTP payload format codes and Asterisk codes: */
|
||||
struct rtpPayloadType ast_rtp_lookup_pt(struct ast_rtp* rtp, int pt);
|
||||
int ast_rtp_lookup_code(struct ast_rtp* rtp, int isAstFormat, int code);
|
||||
void ast_rtp_offered_from_local(struct ast_rtp* rtp, int local);
|
||||
|
||||
void ast_rtp_get_current_formats(struct ast_rtp* rtp,
|
||||
int* astFormats, int* nonAstFormats);
|
||||
|
@ -154,6 +153,8 @@ int ast_rtp_proto_register(struct ast_rtp_protocol *proto);
|
|||
|
||||
void ast_rtp_proto_unregister(struct ast_rtp_protocol *proto);
|
||||
|
||||
int ast_rtp_make_compatible(struct ast_channel *dest, struct ast_channel *src);
|
||||
|
||||
void ast_rtp_stop(struct ast_rtp *rtp);
|
||||
|
||||
void ast_rtp_init(void);
|
||||
|
|
127
rtp.c
127
rtp.c
|
@ -124,7 +124,6 @@ struct ast_rtp {
|
|||
int rtp_lookup_code_cache_isAstFormat;
|
||||
int rtp_lookup_code_cache_code;
|
||||
int rtp_lookup_code_cache_result;
|
||||
int rtp_offered_from_local;
|
||||
struct ast_rtcp *rtcp;
|
||||
};
|
||||
|
||||
|
@ -724,10 +723,98 @@ void ast_rtp_pt_default(struct ast_rtp* rtp)
|
|||
rtp->rtp_lookup_code_cache_result = 0;
|
||||
}
|
||||
|
||||
static void ast_rtp_pt_copy(struct ast_rtp *dest, struct ast_rtp *src)
|
||||
{
|
||||
int i;
|
||||
/* Copy payload types from source to destination */
|
||||
for (i=0; i < MAX_RTP_PT; ++i) {
|
||||
dest->current_RTP_PT[i].isAstFormat =
|
||||
src->current_RTP_PT[i].isAstFormat;
|
||||
dest->current_RTP_PT[i].code =
|
||||
src->current_RTP_PT[i].code;
|
||||
}
|
||||
dest->rtp_lookup_code_cache_isAstFormat = 0;
|
||||
dest->rtp_lookup_code_cache_code = 0;
|
||||
dest->rtp_lookup_code_cache_result = 0;
|
||||
}
|
||||
|
||||
/*--- get_proto: Get channel driver interface structure */
|
||||
static struct ast_rtp_protocol *get_proto(struct ast_channel *chan)
|
||||
{
|
||||
struct ast_rtp_protocol *cur;
|
||||
|
||||
cur = protos;
|
||||
while(cur) {
|
||||
if (cur->type == chan->type) {
|
||||
return cur;
|
||||
}
|
||||
cur = cur->next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int ast_rtp_make_compatible(struct ast_channel *dest, struct ast_channel *src)
|
||||
{
|
||||
struct ast_rtp *destp, *srcp; /* Audio RTP Channels */
|
||||
struct ast_rtp *vdestp, *vsrcp; /* Video RTP channels */
|
||||
struct ast_rtp_protocol *destpr, *srcpr;
|
||||
/* Lock channels */
|
||||
ast_mutex_lock(&dest->lock);
|
||||
while(ast_mutex_trylock(&src->lock)) {
|
||||
ast_mutex_unlock(&dest->lock);
|
||||
usleep(1);
|
||||
ast_mutex_lock(&dest->lock);
|
||||
}
|
||||
|
||||
/* Find channel driver interfaces */
|
||||
destpr = get_proto(dest);
|
||||
srcpr = get_proto(src);
|
||||
if (!destpr) {
|
||||
ast_log(LOG_DEBUG, "Channel '%s' has no RTP, not doing anything\n", dest->name);
|
||||
ast_mutex_unlock(&dest->lock);
|
||||
ast_mutex_unlock(&src->lock);
|
||||
return 0;
|
||||
}
|
||||
if (!srcpr) {
|
||||
ast_log(LOG_WARNING, "Channel '%s' has no RTP, not doing anything\n", src->name);
|
||||
ast_mutex_unlock(&dest->lock);
|
||||
ast_mutex_unlock(&src->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Get audio and video interface (if native bridge is possible) */
|
||||
destp = destpr->get_rtp_info(dest);
|
||||
if (destpr->get_vrtp_info)
|
||||
vdestp = destpr->get_vrtp_info(dest);
|
||||
else
|
||||
vdestp = NULL;
|
||||
srcp = srcpr->get_rtp_info(src);
|
||||
if (srcpr->get_vrtp_info)
|
||||
vsrcp = srcpr->get_vrtp_info(src);
|
||||
else
|
||||
vsrcp = NULL;
|
||||
|
||||
/* Check if bridge is still possible (In SIP canreinvite=no stops this, like NAT) */
|
||||
if (!destp || !srcp) {
|
||||
/* Somebody doesn't want to play... */
|
||||
ast_mutex_unlock(&dest->lock);
|
||||
ast_mutex_unlock(&src->lock);
|
||||
return 0;
|
||||
}
|
||||
ast_rtp_pt_copy(destp, srcp);
|
||||
if (vdestp && vsrcp)
|
||||
ast_rtp_pt_copy(vdestp, vsrcp);
|
||||
ast_mutex_unlock(&dest->lock);
|
||||
ast_mutex_unlock(&src->lock);
|
||||
ast_log(LOG_DEBUG, "Seeded SDP of '%s' with that of '%s'\n", dest->name, src->name);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Make a note of a RTP paymoad type that was seen in a SDP "m=" line. */
|
||||
/* By default, use the well-known value for this type (although it may */
|
||||
/* still be set to a different value by a subsequent "a=rtpmap:" line): */
|
||||
void ast_rtp_set_m_type(struct ast_rtp* rtp, int pt) {
|
||||
void ast_rtp_set_m_type(struct ast_rtp* rtp, int pt)
|
||||
{
|
||||
if (pt < 0 || pt > MAX_RTP_PT)
|
||||
return; /* bogus payload type */
|
||||
|
||||
|
@ -739,7 +826,9 @@ void ast_rtp_set_m_type(struct ast_rtp* rtp, int pt) {
|
|||
/* Make a note of a RTP payload type (with MIME type) that was seen in */
|
||||
/* a SDP "a=rtpmap:" line. */
|
||||
void ast_rtp_set_rtpmap_type(struct ast_rtp* rtp, int pt,
|
||||
char* mimeType, char* mimeSubtype) {
|
||||
char* mimeType, char* mimeSubtype)
|
||||
|
||||
{
|
||||
int i;
|
||||
|
||||
if (pt < 0 || pt > MAX_RTP_PT)
|
||||
|
@ -770,13 +859,6 @@ void ast_rtp_get_current_formats(struct ast_rtp* rtp,
|
|||
}
|
||||
}
|
||||
|
||||
void ast_rtp_offered_from_local(struct ast_rtp* rtp, int local) {
|
||||
if (rtp)
|
||||
rtp->rtp_offered_from_local = local;
|
||||
else
|
||||
ast_log(LOG_WARNING, "rtp structure is null\n");
|
||||
}
|
||||
|
||||
struct rtpPayloadType ast_rtp_lookup_pt(struct ast_rtp* rtp, int pt)
|
||||
{
|
||||
struct rtpPayloadType result;
|
||||
|
@ -786,8 +868,7 @@ struct rtpPayloadType ast_rtp_lookup_pt(struct ast_rtp* rtp, int pt)
|
|||
return result; /* bogus payload type */
|
||||
|
||||
/* Start with the negotiated codecs */
|
||||
if (!rtp->rtp_offered_from_local)
|
||||
result = rtp->current_RTP_PT[pt];
|
||||
result = rtp->current_RTP_PT[pt];
|
||||
|
||||
/* If it doesn't exist, check our static RTP type list, just in case */
|
||||
if (!result.code)
|
||||
|
@ -829,7 +910,8 @@ int ast_rtp_lookup_code(struct ast_rtp* rtp, const int isAstFormat, const int co
|
|||
return -1;
|
||||
}
|
||||
|
||||
char* ast_rtp_lookup_mime_subtype(const int isAstFormat, const int code) {
|
||||
char* ast_rtp_lookup_mime_subtype(const int isAstFormat, const int code)
|
||||
{
|
||||
|
||||
int i;
|
||||
|
||||
|
@ -1485,21 +1567,6 @@ int ast_rtp_proto_register(struct ast_rtp_protocol *proto)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*--- get_proto: Get channel driver interface structure */
|
||||
static struct ast_rtp_protocol *get_proto(struct ast_channel *chan)
|
||||
{
|
||||
struct ast_rtp_protocol *cur;
|
||||
|
||||
cur = protos;
|
||||
while(cur) {
|
||||
if (cur->type == chan->type) {
|
||||
return cur;
|
||||
}
|
||||
cur = cur->next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* ast_rtp_bridge: Bridge calls. If possible and allowed, initiate
|
||||
re-invite so the peers exchange media directly outside
|
||||
of Asterisk. */
|
||||
|
@ -1698,11 +1765,11 @@ enum ast_bridge_result ast_rtp_bridge(struct ast_channel *c0, struct ast_channel
|
|||
*rc = who;
|
||||
if (option_debug)
|
||||
ast_log(LOG_DEBUG, "Oooh, got a %s\n", f ? "digit" : "hangup");
|
||||
if ((c0->tech_pvt == pvt0) && (!c0->_softhangup)) {
|
||||
if ((c0->tech_pvt == pvt0)) {
|
||||
if (pr0->set_rtp_peer(c0, NULL, NULL, 0, 0))
|
||||
ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name);
|
||||
}
|
||||
if ((c1->tech_pvt == pvt1) && (!c1->_softhangup)) {
|
||||
if ((c1->tech_pvt == pvt1)) {
|
||||
if (pr1->set_rtp_peer(c1, NULL, NULL, 0, 0))
|
||||
ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue