diff options
author | markster <markster@f38db490-d61c-443f-a65b-d21fe96a405b> | 2006-05-09 11:44:50 +0000 |
---|---|---|
committer | markster <markster@f38db490-d61c-443f-a65b-d21fe96a405b> | 2006-05-09 11:44:50 +0000 |
commit | 3da3803c07ac5061123a9ef505c6506f07a58540 (patch) | |
tree | d57b0a40dccb81bbcb68b1d0c7e720f6a331ffbb /rtp.c | |
parent | faf703671d6bee04df9dc3841c30e37efe1c1c80 (diff) |
Make SIP early media work more efficiently without so many reinvites
git-svn-id: http://svn.digium.com/svn/asterisk/trunk@26019 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'rtp.c')
-rw-r--r-- | rtp.c | 97 |
1 files changed, 92 insertions, 5 deletions
@@ -733,11 +733,83 @@ static struct ast_rtp_protocol *get_proto(struct ast_channel *chan) return cur; } -int ast_rtp_make_compatible(struct ast_channel *dest, struct ast_channel *src) +int ast_rtp_early_media(struct ast_channel *dest, struct ast_channel *src) +{ + struct ast_rtp *destp, *srcp=NULL; /* Audio RTP Channels */ + struct ast_rtp *vdestp, *vsrcp=NULL; /* Video RTP channels */ + struct ast_rtp_protocol *destpr, *srcpr=NULL; + int srccodec; + /* Lock channels */ + ast_channel_lock(dest); + if (src) { + while(ast_channel_trylock(src)) { + ast_channel_unlock(dest); + usleep(1); + ast_channel_lock(dest); + } + } + + /* Find channel driver interfaces */ + destpr = get_proto(dest); + if (src) + srcpr = get_proto(src); + 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; + } + if (!srcpr) { + if (option_debug) + ast_log(LOG_DEBUG, "Channel '%s' has no RTP, not doing anything\n", src->name); + ast_channel_unlock(dest); + if (src) + ast_channel_unlock(src); + return 0; + } + + /* Get audio and video interface (if native bridge is possible) */ + destp = destpr->get_rtp_info(dest); + vdestp = (destpr->get_vrtp_info) ? destpr->get_vrtp_info(dest) : NULL; + if (srcpr) { + srcp = srcpr->get_rtp_info(src); + vsrcp = (srcpr->get_vrtp_info) ? srcpr->get_vrtp_info(src) : NULL; + } + + /* Check if bridge is still possible (In SIP canreinvite=no stops this, like NAT) */ + if (!destp) { + /* Somebody doesn't want to play... */ + ast_channel_unlock(dest); + if (src) + ast_channel_unlock(src); + return 0; + } + if (srcpr && srcpr->get_codec) + srccodec = srcpr->get_codec(src); + else + srccodec = 0; + /* Consider empty media as non-existant */ + if (srcp && !srcp->them.sin_addr.s_addr) + srcp = NULL; + /* Bridge early media */ + 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 send early media to '%s'\n", dest->name, src ? src->name : "<unspecified>"); + ast_channel_unlock(dest); + if (src) + ast_channel_unlock(src); + if (option_debug) + ast_log(LOG_DEBUG, "Setting early media SDP of '%s' with that of '%s'\n", dest->name, src ? src->name : "<unspecified>"); + return 1; +} + +int ast_rtp_make_compatible(struct ast_channel *dest, struct ast_channel *src, int media) { struct ast_rtp *destp, *srcp; /* Audio RTP Channels */ struct ast_rtp *vdestp, *vsrcp; /* Video RTP channels */ struct ast_rtp_protocol *destpr, *srcpr; + int srccodec; /* Lock channels */ ast_channel_lock(dest); while(ast_channel_trylock(src)) { @@ -780,6 +852,15 @@ int ast_rtp_make_compatible(struct ast_channel *dest, struct ast_channel *src) ast_rtp_pt_copy(destp, srcp); if (vdestp && vsrcp) ast_rtp_pt_copy(vdestp, vsrcp); + if (srcpr->get_codec) + srccodec = srcpr->get_codec(src); + else + srccodec = 0; + if (media) { + /* Bridge early media */ + if (destpr->set_rtp_peer(dest, srcp, vsrcp, srccodec, ast_test_flag(srcp, FLAG_NAT_ACTIVE))) + ast_log(LOG_WARNING, "Channel '%s' failed to send early media to '%s'\n", dest->name, src->name); + } ast_channel_unlock(dest); ast_channel_unlock(src); if (option_debug) @@ -1086,11 +1167,17 @@ void ast_rtp_set_peer(struct ast_rtp *rtp, struct sockaddr_in *them) rtp->rxseqno = 0; } -void ast_rtp_get_peer(struct ast_rtp *rtp, struct sockaddr_in *them) +int ast_rtp_get_peer(struct ast_rtp *rtp, struct sockaddr_in *them) { - them->sin_family = AF_INET; - them->sin_port = rtp->them.sin_port; - them->sin_addr = rtp->them.sin_addr; + if ((them->sin_family != AF_INET) || + (them->sin_port != rtp->them.sin_port) || + (them->sin_addr.s_addr != rtp->them.sin_addr.s_addr)) { + them->sin_family = AF_INET; + them->sin_port = rtp->them.sin_port; + them->sin_addr = rtp->them.sin_addr; + return 1; + } + return 0; } void ast_rtp_get_us(struct ast_rtp *rtp, struct sockaddr_in *us) |