From fa814abe05c2b514286f4e20142e3bb20a1a3492 Mon Sep 17 00:00:00 2001
From: Mark Spencer <markster@digium.com>
Date: Thu, 26 Aug 2004 04:56:26 +0000
Subject: [PATCH] Repair offer/answer model (bug #2293), initial CNG work for
 new frametype

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@3658 65c4cc65-6c06-0410-ace0-fbb531ad65f3
---
 channels/chan_mgcp.c     |  2 ++
 channels/chan_sip.c      |  3 ++
 include/asterisk/frame.h |  5 ++-
 include/asterisk/rtp.h   |  1 +
 rtp.c                    | 66 ++++++++++++++++++----------------------
 5 files changed, 40 insertions(+), 37 deletions(-)

diff --git a/channels/chan_mgcp.c b/channels/chan_mgcp.c
index c0fd5a7d6b..beb80fef6c 100755
--- a/channels/chan_mgcp.c
+++ b/channels/chan_mgcp.c
@@ -1945,6 +1945,7 @@ 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(rtp, 0);
 	add_sdp(&resp, sub, rtp);
     /* SC: fill in new fields */
     resp.cmd = MGCP_CMD_MDCX;
@@ -1978,6 +1979,7 @@ 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(rtp, 1);
 	add_sdp(&resp, sub, rtp);
     /* SC: fill in new fields */
     resp.cmd = MGCP_CMD_CRCX;
diff --git a/channels/chan_sip.c b/channels/chan_sip.c
index b461284d1f..e4f86c1c5a 100755
--- a/channels/chan_sip.c
+++ b/channels/chan_sip.c
@@ -3511,6 +3511,7 @@ static int transmit_response_with_sdp(struct sip_pvt *p, char *msg, struct sip_r
 		return -1;
 	}
 	respprep(&resp, p, msg, req);
+	ast_rtp_offered_from_local(p->rtp, 0);
 	add_sdp(&resp, p);
 	return send_response(p, &resp, retrans, seqno);
 }
@@ -3587,6 +3588,7 @@ static int transmit_reinvite_with_sdp(struct sip_pvt *p)
 		reqprep(&req, p, "INVITE", 0, 1);
 	
 	add_header(&req, "Allow", ALLOWED_METHODS);
+	ast_rtp_offered_from_local(p->rtp, 1);
 	add_sdp(&req, p);
 	/* Use this as the basis */
 	copy_request(&p->initreq, &req);
@@ -3745,6 +3747,7 @@ static int transmit_invite(struct sip_pvt *p, char *cmd, int sdp, char *auth, ch
 	}
 	add_header(&req, "Allow", ALLOWED_METHODS);
 	if (sdp) {
+		ast_rtp_offered_from_local(p->rtp, 1);
 		add_sdp(&req, p);
 	} else {
 		add_header(&req, "Content-Length", "0");
diff --git a/include/asterisk/frame.h b/include/asterisk/frame.h
index b8d6c7d8e9..c80ca72f5a 100755
--- a/include/asterisk/frame.h
+++ b/include/asterisk/frame.h
@@ -118,7 +118,7 @@ struct ast_frame_chain {
 #define AST_FRAME_CONTROL	4
 /*! An empty, useless frame */
 #define AST_FRAME_NULL		5
-/*! Inter Aterisk Exchange private frame type */
+/*! Inter Asterisk Exchange private frame type */
 #define AST_FRAME_IAX		6
 /*! Text messages */
 #define AST_FRAME_TEXT		7
@@ -126,6 +126,9 @@ struct ast_frame_chain {
 #define AST_FRAME_IMAGE		8
 /*! HTML Frame */
 #define AST_FRAME_HTML		9
+/*! Comfort Noise frame (subclass is level of CNG in -dBov), 
+    body may include zero or more 8-bit quantization coefficients */
+#define AST_FRAME_CNG		10
 
 /* HTML subclasses */
 /*! Sending a URL */
diff --git a/include/asterisk/rtp.h b/include/asterisk/rtp.h
index 3d6b0a7932..b8436578cb 100755
--- a/include/asterisk/rtp.h
+++ b/include/asterisk/rtp.h
@@ -89,6 +89,7 @@ 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);
diff --git a/rtp.c b/rtp.c
index 476a9c8360..51b500a961 100755
--- a/rtp.c
+++ b/rtp.c
@@ -5,7 +5,7 @@
  * 	Supports RTP and RTCP with Symmetric RTP support for NAT
  * 	traversal
  * 
- * Copyright (C) 1999, Mark Spencer
+ * Copyright (C) 1999-2004, Digium, Inc.
  *
  * Mark Spencer <markster@digium.com>
  *
@@ -99,6 +99,7 @@ struct ast_rtp {
     int rtp_lookup_code_cache_isAstFormat;	/* a cache for the result of rtp_lookup_code(): */
     int rtp_lookup_code_cache_code;
     int rtp_lookup_code_cache_result;
+    int rtp_offered_from_local;
 	struct ast_rtcp *rtcp;
 };
 
@@ -281,43 +282,28 @@ static struct ast_frame *process_rfc3389(struct ast_rtp *rtp, unsigned char *dat
 	/* Convert comfort noise into audio with various codecs.  Unfortunately this doesn't
 	   totally help us out becuase we don't have an engine to keep it going and we are not
 	   guaranteed to have it every 20ms or anything */
-#if 0
-	printf("RFC3389: %d bytes, format is %d\n", len, rtp->lastrxformat);
+#if 1
+	printf("RFC3389: %d bytes, level %d...\n", len, rtp->lastrxformat);
 #endif	
 	if (!(rtp->flags & FLAG_3389_WARNING)) {
 		ast_log(LOG_NOTICE, "RFC3389 support incomplete.  Turn off on client if possible\n");
 		rtp->flags |= FLAG_3389_WARNING;
 	}
-	if (!rtp->lastrxformat)
-		return 	NULL;
-	switch(rtp->lastrxformat) {
-	case AST_FORMAT_ULAW:
-		rtp->f.frametype = AST_FRAME_VOICE;
-		rtp->f.subclass = AST_FORMAT_ULAW;
-		rtp->f.datalen = 160;
-		rtp->f.samples = 160;
-		memset(rtp->f.data, 0x7f, rtp->f.datalen);
-		f = &rtp->f;
-		break;
-	case AST_FORMAT_ALAW:
-		rtp->f.frametype = AST_FRAME_VOICE;
-		rtp->f.subclass = AST_FORMAT_ALAW;
-		rtp->f.datalen = 160;
-		rtp->f.samples = 160;
-		memset(rtp->f.data, 0x7e, rtp->f.datalen); /* XXX Is this right? XXX */
-		f = &rtp->f;
-		break;
-	case AST_FORMAT_SLINEAR:
-		rtp->f.frametype = AST_FRAME_VOICE;
-		rtp->f.subclass = AST_FORMAT_SLINEAR;
-		rtp->f.datalen = 320;
-		rtp->f.samples = 160;
-		memset(rtp->f.data, 0x00, rtp->f.datalen);
-		f = &rtp->f;
-		break;
-	default:
-		ast_log(LOG_NOTICE, "Don't know how to handle RFC3389 for receive codec %d\n", rtp->lastrxformat);
+	/* Must have at least one byte */
+	if (!len)
+		return NULL;
+	if (len < 24) {
+		rtp->f.datalen = len - 1;
+		memcpy(rtp->f.data, data + 1, len - 1);
+	} else {
+		rtp->f.datalen = 0;
 	}
+	rtp->f.frametype = AST_FRAME_CNG;
+	rtp->f.subclass = data[0] & 0x7f;
+	rtp->f.datalen = len - 1;
+	rtp->f.samples = 0;
+	rtp->f.delivery.tv_usec = rtp->f.delivery.tv_sec = 0;
+	f = &rtp->f;
 	return f;
 }
 
@@ -587,7 +573,7 @@ static struct {
   {{1, AST_FORMAT_SLINEAR}, "audio", "L16"},
   {{1, AST_FORMAT_LPC10}, "audio", "LPC"},
   {{1, AST_FORMAT_G729A}, "audio", "G729"},
-  {{1, AST_FORMAT_SPEEX}, "audio", "SPEEX"},
+  {{1, AST_FORMAT_SPEEX}, "audio", "speex"},
   {{1, AST_FORMAT_ILBC}, "audio", "iLBC"},
   {{0, AST_RTP_DTMF}, "audio", "telephone-event"},
   {{0, AST_RTP_CISCO_DTMF}, "audio", "cisco-telephone-event"},
@@ -698,19 +684,27 @@ 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;
 
+  result.isAstFormat = result.code = 0;
   if (pt < 0 || pt > MAX_RTP_PT) {
-    result.isAstFormat = result.code = 0;
     return result; /* bogus payload type */
   }
   /* Start with the negotiated codecs */
-  result = rtp->current_RTP_PT[pt];
+  if (!rtp->rtp_offered_from_local)
+    result = rtp->current_RTP_PT[pt];
   /* If it doesn't exist, check our static RTP type list, just in case */
   if (!result.code) 
-  	result = static_RTP_PT[pt];
+    result = static_RTP_PT[pt];
   return result;
 }
 
-- 
GitLab