mirror of
https://github.com/asterisk/asterisk.git
synced 2025-11-15 06:18:38 +00:00
SS7 marked the start of an open season for trunk again but here's something minor - abstract early bridging into the technology so that we don't always assume they use RTP and try it.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@43437 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
@@ -575,8 +575,8 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in, struct dial_l
|
||||
OPT_CALLEE_MONITOR | OPT_CALLER_MONITOR |
|
||||
OPT_CALLEE_PARK | OPT_CALLER_PARK |
|
||||
DIAL_NOFORWARDHTML);
|
||||
/* Setup RTP early bridge if appropriate */
|
||||
ast_rtp_early_bridge(in, peer);
|
||||
/* Setup early bridge if appropriate */
|
||||
ast_channel_early_bridge(in, peer);
|
||||
}
|
||||
/* If call has been answered, then the eventual hangup is likely to be normal hangup */
|
||||
in->hangupcause = AST_CAUSE_NORMAL_CLEARING;
|
||||
@@ -605,7 +605,7 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in, struct dial_l
|
||||
ast_verbose(VERBOSE_PREFIX_3 "%s is ringing\n", c->name);
|
||||
/* Setup early media if appropriate */
|
||||
if (single)
|
||||
ast_rtp_early_bridge(in, c);
|
||||
ast_channel_early_bridge(in, c);
|
||||
if (!(*sentringing) && !ast_test_flag(outgoing, OPT_MUSICBACK)) {
|
||||
ast_indicate(in, AST_CONTROL_RINGING);
|
||||
(*sentringing)++;
|
||||
@@ -616,7 +616,7 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in, struct dial_l
|
||||
ast_verbose (VERBOSE_PREFIX_3 "%s is making progress passing it to %s\n", c->name, in->name);
|
||||
/* Setup early media if appropriate */
|
||||
if (single)
|
||||
ast_rtp_early_bridge(in, c);
|
||||
ast_channel_early_bridge(in, c);
|
||||
if (!ast_test_flag(outgoing, OPT_RINGBACK))
|
||||
ast_indicate(in, AST_CONTROL_PROGRESS);
|
||||
break;
|
||||
@@ -629,7 +629,7 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in, struct dial_l
|
||||
if (option_verbose > 2)
|
||||
ast_verbose (VERBOSE_PREFIX_3 "%s is proceeding passing it to %s\n", c->name, in->name);
|
||||
if (single)
|
||||
ast_rtp_early_bridge(in, c);
|
||||
ast_channel_early_bridge(in, c);
|
||||
if (!ast_test_flag(outgoing, OPT_RINGBACK))
|
||||
ast_indicate(in, AST_CONTROL_PROCEEDING);
|
||||
break;
|
||||
@@ -1624,7 +1624,7 @@ out:
|
||||
sentringing = 0;
|
||||
ast_indicate(chan, -1);
|
||||
}
|
||||
ast_rtp_early_bridge(chan, NULL);
|
||||
ast_channel_early_bridge(chan, NULL);
|
||||
hanguptree(outgoing, NULL);
|
||||
pbx_builtin_setvar_helper(chan, "DIALSTATUS", status);
|
||||
if (option_debug)
|
||||
|
||||
@@ -1527,6 +1527,7 @@ static const struct ast_channel_tech sip_tech = {
|
||||
.send_digit_begin = sip_senddigit_begin,
|
||||
.send_digit_end = sip_senddigit_end,
|
||||
.bridge = ast_rtp_bridge,
|
||||
.early_bridge = ast_rtp_early_bridge,
|
||||
.send_text = sip_sendtext,
|
||||
};
|
||||
|
||||
|
||||
@@ -238,6 +238,9 @@ struct ast_channel_tech {
|
||||
enum ast_bridge_result (* const bridge)(struct ast_channel *c0, struct ast_channel *c1, int flags,
|
||||
struct ast_frame **fo, struct ast_channel **rc, int timeoutms);
|
||||
|
||||
/*! \brief Bridge two channels of the same type together (early) */
|
||||
enum ast_bridge_result (* const early_bridge)(struct ast_channel *c0, struct ast_channel *c1);
|
||||
|
||||
/*! \brief Indicate a particular condition (e.g. AST_CONTROL_BUSY or AST_CONTROL_RINGING or AST_CONTROL_CONGESTION */
|
||||
int (* const indicate)(struct ast_channel *c, int condition, const void *data, size_t datalen);
|
||||
|
||||
@@ -965,6 +968,13 @@ int ast_readstring_full(struct ast_channel *c, char *s, int len, int timeout, in
|
||||
* \return Returns 0 on success and -1 if it could not be done */
|
||||
int ast_channel_make_compatible(struct ast_channel *c0, struct ast_channel *c1);
|
||||
|
||||
/*! Bridge two channels together (early)
|
||||
* \param c0 first channel to bridge
|
||||
* \param c1 second channel to bridge
|
||||
* Bridge two channels (c0 and c1) together early. This implies either side may not be answered yet.
|
||||
* \return Returns 0 on success and -1 if it could not be done */
|
||||
int ast_channel_early_bridge(struct ast_channel *c0, struct ast_channel *c1);
|
||||
|
||||
/*! Bridge two channels together
|
||||
* \param c0 first channel to bridge
|
||||
* \param c1 second channel to bridge
|
||||
|
||||
@@ -196,7 +196,7 @@ int ast_rtp_make_compatible(struct ast_channel *dest, struct ast_channel *src, i
|
||||
|
||||
/*! \brief If possible, create an early bridge directly between the devices without
|
||||
having to send a re-invite later */
|
||||
int ast_rtp_early_bridge(struct ast_channel *dest, struct ast_channel *src);
|
||||
int ast_rtp_early_bridge(struct ast_channel *c0, struct ast_channel *c1);
|
||||
|
||||
void ast_rtp_stop(struct ast_rtp *rtp);
|
||||
|
||||
|
||||
@@ -3675,6 +3675,16 @@ static enum ast_bridge_result ast_generic_bridge(struct ast_channel *c0, struct
|
||||
return res;
|
||||
}
|
||||
|
||||
/*! \brief Bridge two channels together (early) */
|
||||
int ast_channel_early_bridge(struct ast_channel *c0, struct ast_channel *c1)
|
||||
{
|
||||
/* Make sure we can early bridge, if not error out */
|
||||
if (!c0->tech->early_bridge || (c1 && (!c1->tech->early_bridge || c0->tech->early_bridge != c1->tech->early_bridge)))
|
||||
return -1;
|
||||
|
||||
return c0->tech->early_bridge(c0, c1);
|
||||
}
|
||||
|
||||
/*! \brief Bridge two channels together */
|
||||
enum ast_bridge_result ast_channel_bridge(struct ast_channel *c0, struct ast_channel *c1,
|
||||
struct ast_bridge_config *config, struct ast_frame **fo, struct ast_channel **rc)
|
||||
|
||||
71
main/rtp.c
71
main/rtp.c
@@ -1374,8 +1374,9 @@ static struct ast_rtp_protocol *get_proto(struct ast_channel *chan)
|
||||
return cur;
|
||||
}
|
||||
|
||||
int ast_rtp_early_bridge(struct ast_channel *dest, struct ast_channel *src)
|
||||
int ast_rtp_early_bridge(struct ast_channel *c0, struct ast_channel *c1)
|
||||
{
|
||||
// dest = c0, src = c1
|
||||
struct ast_rtp *destp = NULL, *srcp = NULL; /* Audio RTP Channels */
|
||||
struct ast_rtp *vdestp = NULL, *vsrcp = NULL; /* Video RTP channels */
|
||||
struct ast_rtp_protocol *destpr = NULL, *srcpr = NULL;
|
||||
@@ -1384,68 +1385,68 @@ int ast_rtp_early_bridge(struct ast_channel *dest, struct ast_channel *src)
|
||||
int srccodec;
|
||||
|
||||
/* Lock channels */
|
||||
ast_channel_lock(dest);
|
||||
if (src) {
|
||||
while(ast_channel_trylock(src)) {
|
||||
ast_channel_unlock(dest);
|
||||
ast_channel_lock(c0);
|
||||
if (c1) {
|
||||
while(ast_channel_trylock(c1)) {
|
||||
ast_channel_unlock(c0);
|
||||
usleep(1);
|
||||
ast_channel_lock(dest);
|
||||
ast_channel_lock(c0);
|
||||
}
|
||||
}
|
||||
|
||||
/* Find channel driver interfaces */
|
||||
destpr = get_proto(dest);
|
||||
if (src)
|
||||
srcpr = get_proto(src);
|
||||
destpr = get_proto(c0);
|
||||
if (c1)
|
||||
srcpr = get_proto(c1);
|
||||
if (!destpr) {
|
||||
if (option_debug)
|
||||
ast_log(LOG_DEBUG, "Channel '%s' has no RTP, not doing anything\n", dest->name);
|
||||
ast_channel_unlock(dest);
|
||||
if (src)
|
||||
ast_channel_unlock(src);
|
||||
return 0;
|
||||
ast_log(LOG_DEBUG, "Channel '%s' has no RTP, not doing anything\n", c0->name);
|
||||
ast_channel_unlock(c0);
|
||||
if (c1)
|
||||
ast_channel_unlock(c1);
|
||||
return -1;
|
||||
}
|
||||
if (!srcpr) {
|
||||
if (option_debug)
|
||||
ast_log(LOG_DEBUG, "Channel '%s' has no RTP, not doing anything\n", src ? src->name : "<unspecified>");
|
||||
ast_channel_unlock(dest);
|
||||
if (src)
|
||||
ast_channel_unlock(src);
|
||||
return 0;
|
||||
ast_log(LOG_DEBUG, "Channel '%s' has no RTP, not doing anything\n", c1 ? c1->name : "<unspecified>");
|
||||
ast_channel_unlock(c0);
|
||||
if (c1)
|
||||
ast_channel_unlock(c1);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Get audio and video interface (if native bridge is possible) */
|
||||
audio_dest_res = destpr->get_rtp_info(dest, &destp);
|
||||
video_dest_res = destpr->get_vrtp_info ? destpr->get_vrtp_info(dest, &vdestp) : AST_RTP_GET_FAILED;
|
||||
audio_dest_res = destpr->get_rtp_info(c0, &destp);
|
||||
video_dest_res = destpr->get_vrtp_info ? destpr->get_vrtp_info(c0, &vdestp) : AST_RTP_GET_FAILED;
|
||||
if (srcpr) {
|
||||
audio_src_res = srcpr->get_rtp_info(src, &srcp);
|
||||
video_src_res = srcpr->get_vrtp_info ? srcpr->get_vrtp_info(src, &vsrcp) : AST_RTP_GET_FAILED;
|
||||
audio_src_res = srcpr->get_rtp_info(c1, &srcp);
|
||||
video_src_res = srcpr->get_vrtp_info ? srcpr->get_vrtp_info(c1, &vsrcp) : AST_RTP_GET_FAILED;
|
||||
}
|
||||
|
||||
/* Check if bridge is still possible (In SIP canreinvite=no stops this, like NAT) */
|
||||
if (audio_dest_res != AST_RTP_TRY_NATIVE) {
|
||||
/* Somebody doesn't want to play... */
|
||||
ast_channel_unlock(dest);
|
||||
if (src)
|
||||
ast_channel_unlock(src);
|
||||
return 0;
|
||||
ast_channel_unlock(c0);
|
||||
if (c1)
|
||||
ast_channel_unlock(c1);
|
||||
return -1;
|
||||
}
|
||||
if (audio_src_res == AST_RTP_TRY_NATIVE && srcpr->get_codec)
|
||||
srccodec = srcpr->get_codec(src);
|
||||
srccodec = srcpr->get_codec(c1);
|
||||
else
|
||||
srccodec = 0;
|
||||
/* Consider empty media as non-existant */
|
||||
if (audio_src_res == AST_RTP_TRY_NATIVE && !srcp->them.sin_addr.s_addr)
|
||||
srcp = NULL;
|
||||
/* Bridge media early */
|
||||
if (destpr->set_rtp_peer(dest, srcp, vsrcp, srccodec, srcp ? ast_test_flag(srcp, FLAG_NAT_ACTIVE) : 0))
|
||||
ast_log(LOG_WARNING, "Channel '%s' failed to setup early bridge to '%s'\n", dest->name, src ? src->name : "<unspecified>");
|
||||
ast_channel_unlock(dest);
|
||||
if (src)
|
||||
ast_channel_unlock(src);
|
||||
if (destpr->set_rtp_peer(c0, srcp, vsrcp, srccodec, srcp ? ast_test_flag(srcp, FLAG_NAT_ACTIVE) : 0))
|
||||
ast_log(LOG_WARNING, "Channel '%s' failed to setup early bridge to '%s'\n", c0->name, c1 ? c1->name : "<unspecified>");
|
||||
ast_channel_unlock(c0);
|
||||
if (c1)
|
||||
ast_channel_unlock(c1);
|
||||
if (option_debug)
|
||||
ast_log(LOG_DEBUG, "Setting early bridge SDP of '%s' with that of '%s'\n", dest->name, src ? src->name : "<unspecified>");
|
||||
return 1;
|
||||
ast_log(LOG_DEBUG, "Setting early bridge SDP of '%s' with that of '%s'\n", c0->name, c1 ? c1->name : "<unspecified>");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ast_rtp_make_compatible(struct ast_channel *dest, struct ast_channel *src, int media)
|
||||
|
||||
Reference in New Issue
Block a user