mark RTP sessions that are not carrying DTMF
authorKevin P. Fleming <kpfleming@digium.com>
Tue, 16 May 2006 22:11:02 +0000 (22:11 +0000)
committerKevin P. Fleming <kpfleming@digium.com>
Tue, 16 May 2006 22:11:02 +0000 (22:11 +0000)
allow native bridging of RTP sessions that are not carrying DTMF even when the bridge needs to listen to DTMF (when SIP INFO is used for DTMF, for example)

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@27559 65c4cc65-6c06-0410-ace0-fbb531ad65f3

channels/chan_sip.c
include/asterisk/rtp.h
rtp.c

index d623df5..189e4f0 100644 (file)
@@ -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)) {
index 7235639..5b03d1d 100644 (file)
@@ -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 841bbbd..bfb2262 100644 (file)
--- 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;