summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--channels/chan_sip.c7
-rw-r--r--include/asterisk/rtp.h3
-rw-r--r--rtp.c30
3 files changed, 35 insertions, 5 deletions
diff --git a/channels/chan_sip.c b/channels/chan_sip.c
index d623df5ee..189e4f064 100644
--- a/channels/chan_sip.c
+++ b/channels/chan_sip.c
@@ -2195,6 +2195,7 @@ static int create_addr_from_peer(struct sip_pvt *r, struct sip_peer *peer)
ast_rtp_destroy(r->vrtp);
r->vrtp = NULL;
}
+ ast_rtp_setdtmf(r->rtp, ast_test_flag(&r->flags[0], SIP_DTMF) != SIP_DTMF_INFO);
r->prefs = peer->prefs;
natflags = ast_test_flag(&r->flags[0], SIP_NAT) & SIP_NAT_ROUTE;
if (r->rtp) {
@@ -3524,9 +3525,12 @@ static struct sip_pvt *sip_alloc(ast_string_field callid, struct sockaddr_in *si
free(p);
return NULL;
}
+ ast_rtp_setdtmf(p->rtp, ast_test_flag(&p->flags[0], SIP_DTMF) != SIP_DTMF_INFO);
ast_rtp_settos(p->rtp, global_tos_audio);
- if (p->vrtp)
+ if (p->vrtp) {
ast_rtp_settos(p->vrtp, global_tos_video);
+ ast_rtp_setdtmf(p->vrtp, 0);
+ }
p->rtptimeout = global_rtptimeout;
p->rtpholdtimeout = global_rtpholdtimeout;
p->rtpkeepalive = global_rtpkeepalive;
@@ -11170,6 +11174,7 @@ static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, int
get_rdnis(p, NULL); /* Get redirect information */
extract_uri(p, req); /* Get the Contact URI */
build_contact(p); /* Build our contact header */
+ ast_rtp_setdtmf(p->rtp, ast_test_flag(&p->flags[0], SIP_DTMF) != SIP_DTMF_INFO);
if (gotdest) {
if (gotdest == 1 && ast_test_flag(&p->flags[1], SIP_PAGE2_ALLOWOVERLAP)) {
diff --git a/include/asterisk/rtp.h b/include/asterisk/rtp.h
index 7235639f1..5b03d1d86 100644
--- a/include/asterisk/rtp.h
+++ b/include/asterisk/rtp.h
@@ -151,6 +151,9 @@ char *ast_rtp_lookup_mime_multiple(char *buf, int size, const int capability, co
void ast_rtp_setnat(struct ast_rtp *rtp, int nat);
+/*! \brief Indicate whether this RTP session is carrying DTMF or not */
+void ast_rtp_setdtmf(struct ast_rtp *rtp, int dtmf);
+
int ast_rtp_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc, int timeoutms);
int ast_rtp_proto_register(struct ast_rtp_protocol *proto);
diff --git a/rtp.c b/rtp.c
index 841bbbd95..bfb226203 100644
--- a/rtp.c
+++ b/rtp.c
@@ -86,6 +86,7 @@ struct rtpPayloadType {
#define FLAG_NAT_ACTIVE (3 << 1)
#define FLAG_NAT_INACTIVE (0 << 1)
#define FLAG_NAT_INACTIVE_NOWARN (1 << 1)
+#define FLAG_HAS_DTMF (1 << 3)
/*! \brief RTP session description */
struct ast_rtp {
@@ -434,6 +435,11 @@ void ast_rtp_setnat(struct ast_rtp *rtp, int nat)
rtp->nat = nat;
}
+void ast_rtp_setdtmf(struct ast_rtp *rtp, int dtmf)
+{
+ ast_set2_flag(rtp, dtmf ? 1 : 0, FLAG_HAS_DTMF);
+}
+
static struct ast_frame *send_dtmf(struct ast_rtp *rtp)
{
char iabuf[INET_ADDRSTRLEN];
@@ -1344,6 +1350,7 @@ struct ast_rtp *ast_rtp_new_with_bindaddr(struct sched_context *sched, struct io
rtp->s = rtp_socket();
rtp->ssrc = ast_random();
rtp->seqno = ast_random() & 0xffff;
+ ast_set_flag(rtp, FLAG_HAS_DTMF);
if (rtp->s < 0) {
free(rtp);
ast_log(LOG_ERROR, "Unable to allocate socket: %s\n", strerror(errno));
@@ -1921,10 +1928,6 @@ enum ast_bridge_result ast_rtp_bridge(struct ast_channel *c0, struct ast_channel
memset(&vac0, 0, sizeof(vac0));
memset(&vac1, 0, sizeof(vac1));
- /* if need DTMF, cant native bridge */
- if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1))
- return AST_BRIDGE_FAILED_NOWARN;
-
/* Lock channels */
ast_channel_lock(c0);
while(ast_channel_trylock(c1)) {
@@ -1966,6 +1969,25 @@ enum ast_bridge_result ast_rtp_bridge(struct ast_channel *c0, struct ast_channel
ast_channel_unlock(c1);
return AST_BRIDGE_FAILED_NOWARN;
}
+
+ if (ast_test_flag(p0, FLAG_HAS_DTMF) && (flags & AST_BRIDGE_DTMF_CHANNEL_0)) {
+ /* can't bridge, we are carrying DTMF for this channel and the bridge
+ needs it
+ */
+ ast_channel_unlock(c0);
+ ast_channel_unlock(c1);
+ return AST_BRIDGE_FAILED_NOWARN;
+ }
+
+ if (ast_test_flag(p1, FLAG_HAS_DTMF) && (flags & AST_BRIDGE_DTMF_CHANNEL_1)) {
+ /* can't bridge, we are carrying DTMF for this channel and the bridge
+ needs it
+ */
+ ast_channel_unlock(c0);
+ ast_channel_unlock(c1);
+ return AST_BRIDGE_FAILED_NOWARN;
+ }
+
/* Get codecs from both sides */
codec0 = pr0->get_codec ? pr0->get_codec(c0) : 0;
codec1 = pr1->get_codec ? pr1->get_codec(c1) : 0;