[Freeswitch-svn] [commit] r11435 - freeswitch/branches/1.0/src

FreeSWITCH SVN mikej at freeswitch.org
Thu Jan 22 15:44:08 PST 2009


Author: mikej
Date: Thu Jan 22 17:44:08 2009
New Revision: 11435

Log:
core: fix multiple 2833 dtmf handling issues (r:11149,11261,11262,11266,11293,11294,11338/FSCORE-266,FSCORE-273)

Modified:
   freeswitch/branches/1.0/src/switch_rtp.c

Modified: freeswitch/branches/1.0/src/switch_rtp.c
==============================================================================
--- freeswitch/branches/1.0/src/switch_rtp.c	(original)
+++ freeswitch/branches/1.0/src/switch_rtp.c	Thu Jan 22 17:44:08 2009
@@ -30,7 +30,7 @@
  * switch_rtp.c -- RTP
  *
  */
-
+//#define DEBUG_2833
 #include <switch.h>
 #include <switch_stun.h>
 #undef PACKAGE_NAME
@@ -111,6 +111,7 @@
 	unsigned int out_digit_dur;
 	uint16_t in_digit_seq;
 	uint32_t in_digit_ts;
+	uint32_t in_digit_sanity;
 	uint32_t timestamp_dtmf;
 	uint16_t last_duration;
 	uint32_t flip;
@@ -1014,6 +1015,7 @@
 
 	switch_mutex_lock(rtp_session->flag_mutex);
 	switch_set_flag(rtp_session, SWITCH_RTP_FLAG_BREAK);
+	switch_set_flag(rtp_session, SWITCH_RTP_FLAG_FLUSH);
 	
 	if (switch_test_flag(rtp_session, SWITCH_RTP_FLAG_NOBLOCK)) {
 		switch_mutex_unlock(rtp_session->flag_mutex);
@@ -1351,6 +1353,8 @@
 			switch_core_timer_next(&rtp_session->timer);
 		}
 
+	recvfrom:
+
 		bytes = sizeof(rtp_msg_t);
 		status = switch_socket_recvfrom(rtp_session->from_addr, rtp_session->sock_input, 0, (void *) &rtp_session->recv_msg, &bytes);
 
@@ -1358,12 +1362,6 @@
 			ret = (int) bytes;
 			goto end;
 		}
-		
-		if (switch_test_flag(rtp_session, SWITCH_RTP_FLAG_FLUSH)) {
-			do_flush(rtp_session);
-			switch_clear_flag_locked(rtp_session, SWITCH_RTP_FLAG_FLUSH);
-			bytes = 0;
-		}
 
 		if (rtp_session->max_missed_packets) {
 			if (bytes) {
@@ -1379,11 +1377,16 @@
 		if (switch_test_flag(rtp_session, SWITCH_RTP_FLAG_BREAK) || (bytes && bytes == 4 && *((int *)&rtp_session->recv_msg) == UINT_MAX)) {
 			switch_clear_flag_locked(rtp_session, SWITCH_RTP_FLAG_BREAK);
 			do_2833(rtp_session);
-			rtp_flush_read_buffer(rtp_session);
 			bytes = 0;
 			return_cng_frame();
 		}
 
+		if (switch_test_flag(rtp_session, SWITCH_RTP_FLAG_FLUSH)) {
+			do_flush(rtp_session);
+			switch_clear_flag_locked(rtp_session, SWITCH_RTP_FLAG_FLUSH);
+			bytes = 0;
+		}
+		
 		if (bytes && bytes < 5) {
 			continue;
 		}
@@ -1541,31 +1544,56 @@
 		}
 
 
+#ifdef DEBUG_2833
+		if (rtp_session->dtmf_data.in_digit_sanity && !(rtp_session->dtmf_data.in_digit_sanity % 100)) {
+			printf("sanity %d\n", rtp_session->dtmf_data.in_digit_sanity);
+		}
+#endif
+
+		if (rtp_session->dtmf_data.in_digit_sanity && !--rtp_session->dtmf_data.in_digit_sanity) {
+			rtp_session->dtmf_data.last_digit = 0;
+			rtp_session->dtmf_data.in_digit_ts = 0;
+			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed DTMF sanity check.\n");
+		}
 
 		/* RFC2833 ... like all RFC RE: VoIP, guaranteed to drive you to insanity! 
 		   We know the real rules here, but if we enforce them, it's an interop nightmare so,
 		   we put up with as much as we can so we don't have to deal with being punished for
 		   doing it right. Nice guys finish last!
 		 */
-		if (bytes && !switch_test_flag(rtp_session, SWITCH_RTP_FLAG_PASS_RFC2833) && rtp_session->recv_msg.header.pt == rtp_session->te) {
+		if (bytes && !switch_test_flag(rtp_session, SWITCH_RTP_FLAG_PROXY_MEDIA) && 
+			!switch_test_flag(rtp_session, SWITCH_RTP_FLAG_PASS_RFC2833) && rtp_session->recv_msg.header.pt == rtp_session->te) {
 			unsigned char *packet = (unsigned char *) rtp_session->recv_msg.body;
 			int end = packet[1] & 0x80 ? 1 : 0;
 			uint16_t duration = (packet[2] << 8) + packet[3];
 			char key = switch_rfc2833_to_char(packet[0]);
 			uint16_t in_digit_seq = ntohs((uint16_t) rtp_session->recv_msg.header.seq);
+			uint32_t ts = htonl(rtp_session->recv_msg.header.ts);
+
+			if (in_digit_seq < rtp_session->dtmf_data.in_digit_seq) {
+				if (rtp_session->dtmf_data.in_digit_seq - in_digit_seq > 100) {
+					rtp_session->dtmf_data.in_digit_seq = 0;
+				}
+			}
 
 			if (in_digit_seq > rtp_session->dtmf_data.in_digit_seq) {
-				uint32_t ts = htonl(rtp_session->recv_msg.header.ts);
-				//int m = rtp_session->recv_msg.header.m;
 
 				rtp_session->dtmf_data.in_digit_seq = in_digit_seq;
-
-				//printf("%c %u %u %u\n", key, in_digit_seq, ts, duration);
+#ifdef DEBUG_2833
+				
+				printf("read: %c %u %u %u %u %d %d %s\n", 
+					   key, in_digit_seq, rtp_session->dtmf_data.in_digit_seq, 
+					   ts, duration, rtp_session->recv_msg.header.m, end, end && !rtp_session->dtmf_data.in_digit_ts ? "ignored" : "");
+#endif
+				/* only set sanity if we do NOT ignore the packet */
+				if (rtp_session->dtmf_data.in_digit_ts) {
+					rtp_session->dtmf_data.in_digit_sanity = 2000;
+				}
 
 				if (rtp_session->dtmf_data.last_duration > duration && ts == rtp_session->dtmf_data.in_digit_ts) {
 					rtp_session->dtmf_data.flip++;
 				}
-
+				
 				if (end) {
 					if (rtp_session->dtmf_data.in_digit_ts) {
 						switch_dtmf_t dtmf = { key, duration };
@@ -1576,28 +1604,53 @@
 						if (rtp_session->dtmf_data.flip) {
 							dtmf.duration += rtp_session->dtmf_data.flip * 0xFFFF;
 							rtp_session->dtmf_data.flip = 0;
-							//printf("you're welcome!\n");
+#ifdef DEBUG_2833
+							printf("you're welcome!\n");
+#endif
 						}
-						//printf("done digit=%c ts=%u start_ts=%u dur=%u ddur=%u\n", 
-						//dtmf.digit, ts, rtp_session->dtmf_data.in_digit_ts, duration, dtmf.duration);
+
+#ifdef DEBUG_2833
+						printf("done digit=%c ts=%u start_ts=%u dur=%u ddur=%u\n", 
+							   dtmf.digit, ts, rtp_session->dtmf_data.in_digit_ts, duration, dtmf.duration);
+#endif
 						switch_rtp_queue_rfc2833_in(rtp_session, &dtmf);
-						switch_set_flag_locked(rtp_session, SWITCH_RTP_FLAG_BREAK);
 						rtp_session->dtmf_data.last_digit = rtp_session->dtmf_data.first_digit;
+
+						rtp_session->dtmf_data.in_digit_ts = 0;
+						rtp_session->dtmf_data.in_digit_sanity = 0;
+						do_cng = 1;
+					} else {
+						if (!switch_rtp_ready(rtp_session)) {
+							goto end;
+						}
+						switch_cond_next();
+						goto recvfrom;
 					}
-					rtp_session->dtmf_data.in_digit_ts = 0;
+
 				} else if (!rtp_session->dtmf_data.in_digit_ts) {
 					rtp_session->dtmf_data.in_digit_ts = ts;
 					rtp_session->dtmf_data.first_digit = key;
+					rtp_session->dtmf_data.in_digit_sanity = 2000;
 				}
 
 				rtp_session->dtmf_data.last_duration = duration;
-
+#ifdef DEBUG_2833
+			} else {
+				printf("drop: %c %u %u %u %u %d %d\n", 
+					   key, in_digit_seq, rtp_session->dtmf_data.in_digit_seq, ts, duration, rtp_session->recv_msg.header.m, end);
+#endif
 			}
-
-			do_cng = 1;
+		}
+		
+		if (rtp_session->dtmf_data.in_digit_ts) {
+			if (!switch_rtp_ready(rtp_session)) {
+				goto end;
+			}
+			switch_cond_next();
+			goto recvfrom;
 		}
 
-	  timer_check:
+	timer_check:
 
 		if (do_cng) {
 			uint8_t *data = (uint8_t *) rtp_session->recv_msg.body;
@@ -1703,10 +1756,6 @@
 	}
 	switch_mutex_unlock(rtp_session->dtmf_data.dtmf_mutex);
 
-	if (bytes) {
-		rtp_flush_read_buffer(rtp_session);
-	}
-
 	return bytes;
 }
 



More information about the Freeswitch-svn mailing list