diff mgw/gsm2pstn.c @ 205:0047c4c08d9e

mgw: accept the new TRAUlike RTP format in addition to standard, old BFI and zero-length payload formats
author Mychaela Falconia <falcon@freecalypso.org>
date Thu, 06 Apr 2023 19:50:09 -0800
parents e6c7ced3c031
children
line wrap: on
line diff
--- a/mgw/gsm2pstn.c	Tue Apr 04 21:21:04 2023 -0800
+++ b/mgw/gsm2pstn.c	Thu Apr 06 19:50:09 2023 -0800
@@ -17,6 +17,7 @@
 #include <gsm.h>	/* libgsm dependency */
 #include <gsm_fr_preproc.h>
 #include <gsm_efr.h>
+#include "../include/codec_defs.h"
 #include "../include/rtp_defs.h"
 #include "../include/tmgw_ctrl.h"
 #include "../include/tmgw_const.h"
@@ -41,8 +42,9 @@
 	unsigned pktsize;
 	int16_t seq_delta;
 	int32_t ts_delta;
+	uint8_t codec_frame[GSM_FR_BYTES];
 	int16_t pcm_samples[SAMPLES_PER_FRAME];
-	int rc, bfi, taf, m_out;
+	int rc, bfi, bfi_nodata, taf, m_out;
 
 	addrlen = sizeof(struct sockaddr_in);
 	rc = recvfrom(in_fd, &pkt, sizeof pkt, 0,
@@ -70,16 +72,38 @@
 		goto bad_rtp_pkt;
 	if ((pkt.m_pt & 0x7F) != ep->gsm_payload_type)
 		goto bad_rtp_pkt;
-	if (pktsize == ep->gsm_rtp_pkt_size &&
-	    (pkt.payload[0] & 0xF0) == ep->gsm_payload_magic) {
-		bfi = 0;
+	pktsize -= RTP_PACKET_HDR_SIZE;
+	if (!pktsize) {
+		/* zero length payload */
+		bfi = bfi_nodata = 1;
+		taf = 0;
+	} else if (pktsize == ep->gsm_payload_len &&
+		   (pkt.payload[0] & 0xF0) == ep->gsm_payload_magic) {
+		/* standard RFC 3551 or TS 101 318 payload */
+		bfi = bfi_nodata = 0;
 		taf = 0;
-	} else if (pktsize == RTP_PACKET_SIZE_BFI && pkt.payload[0] == 0xBF) {
-		bfi = 1;
+		bcopy(pkt.payload, codec_frame, pktsize);
+	} else if (pktsize == 2 && pkt.payload[0] == 0xBF) {
+		/* old BFI marker */
+		bfi = bfi_nodata = 1;
 		taf = pkt.payload[1] & 1;
-	} else if (pktsize == RTP_PACKET_HDR_SIZE) {
-		bfi = 1;
-		taf = 0;
+	} else if ((pkt.payload[0] & 0xF0) == 0xE0) {
+		/* new TRAUlike RTP payload format */
+		bfi_nodata = (pkt.payload[0] & 0x04) >> 2;
+		bfi = (pkt.payload[0] & 0x02) >> 1;
+		taf = pkt.payload[0] & 0x01;
+		if (bfi_nodata) {
+			if (!bfi)
+				goto bad_rtp_pkt;
+			if (pktsize != 1)
+				goto bad_rtp_pkt;
+		} else {
+			if (pktsize != ep->gsm_payload_len + 1)
+				goto bad_rtp_pkt;
+			if ((pkt.payload[1] & 0xF0) != ep->gsm_payload_magic)
+				goto bad_rtp_pkt;
+			bcopy(pkt.payload+1, codec_frame, ep->gsm_payload_len);
+		}
 	} else
 		goto bad_rtp_pkt;
 	if (ep->g2p_state && pkt.ssrc != ep->g2p_ssrc) {
@@ -127,19 +151,19 @@
 	case GSM_TCHF_FRAME:
 		if (bfi)
 			gsmfr_preproc_bfi(ep->gsm_decoder_extra_state, taf,
-					  pkt.payload);
+					  codec_frame);
 		else
 			gsmfr_preproc_good_frame(ep->gsm_decoder_extra_state,
-						 pkt.payload);
-		gsm_decode(ep->gsm_decoder_state, pkt.payload, pcm_samples);
+						 codec_frame);
+		gsm_decode(ep->gsm_decoder_state, codec_frame, pcm_samples);
 		break;
 	case GSM_TCHF_FRAME_EFR:
-		if (bfi)
+		if (bfi_nodata)
 			EFR_decode_bfi_nodata(ep->gsm_decoder_state, taf,
 					      pcm_samples);
 		else
-			EFR_decode_frame(ep->gsm_decoder_state, pkt.payload,
-					 0, 0, pcm_samples);
+			EFR_decode_frame(ep->gsm_decoder_state, codec_frame,
+					 bfi, taf, pcm_samples);
 		break;
 	}
 	if (ep->dtmf_sample_ptr) {