changeset 10:e686bc92c7d8

revamp for new subdir structure and configure script
author Mychaela Falconia <falcon@freecalypso.org>
date Wed, 15 May 2024 01:44:46 +0000
parents c00510e1ae8b
children 8b047c9bfe5f
files .hgignore Makefile configure net-traffic/Makefile net-traffic/rtp-stream-gen.c net-traffic/udp-test-sink.c pcap-study/Makefile pcap-study/rtp-cont-check.c pcap-study/rtp-g711-extr.c pcap-study/rtp-gsmfr-dump.c pcap-study/rtp-gsmfr-extr.c pcap-study/rtp-jitter-view.c pcap-study/rtp-stream-dump.c pcap-study/rtp-tfo-trace.c rtp-cont-check.c rtp-g711-extr.c rtp-gsmfr-dump.c rtp-gsmfr-extr.c rtp-jitter-view.c rtp-stream-dump.c rtp-stream-gen.c rtp-tfo-trace.c udp-test-sink.c
diffstat 23 files changed, 2120 insertions(+), 2020 deletions(-) [+]
line wrap: on
line diff
--- a/.hgignore	Sun Mar 10 02:27:37 2024 +0000
+++ b/.hgignore	Wed May 15 01:44:46 2024 +0000
@@ -1,13 +1,15 @@
 syntax: regexp
 
 \.[oa]$
+^config\.defs$
 
-^rtp-cont-check$
-^rtp-g711-extr$
-^rtp-gsmfr-dump$
-^rtp-gsmfr-extr$
-^rtp-jitter-view$
-^rtp-stream-dump$
-^rtp-stream-gen$
-^rtp-tfo-trace$
-^udp-test-sink$
+^net-traffic/rtp-stream-gen$
+^net-traffic/udp-test-sink$
+
+^pcap-study/rtp-cont-check$
+^pcap-study/rtp-g711-extr$
+^pcap-study/rtp-gsmfr-dump$
+^pcap-study/rtp-gsmfr-extr$
+^pcap-study/rtp-jitter-view$
+^pcap-study/rtp-stream-dump$
+^pcap-study/rtp-tfo-trace$
--- a/Makefile	Sun Mar 10 02:27:37 2024 +0000
+++ b/Makefile	Wed May 15 01:44:46 2024 +0000
@@ -1,42 +1,20 @@
-CC=	gcc
-CFLAGS=	-O2
-PROGS=	rtp-cont-check rtp-g711-extr rtp-gsmfr-dump rtp-gsmfr-extr \
-	rtp-jitter-view rtp-stream-dump rtp-stream-gen rtp-tfo-trace \
-	udp-test-sink
-INSTBIN=/opt/freecalypso/bin
-
-all:	${PROGS}
+SUBDIR=	net-traffic pcap-study
 
-rtp-cont-check:	rtp-cont-check.c
-	${CC} ${CFLAGS} -o $@ $@.c -lpcap
-
-rtp-g711-extr:	rtp-g711-extr.c
-	${CC} ${CFLAGS} -o $@ $@.c -lpcap
+all:	${SUBDIR}
 
-rtp-gsmfr-dump:	rtp-gsmfr-dump.c
-	${CC} ${CFLAGS} -o $@ $@.c -lpcap -lgsmefr -lgsm
-
-rtp-gsmfr-extr:	rtp-gsmfr-extr.c
-	${CC} ${CFLAGS} -o $@ $@.c -lpcap
+${SUBDIR}: FRC config.defs
+	cd $@; ${MAKE} ${MFLAGS}
 
-rtp-jitter-view:	rtp-jitter-view.c
-	${CC} ${CFLAGS} -o $@ $@.c -lpcap
-
-rtp-stream-dump:	rtp-stream-dump.c
-	${CC} ${CFLAGS} -o $@ $@.c -lpcap
-
-rtp-stream-gen:	rtp-stream-gen.c
-	${CC} ${CFLAGS} -o $@ $@.c
+config.defs:
+	@echo 'You must run ./configure before make'
+	@false
 
-rtp-tfo-trace:	rtp-tfo-trace.c
-	${CC} ${CFLAGS} -o $@ $@.c -lpcap
-
-udp-test-sink:	udp-test-sink.c
-	${CC} ${CFLAGS} -o $@ $@.c
+install:	FRC
+	for i in ${SUBDIR}; do (cd $$i; ${MAKE} ${MFLAGS} \
+		DESTDIR=${DESTDIR} install); done
 
-install:
-	mkdir -p ${INSTBIN}
-	install -c ${PROGS} ${INSTBIN}
+clean: FRC
+	rm -f a.out core errs
+	for i in ${SUBDIR}; do (cd $$i; ${MAKE} ${MFLAGS} clean); done
 
-clean:
-	rm -f *.o *.out ${PROGS}
+FRC:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/configure	Wed May 15 01:44:46 2024 +0000
@@ -0,0 +1,68 @@
+#!/bin/sh
+# This configure script is custom and hand-coded;
+# it is NOT a product of GNU Autoconf or any other such tools!
+
+set -e
+
+if [ ! -f configure ]
+then
+	echo "This script needs to be run from the top of the source tree" 1>&2
+	exit 1
+fi
+
+# defaults that can be overridden
+CC=gcc
+CFLAGS=-O2
+prefix=/usr/local
+exec_prefix=
+bindir=
+
+while [ $# != 0 ]
+do
+	case "$1" in
+		--prefix=*)
+			prefix=`echo $1 | cut -c 10-`
+			;;
+		--exec-prefix=*)
+			exec_prefix=`echo $1 | cut -c 15-`
+			;;
+		--bindir=*)
+			bindir=`echo $1 | cut -c 10-`
+			;;
+		CC=*)
+			CC=`echo $1 | cut -c 4-`
+			;;
+		CFLAGS=*)
+			CFLAGS=`echo $1 | cut -c 8-`
+			;;
+		*)
+			echo "error: non-understood option $1" 1>&2
+			exit 1;
+			;;
+	esac
+	shift
+done
+
+# inheritance rules for install directories
+
+if [ -z "$exec_prefix" ]
+then
+	exec_prefix="$prefix"
+fi
+if [ -z "$bindir" ]
+then
+	bindir="$exec_prefix/bin"
+fi
+
+# report the final configuration
+
+echo "C code will be compiled with:"
+echo "  CC=$CC"
+echo "  CFLAGS=$CFLAGS"
+echo "Installation directory:"
+echo "  bindir=$bindir"
+
+# emit the Makefile include fragment
+echo "CC=$CC" > config.defs
+echo "CFLAGS=$CFLAGS" >> config.defs
+echo "bindir=$bindir" >> config.defs
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/net-traffic/Makefile	Wed May 15 01:44:46 2024 +0000
@@ -0,0 +1,18 @@
+PROGS=	rtp-stream-gen udp-test-sink
+
+include ../config.defs
+
+all:	${PROGS}
+
+rtp-stream-gen:	rtp-stream-gen.c
+	${CC} ${CFLAGS} -o $@ $@.c
+
+udp-test-sink:	udp-test-sink.c
+	${CC} ${CFLAGS} -o $@ $@.c
+
+install:
+	mkdir -p ${DESTDIR}${bindir}
+	install -c ${PROGS} ${DESTDIR}${bindir}
+
+clean:
+	rm -f *.o *.out ${PROGS}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/net-traffic/rtp-stream-gen.c	Wed May 15 01:44:46 2024 +0000
@@ -0,0 +1,162 @@
+/*
+ * This program generates a dummy RTP stream, sending RTP packets with
+ * a dummy payload to the specified destination IP:port, paced in time
+ * every 20 ms.  The purpose is to test the behaviour of affordably-available
+ * Internet connections when presented with such traffic: the intent is
+ * to capture this packet stream on the receiving end with tcpdump and then
+ * analyze the pcap for problem signs of packet loss, jitter and reordering.
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <unistd.h>
+
+#define	RTP_PACKET_HDR_SIZE	12
+#define	RTP_MAX_PAYLOAD		160
+#define	GSM_FR_BYTES		33
+
+struct rtp_packet {
+	uint8_t		v_p_x_cc;
+	uint8_t		m_pt;
+	uint16_t	seq;
+	uint32_t	tstamp;
+	uint32_t	ssrc;
+	uint8_t		payload[RTP_MAX_PAYLOAD];
+};
+
+static const uint8_t gsmfr_silence_frame[GSM_FR_BYTES] = {
+	0xDA, 0xA7, 0xAA, 0xA5, 0x1A,
+	0x50, 0x20, 0x38, 0xE4, 0x6D, 0xB9, 0x1B,
+	0x50, 0x20, 0x38, 0xE4, 0x6D, 0xB9, 0x1B,
+	0x50, 0x20, 0x38, 0xE4, 0x6D, 0xB9, 0x1B,
+	0x50, 0x20, 0x38, 0xE4, 0x6D, 0xB9, 0x1B,
+};
+
+static struct sockaddr_in sin_src, sin_dest;
+static struct rtp_packet rtp_pkt;
+static unsigned rtp_pkt_len, req_packet_count;
+static int udp_fd;
+
+static void
+parse_ip_port(arg, sin)
+	char *arg;
+	struct sockaddr_in *sin;
+{
+	char *cp;
+	int rc;
+
+	cp = index(arg, ':');
+	if (!cp) {
+		fprintf(stderr, "error: missing ':' in IP:port argument\n");
+		exit(1);
+	}
+	*cp++ = '\0';
+	sin->sin_family = AF_INET;
+	rc = inet_aton(arg, &sin->sin_addr);
+	if (!rc) {
+		fprintf(stderr, "error: invalid IP address argument\n");
+		exit(1);
+	}
+	sin->sin_port = htons(atoi(cp));
+}
+
+static void
+prepare_rtp_payload(type_arg)
+	char *type_arg;
+{
+	unsigned pl_len;
+
+	if (!strcmp(type_arg, "pcmu")) {
+		rtp_pkt.m_pt = 0;
+		memset(rtp_pkt.payload, 0xFF, RTP_MAX_PAYLOAD);
+		pl_len = RTP_MAX_PAYLOAD;
+	} else if (!strcmp(type_arg, "pcma")) {
+		rtp_pkt.m_pt = 8;
+		memset(rtp_pkt.payload, 0xD5, RTP_MAX_PAYLOAD);
+		pl_len = RTP_MAX_PAYLOAD;
+	} else if (!strcmp(type_arg, "gsm")) {
+		rtp_pkt.m_pt = 3;
+		memcpy(rtp_pkt.payload, gsmfr_silence_frame, GSM_FR_BYTES);
+		pl_len = GSM_FR_BYTES;
+	} else {
+		fprintf(stderr, "error: invalid PL type argument \"%s\"\n",
+			type_arg);
+		exit(1);
+	}
+	rtp_pkt_len = RTP_PACKET_HDR_SIZE + pl_len;
+}
+
+static void
+assign_rtpout_ssrc()
+{
+	struct timeval curtime;
+
+	gettimeofday(&curtime, 0);
+	rtp_pkt.ssrc = curtime.tv_sec ^ curtime.tv_usec ^ getpid();
+}
+
+static void
+prepare_udp_socket()
+{
+	int rc;
+
+	udp_fd = socket(AF_INET, SOCK_DGRAM, 0);
+	if (udp_fd < 0) {
+		perror("socket(AF_INET, SOCK_DGRAM, 0)");
+		exit(1);
+	}
+	rc = bind(udp_fd, (struct sockaddr *) &sin_src, sizeof sin_src);
+	if (rc < 0) {
+		perror("bind");
+		exit(1);
+	}
+	rc = connect(udp_fd, (struct sockaddr *) &sin_dest, sizeof sin_dest);
+	if (rc < 0) {
+		perror("connect");
+		exit(1);
+	}
+}
+
+static void
+send_out_packets()
+{
+	unsigned n, seq, ts;
+
+	seq = 0;
+	ts = 0;
+	for (n = 0; n < req_packet_count; n++) {
+		rtp_pkt.seq = htons(seq);
+		rtp_pkt.tstamp = htonl(ts);
+		send(udp_fd, &rtp_pkt, rtp_pkt_len, 0);
+		seq++;
+		ts += 160;
+		usleep(20000);
+	}
+}
+
+main(argc, argv)
+	char **argv;
+{
+	if (argc != 5) {
+		fprintf(stderr, "usage: %s src-IP:port dest-IP:port type num\n",
+			argv[0]);
+		exit(1);
+	}
+	parse_ip_port(argv[1], &sin_src);
+	parse_ip_port(argv[2], &sin_dest);
+	prepare_rtp_payload(argv[3]);
+	rtp_pkt.v_p_x_cc = 0x80;
+	assign_rtpout_ssrc();
+	req_packet_count = atoi(argv[4]);
+	prepare_udp_socket();
+	send_out_packets();
+	exit(0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/net-traffic/udp-test-sink.c	Wed May 15 01:44:46 2024 +0000
@@ -0,0 +1,96 @@
+/*
+ * This program is a simple sink for UDP: it binds to a UDP port and sinks
+ * (reads and discards) all packets that arrive at it.  Upon receiving a
+ * burst or stream of packets followed by a prolonged pause, it prints
+ * the number of packets that were received.
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <sys/errno.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <unistd.h>
+
+static void
+parse_ip_port(arg, sin)
+	char *arg;
+	struct sockaddr_in *sin;
+{
+	char *cp;
+	int rc;
+
+	cp = index(arg, ':');
+	if (!cp) {
+		fprintf(stderr, "error: missing ':' in IP:port argument\n");
+		exit(1);
+	}
+	*cp++ = '\0';
+	sin->sin_family = AF_INET;
+	rc = inet_aton(arg, &sin->sin_addr);
+	if (!rc) {
+		fprintf(stderr, "error: invalid IP address argument\n");
+		exit(1);
+	}
+	sin->sin_port = htons(atoi(cp));
+}
+
+main(argc, argv)
+	char **argv;
+{
+	struct sockaddr_in bindsin;
+	int udp_fd, rc;
+	unsigned idle_sec, rx_count;
+	fd_set fds;
+	struct timeval tv;
+	u_char dummybuf[256];
+
+	if (argc < 2 || argc > 3) {
+		fprintf(stderr, "usage: bind-IP:port [idle-sec]\n", argv[0]);
+		exit(1);
+	}
+	parse_ip_port(argv[1], &bindsin);
+	if (argc >= 3)
+		idle_sec = atoi(argv[2]);
+	else
+		idle_sec = 0;
+	udp_fd = socket(AF_INET, SOCK_DGRAM, 0);
+	if (udp_fd < 0) {
+		perror("socket(AF_INET, SOCK_DGRAM, 0)");
+		exit(1);
+	}
+	rc = bind(udp_fd, (struct sockaddr *) &bindsin, sizeof bindsin);
+	if (rc < 0) {
+		perror("bind");
+		exit(1);
+	}
+	for (rx_count = 0; ; ) {
+		FD_ZERO(&fds);
+		FD_SET(udp_fd, &fds);
+		if (rx_count && idle_sec) {
+			tv.tv_sec = idle_sec;
+			tv.tv_usec = 0;
+			rc = select(udp_fd+1, &fds, 0, 0, &tv);
+		} else
+			rc = select(udp_fd+1, &fds, 0, 0, 0);
+		if (rc < 0) {
+			if (errno == EINTR)
+				continue;
+			perror("select");
+			exit(1);
+		}
+		if (FD_ISSET(udp_fd, &fds)) {
+			recv(udp_fd, dummybuf, sizeof dummybuf, 0);
+			rx_count++;
+		} else {
+			printf("Received %u packet%s\n", rx_count,
+				rx_count != 1 ? "s" : "");
+			rx_count = 0;
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pcap-study/Makefile	Wed May 15 01:44:46 2024 +0000
@@ -0,0 +1,34 @@
+PROGS=	rtp-cont-check rtp-g711-extr rtp-gsmfr-dump rtp-gsmfr-extr \
+	rtp-jitter-view rtp-stream-dump rtp-tfo-trace
+
+include ../config.defs
+
+all:	${PROGS}
+
+rtp-cont-check:	rtp-cont-check.c
+	${CC} ${CFLAGS} -o $@ $@.c -lpcap
+
+rtp-g711-extr:	rtp-g711-extr.c
+	${CC} ${CFLAGS} -o $@ $@.c -lpcap
+
+rtp-gsmfr-dump:	rtp-gsmfr-dump.c
+	${CC} ${CFLAGS} -o $@ $@.c -lpcap -lgsmefr -lgsm
+
+rtp-gsmfr-extr:	rtp-gsmfr-extr.c
+	${CC} ${CFLAGS} -o $@ $@.c -lpcap
+
+rtp-jitter-view:	rtp-jitter-view.c
+	${CC} ${CFLAGS} -o $@ $@.c -lpcap
+
+rtp-stream-dump:	rtp-stream-dump.c
+	${CC} ${CFLAGS} -o $@ $@.c -lpcap
+
+rtp-tfo-trace:	rtp-tfo-trace.c
+	${CC} ${CFLAGS} -o $@ $@.c -lpcap
+
+install:
+	mkdir -p ${DESTDIR}${bindir}
+	install -c ${PROGS} ${DESTDIR}${bindir}
+
+clean:
+	rm -f *.o *.out ${PROGS}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pcap-study/rtp-cont-check.c	Wed May 15 01:44:46 2024 +0000
@@ -0,0 +1,234 @@
+/*
+ * This program reads a pcap file, extracts packets belonging to a
+ * particular RTP stream as identified by a source or destination
+ * IP:port, and checks its continuity: verifies that the sequence
+ * number always increments by 1 and that the timestamp always
+ * increments by 160 units.  Finally, this program prints out
+ * the minimum and maximum observed capture time deltas between
+ * successive packets of the stream.
+ *
+ * The codec can be anything, and this program can also be used to
+ * check continuity of RTP streams coming from PSTN/SIP, but the
+ * core assumption is that packets must arrive every 20 ms, with
+ * the timestamp field incrementing by 160 units each time.
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <pcap/pcap.h>
+
+static pcap_t *pcap;
+static in_addr_t match_ip_addr;
+static u_short match_udp_port;
+static unsigned iphdr_addr_offset, udphdr_port_offset;
+static unsigned link_hdr_len, ethertype_offset;
+static int stream_init_flag, deltat_init_flag;
+static unsigned last_seq, last_tstamp, stream_ssrc;
+static struct timeval last_pkt_time;
+static unsigned deltat_min, deltat_max;
+
+static void
+check_dl_type()
+{
+	int dltype;
+
+	dltype = pcap_datalink(pcap);
+	switch (dltype) {
+	case DLT_EN10MB:
+		link_hdr_len = 14;
+		ethertype_offset = 12;
+		break;
+	case DLT_RAW:
+		link_hdr_len = 0;
+		break;
+	case DLT_LINUX_SLL:
+		link_hdr_len = 16;
+		ethertype_offset = 14;
+		break;
+	default:
+		fprintf(stderr, "error: unsupported data link type %d\n",
+			dltype);
+		exit(1);
+	}
+}
+
+static void
+rtp_stream_logic(rtp_hdr, pkt_idx, pkt_time)
+	u_char *rtp_hdr;
+	unsigned pkt_idx;
+	struct timeval *pkt_time;
+{
+	unsigned cur_seq, cur_tstamp, cur_ssrc;
+	struct timeval deltat;
+
+	cur_seq = (rtp_hdr[2] << 8) | rtp_hdr[3];
+	cur_tstamp = (rtp_hdr[4] << 24) | (rtp_hdr[5] << 16) |
+			(rtp_hdr[6] << 8) | rtp_hdr[7];
+	cur_ssrc = (rtp_hdr[8] << 24) | (rtp_hdr[9] << 16) |
+			(rtp_hdr[10] << 8) | rtp_hdr[11];
+	if (stream_init_flag) {
+		if (cur_ssrc != stream_ssrc) {
+			fprintf(stderr,
+		"error in packet #%u: SSRC change from 0x%08X to 0x%08X\n",
+				pkt_idx, stream_ssrc, cur_ssrc);
+			exit(1);
+		}
+		if (cur_seq != last_seq + 1 &&
+		    (cur_seq != 0 || last_seq != 0xFFFF)) {
+			fprintf(stderr,
+		"error in packet #%u: seq break from 0x%04X to 0x%04X\n",
+				pkt_idx, last_seq, cur_seq);
+			exit(1);
+		}
+		if (cur_tstamp != last_tstamp + 160) {
+			fprintf(stderr,
+		"error in packet #%u: timestamp break from 0x%08X to 0x%08X\n",
+				pkt_idx, last_tstamp, cur_tstamp);
+			exit(1);
+		}
+		if (timercmp(pkt_time, &last_pkt_time, <)) {
+			fprintf(stderr,
+			"packet #%u timing error: Rx time goes backward\n",
+				pkt_idx);
+			exit(1);
+		}
+		timersub(pkt_time, &last_pkt_time, &deltat);
+		if (deltat.tv_sec) {
+			fprintf(stderr,
+				"packet #%u timing error: Rx time gap >= 1 s\n",
+				pkt_idx);
+			exit(1);
+		}
+		if (deltat_init_flag) {
+			if (deltat.tv_usec < deltat_min)
+				deltat_min = deltat.tv_usec;
+			if (deltat.tv_usec > deltat_max)
+				deltat_max = deltat.tv_usec;
+		} else {
+			deltat_min = deltat.tv_usec;
+			deltat_max = deltat.tv_usec;
+			deltat_init_flag = 1;
+		}
+	} else {
+		stream_init_flag = 1;
+		stream_ssrc = cur_ssrc;
+	}
+	last_seq = cur_seq;
+	last_tstamp = cur_tstamp;
+	bcopy(pkt_time, &last_pkt_time, sizeof(struct timeval));
+}
+
+static void
+process_packet(pkt, caplen, pkt_idx, pkt_time)
+	u_char *pkt;
+	unsigned caplen, pkt_idx;
+	struct timeval *pkt_time;
+{
+	unsigned udplen;
+
+	if (caplen < link_hdr_len + 28)
+		return;
+	if (link_hdr_len) {
+		if (pkt[ethertype_offset] != 0x08)
+			return;
+		if (pkt[ethertype_offset+1] != 0x00)
+			return;
+		pkt += link_hdr_len;
+		caplen -= link_hdr_len;
+	}
+	/* check IP header */
+	if (pkt[0] != 0x45)
+		return;
+	if (pkt[9] != 17)	/* UDP */
+		return;
+	if (bcmp(pkt + iphdr_addr_offset, &match_ip_addr, 4))
+		return;
+	/* check UDP header */
+	if (bcmp(pkt + 20 + udphdr_port_offset, &match_udp_port, 2))
+		return;
+	/* it is our target - now scrutinize it */
+	udplen = (pkt[24] << 8) | pkt[25];
+	if (caplen < udplen + 20) {
+		fprintf(stderr,
+			"error: packet #%u is truncated in the capture\n",
+			pkt_idx);
+		exit(1);
+	}
+	if (udplen < 20) {
+		fprintf(stderr,
+		"error in packet #%u: UDP length is too short for RTP header\n",
+			pkt_idx);
+		exit(1);
+	}
+	if (pkt[28] != 0x80) {
+		fprintf(stderr,
+		"error in packet #%u: unsupported RTP header structure\n",
+			pkt_idx);
+		exit(1);
+	}
+	rtp_stream_logic(pkt + 28, pkt_idx, pkt_time);
+}
+
+main(argc, argv)
+	char **argv;
+{
+	char errbuf[PCAP_ERRBUF_SIZE];
+	u_char *pkt;
+	struct pcap_pkthdr pkthdr;
+	unsigned pkt_idx;
+
+	if (argc != 5) {
+		fprintf(stderr,
+			"usage: %s pcap-file src|dest ip-addr udp-port\n",
+			argv[0]);
+		exit(1);
+	}
+	pcap = pcap_open_offline(argv[1], errbuf);
+	if (!pcap) {
+		fprintf(stderr, "%s: %s\n", argv[1], errbuf);
+		exit(1);
+	}
+	check_dl_type();
+	if (!strcmp(argv[2], "src")) {
+		iphdr_addr_offset = 12;
+		udphdr_port_offset = 0;
+	} else if (!strcmp(argv[2], "dest")) {
+		iphdr_addr_offset = 16;
+		udphdr_port_offset = 2;
+	} else {
+		fprintf(stderr,
+		"error: direction argument must be \"src\" or \"dest\"\n");
+		exit(1);
+	}
+	match_ip_addr = inet_addr(argv[3]);
+	if (match_ip_addr == INADDR_NONE) {
+		fprintf(stderr, "error: IP address argument is invalid\n");
+		exit(1);
+	}
+	match_udp_port = htons(strtoul(argv[4], 0, 0));
+	for (pkt_idx = 0; ; pkt_idx++) {
+		pkt = pcap_next(pcap, &pkthdr);
+		if (!pkt)
+			break;
+		process_packet(pkt, (unsigned) pkthdr.caplen, pkt_idx,
+				&pkthdr.ts);
+	}
+	if (!stream_init_flag) {
+		fprintf(stderr, "error: specified RTP stream not found\n");
+		exit(1);
+	}
+	if (!deltat_init_flag) {
+		fprintf(stderr, "error: found only one matching packet\n");
+		exit(1);
+	}
+	printf("Minimum time delta: %u us\n", deltat_min);
+	printf("Maximum time delta: %u us\n", deltat_max);
+	exit(0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pcap-study/rtp-g711-extr.c	Wed May 15 01:44:46 2024 +0000
@@ -0,0 +1,212 @@
+/*
+ * This program reads a pcap file, extracts packets belonging to a
+ * particular RTP stream as identified by a source or destination
+ * IP:port, and verifies that an unbroken RTP stream is present,
+ * with 160-byte payloads corresponding to timestamp increments
+ * of 160 units per packet, as expected for a G.711 (PCMU or PCMA)
+ * RTP stream with 20 ms packetization.  The extracted G.711 stream
+ * is written to a raw binary file.
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <pcap/pcap.h>
+
+static pcap_t *pcap;
+static in_addr_t match_ip_addr;
+static u_short match_udp_port;
+static unsigned iphdr_addr_offset, udphdr_port_offset;
+static unsigned link_hdr_len, ethertype_offset;
+static FILE *outfile;
+static int stream_init_flag;
+static unsigned last_seq, last_tstamp, stream_ssrc;
+
+static void
+check_dl_type()
+{
+	int dltype;
+
+	dltype = pcap_datalink(pcap);
+	switch (dltype) {
+	case DLT_EN10MB:
+		link_hdr_len = 14;
+		ethertype_offset = 12;
+		break;
+	case DLT_RAW:
+		link_hdr_len = 0;
+		break;
+	case DLT_LINUX_SLL:
+		link_hdr_len = 16;
+		ethertype_offset = 14;
+		break;
+	default:
+		fprintf(stderr, "error: unsupported data link type %d\n",
+			dltype);
+		exit(1);
+	}
+}
+
+static void
+rtp_stream_logic(rtp_hdr, pkt_idx)
+	u_char *rtp_hdr;
+	unsigned pkt_idx;
+{
+	unsigned cur_seq, cur_tstamp, cur_ssrc;
+
+	cur_seq = (rtp_hdr[2] << 8) | rtp_hdr[3];
+	cur_tstamp = (rtp_hdr[4] << 24) | (rtp_hdr[5] << 16) |
+			(rtp_hdr[6] << 8) | rtp_hdr[7];
+	cur_ssrc = (rtp_hdr[8] << 24) | (rtp_hdr[9] << 16) |
+			(rtp_hdr[10] << 8) | rtp_hdr[11];
+	if (stream_init_flag) {
+		if (cur_ssrc != stream_ssrc) {
+			fprintf(stderr,
+		"error in packet #%u: SSRC change from 0x%08X to 0x%08X\n",
+				pkt_idx, stream_ssrc, cur_ssrc);
+			exit(1);
+		}
+		if (cur_seq != last_seq + 1 &&
+		    (cur_seq != 0 || last_seq != 0xFFFF)) {
+			fprintf(stderr,
+		"error in packet #%u: seq break from 0x%04X to 0x%04X\n",
+				pkt_idx, last_seq, cur_seq);
+			exit(1);
+		}
+		if (cur_tstamp != last_tstamp + 160) {
+			fprintf(stderr,
+		"error in packet #%u: timestamp break from 0x%08X to 0x%08X\n",
+				pkt_idx, last_tstamp, cur_tstamp);
+			exit(1);
+		}
+	} else {
+		stream_init_flag = 1;
+		stream_ssrc = cur_ssrc;
+	}
+	last_seq = cur_seq;
+	last_tstamp = cur_tstamp;
+}
+
+static void
+process_packet(pkt, caplen, pkt_idx)
+	u_char *pkt;
+	unsigned caplen, pkt_idx;
+{
+	unsigned udplen, payload_len;
+
+	if (caplen < link_hdr_len + 28)
+		return;
+	if (link_hdr_len) {
+		if (pkt[ethertype_offset] != 0x08)
+			return;
+		if (pkt[ethertype_offset+1] != 0x00)
+			return;
+		pkt += link_hdr_len;
+		caplen -= link_hdr_len;
+	}
+	/* check IP header */
+	if (pkt[0] != 0x45)
+		return;
+	if (pkt[9] != 17)	/* UDP */
+		return;
+	if (bcmp(pkt + iphdr_addr_offset, &match_ip_addr, 4))
+		return;
+	/* check UDP header */
+	if (bcmp(pkt + 20 + udphdr_port_offset, &match_udp_port, 2))
+		return;
+	/* it is our target - now scrutinize it */
+	udplen = (pkt[24] << 8) | pkt[25];
+	if (caplen < udplen + 20) {
+		fprintf(stderr,
+			"error: packet #%u is truncated in the capture\n",
+			pkt_idx);
+		exit(1);
+	}
+	if (udplen < 20) {
+		fprintf(stderr,
+		"error in packet #%u: UDP length is too short for RTP header\n",
+			pkt_idx);
+		exit(1);
+	}
+	if (pkt[28] != 0x80) {
+		fprintf(stderr,
+		"error in packet #%u: unsupported RTP header structure\n",
+			pkt_idx);
+		exit(1);
+	}
+	rtp_stream_logic(pkt + 28, pkt_idx);
+	payload_len = udplen - 20;
+	if (payload_len != 160) {
+		fprintf(stderr, "error in packet #%u: unsupported payload\n",
+			pkt_idx);
+		exit(1);
+	}
+	fwrite(pkt + 40, 1, payload_len, outfile);
+}
+
+main(argc, argv)
+	char **argv;
+{
+	char errbuf[PCAP_ERRBUF_SIZE];
+	u_char *pkt;
+	struct pcap_pkthdr pkthdr;
+	unsigned pkt_idx, skip_num;
+
+	if (argc < 6 || argc > 7) {
+		fprintf(stderr,
+	"usage: %s pcap-file src|dest ip-addr udp-port outfile [skip-count]\n",
+			argv[0]);
+		exit(1);
+	}
+	pcap = pcap_open_offline(argv[1], errbuf);
+	if (!pcap) {
+		fprintf(stderr, "%s: %s\n", argv[1], errbuf);
+		exit(1);
+	}
+	check_dl_type();
+	if (!strcmp(argv[2], "src")) {
+		iphdr_addr_offset = 12;
+		udphdr_port_offset = 0;
+	} else if (!strcmp(argv[2], "dest")) {
+		iphdr_addr_offset = 16;
+		udphdr_port_offset = 2;
+	} else {
+		fprintf(stderr,
+		"error: direction argument must be \"src\" or \"dest\"\n");
+		exit(1);
+	}
+	match_ip_addr = inet_addr(argv[3]);
+	if (match_ip_addr == INADDR_NONE) {
+		fprintf(stderr, "error: IP address argument is invalid\n");
+		exit(1);
+	}
+	match_udp_port = htons(strtoul(argv[4], 0, 0));
+	outfile = fopen(argv[5], "w");
+	if (!outfile) {
+		perror(argv[5]);
+		exit(1);
+	}
+	if (argv[6])
+		skip_num = strtoul(argv[6], 0, 0);
+	else
+		skip_num = 0;
+	for (pkt_idx = 0; ; pkt_idx++) {
+		pkt = pcap_next(pcap, &pkthdr);
+		if (!pkt)
+			break;
+		if (pkt_idx < skip_num)
+			continue;
+		process_packet(pkt, (unsigned) pkthdr.caplen, pkt_idx);
+	}
+	if (!stream_init_flag) {
+		fprintf(stderr, "error: specified RTP stream not found\n");
+		exit(1);
+	}
+	fclose(outfile);
+	exit(0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pcap-study/rtp-gsmfr-dump.c	Wed May 15 01:44:46 2024 +0000
@@ -0,0 +1,276 @@
+/*
+ * This program is a combination of rtp-gsmfr-extr and gsmrec-dump into
+ * one step: it reads a pcap file, extracts packets belonging to a
+ * particular RTP stream as identified by a source or destination
+ * IP:port, verifies that an unbroken RTP stream is present, which is
+ * expected to be in GSM FR or EFR codec, but instead of writing this
+ * FR/EFR frame stream to a gsmx file, decodes it like gsmrec-dump.
+ *
+ * The advantage of this program over running rtp-gsmfr-extr followed
+ * by gsmrec-dump is that TRAUlike Extension Headers (if present) are
+ * dumped for analysis, rather than discarded.
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <pcap/pcap.h>
+#include <gsm.h>
+#include <gsm_efr.h>
+
+static pcap_t *pcap;
+static in_addr_t match_ip_addr;
+static u_short match_udp_port;
+static unsigned iphdr_addr_offset, udphdr_port_offset;
+static unsigned link_hdr_len, ethertype_offset;
+static int stream_init_flag;
+static unsigned last_seq, last_tstamp, stream_ssrc;
+static gsm dummy_state;
+
+static void
+check_dl_type()
+{
+	int dltype;
+
+	dltype = pcap_datalink(pcap);
+	switch (dltype) {
+	case DLT_EN10MB:
+		link_hdr_len = 14;
+		ethertype_offset = 12;
+		break;
+	case DLT_RAW:
+		link_hdr_len = 0;
+		break;
+	case DLT_LINUX_SLL:
+		link_hdr_len = 16;
+		ethertype_offset = 14;
+		break;
+	default:
+		fprintf(stderr, "error: unsupported data link type %d\n",
+			dltype);
+		exit(1);
+	}
+}
+
+static void
+rtp_stream_logic(rtp_hdr, pkt_idx)
+	u_char *rtp_hdr;
+	unsigned pkt_idx;
+{
+	unsigned cur_seq, cur_tstamp, cur_ssrc;
+
+	cur_seq = (rtp_hdr[2] << 8) | rtp_hdr[3];
+	cur_tstamp = (rtp_hdr[4] << 24) | (rtp_hdr[5] << 16) |
+			(rtp_hdr[6] << 8) | rtp_hdr[7];
+	cur_ssrc = (rtp_hdr[8] << 24) | (rtp_hdr[9] << 16) |
+			(rtp_hdr[10] << 8) | rtp_hdr[11];
+	if (stream_init_flag) {
+		if (cur_ssrc != stream_ssrc) {
+			printf(
+		"error in packet #%u: SSRC change from 0x%08X to 0x%08X\n",
+				pkt_idx, stream_ssrc, cur_ssrc);
+		} else if (cur_seq != last_seq + 1 &&
+			   (cur_seq != 0 || last_seq != 0xFFFF)) {
+			printf(
+		"error in packet #%u: seq break from 0x%04X to 0x%04X\n",
+				pkt_idx, last_seq, cur_seq);
+		} else if (cur_tstamp != last_tstamp + 160) {
+			printf(
+		"error in packet #%u: timestamp break from 0x%08X to 0x%08X\n",
+				pkt_idx, last_tstamp, cur_tstamp);
+		}
+	} else
+		stream_init_flag = 1;
+	last_seq = cur_seq;
+	last_tstamp = cur_tstamp;
+	stream_ssrc = cur_ssrc;
+}
+
+static void
+process_payload(payload, payload_len)
+	u_char *payload;
+	unsigned payload_len;
+{
+	gsm_signal params[76];
+	int i, j, n;
+
+	printf("seq 0x%04X ts 0x%08X: ", last_seq, last_tstamp);
+	switch (payload_len) {
+	case 0:
+		printf("zero-length payload\n");
+		return;
+	case 1:
+		if ((payload[0] & 0xF6) != 0xE6)
+			break;
+		printf("TEH 0x%02X\n", payload[0]);
+		return;
+	case 2:
+		if (payload[0] != 0xBF)
+			break;
+		printf("old BFI TAF=%u\n", payload[1] & 1);
+		return;
+	case 31:
+		if ((payload[0] & 0xF0) != 0xC0)
+			break;
+		printf("std EFR SID=%d LPC", EFR_sid_classify(payload));
+		EFR_frame2params(payload, params);
+	print_efr:
+		n = 0;
+		for (i = 0; i < 5; i++)
+			printf(" %d", params[n++]);
+		putchar('\n');
+		for (i = 0; i < 4; i++) {
+			putchar(' ');
+			for (j = 0; j < 13; j++)
+				printf(" %d", params[n++]);
+			putchar('\n');
+		}
+		return;
+	case 32:
+		if ((payload[0] & 0xF4) != 0xE0)
+			break;
+		if ((payload[1] & 0xF0) != 0xC0)
+			break;
+		printf("TEH 0x%02X EFR SID=%d LPC", payload[0],
+			EFR_sid_classify(payload+1));
+		EFR_frame2params(payload+1, params);
+		goto print_efr;
+	case 33:
+		if ((payload[0] & 0xF0) != 0xD0)
+			break;
+		fputs("std FR", stdout);
+		gsm_explode(dummy_state, payload, params);
+	print_fr:
+		n = 0;
+		for (i = 0; i < 8; i++)
+			printf(" %d", params[n++]);
+		putchar('\n');
+		for (i = 0; i < 4; i++) {
+			putchar(' ');
+			for (j = 0; j < 17; j++)
+				printf(" %d", params[n++]);
+			putchar('\n');
+		}
+		return;
+	case 34:
+		if ((payload[0] & 0xF4) != 0xE0)
+			break;
+		if ((payload[1] & 0xF0) != 0xD0)
+			break;
+		printf("TEH 0x%02X FR", payload[0]);
+		gsm_explode(dummy_state, payload+1, params);
+		goto print_fr;
+	}
+	printf("unknown payload format, length=%u\n", payload_len);
+}
+
+static void
+process_packet(pkt, caplen, pkt_idx)
+	u_char *pkt;
+	unsigned caplen, pkt_idx;
+{
+	unsigned udplen, payload_len;
+
+	if (caplen < link_hdr_len + 28)
+		return;
+	if (link_hdr_len) {
+		if (pkt[ethertype_offset] != 0x08)
+			return;
+		if (pkt[ethertype_offset+1] != 0x00)
+			return;
+		pkt += link_hdr_len;
+		caplen -= link_hdr_len;
+	}
+	/* check IP header */
+	if (pkt[0] != 0x45)
+		return;
+	if (pkt[9] != 17)	/* UDP */
+		return;
+	if (bcmp(pkt + iphdr_addr_offset, &match_ip_addr, 4))
+		return;
+	/* check UDP header */
+	if (bcmp(pkt + 20 + udphdr_port_offset, &match_udp_port, 2))
+		return;
+	/* it is our target - now scrutinize it */
+	udplen = (pkt[24] << 8) | pkt[25];
+	if (caplen < udplen + 20) {
+		fprintf(stderr,
+			"error: packet #%u is truncated in the capture\n",
+			pkt_idx);
+		exit(1);
+	}
+	if (udplen < 20) {
+		fprintf(stderr,
+		"error in packet #%u: UDP length is too short for RTP header\n",
+			pkt_idx);
+		exit(1);
+	}
+	if (pkt[28] != 0x80) {
+		fprintf(stderr,
+		"error in packet #%u: unsupported RTP header structure\n",
+			pkt_idx);
+		exit(1);
+	}
+	rtp_stream_logic(pkt + 28, pkt_idx);
+	process_payload(pkt + 40, udplen - 20);
+}
+
+main(argc, argv)
+	char **argv;
+{
+	char errbuf[PCAP_ERRBUF_SIZE];
+	u_char *pkt;
+	struct pcap_pkthdr pkthdr;
+	unsigned pkt_idx;
+
+	if (argc != 5) {
+		fprintf(stderr,
+			"usage: %s pcap-file src|dest ip-addr udp-port\n",
+			argv[0]);
+		exit(1);
+	}
+	pcap = pcap_open_offline(argv[1], errbuf);
+	if (!pcap) {
+		fprintf(stderr, "%s: %s\n", argv[1], errbuf);
+		exit(1);
+	}
+	check_dl_type();
+	if (!strcmp(argv[2], "src")) {
+		iphdr_addr_offset = 12;
+		udphdr_port_offset = 0;
+	} else if (!strcmp(argv[2], "dest")) {
+		iphdr_addr_offset = 16;
+		udphdr_port_offset = 2;
+	} else {
+		fprintf(stderr,
+		"error: direction argument must be \"src\" or \"dest\"\n");
+		exit(1);
+	}
+	match_ip_addr = inet_addr(argv[3]);
+	if (match_ip_addr == INADDR_NONE) {
+		fprintf(stderr, "error: IP address argument is invalid\n");
+		exit(1);
+	}
+	match_udp_port = htons(strtoul(argv[4], 0, 0));
+	dummy_state = gsm_create();
+	if (!dummy_state) {
+		fprintf(stderr, "gsm_create() failed!\n");
+		exit(1);
+	}
+	for (pkt_idx = 0; ; pkt_idx++) {
+		pkt = pcap_next(pcap, &pkthdr);
+		if (!pkt)
+			break;
+		process_packet(pkt, (unsigned) pkthdr.caplen, pkt_idx);
+	}
+	if (!stream_init_flag) {
+		fprintf(stderr, "error: specified RTP stream not found\n");
+		exit(1);
+	}
+	exit(0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pcap-study/rtp-gsmfr-extr.c	Wed May 15 01:44:46 2024 +0000
@@ -0,0 +1,249 @@
+/*
+ * This program reads a pcap file, extracts packets belonging to a
+ * particular RTP stream as identified by a source or destination
+ * IP:port, verifies that an unbroken RTP stream is present, in
+ * GSM FR or EFR codec, and writes the FR/EFR frame stream to our
+ * extended-libgsm format binary file, to be fed to decoding test
+ * programs.
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <pcap/pcap.h>
+
+static pcap_t *pcap;
+static in_addr_t match_ip_addr;
+static u_short match_udp_port;
+static unsigned iphdr_addr_offset, udphdr_port_offset;
+static unsigned link_hdr_len, ethertype_offset;
+static FILE *outfile;
+static int stream_init_flag;
+static unsigned last_seq, last_tstamp, stream_ssrc;
+
+static void
+check_dl_type()
+{
+	int dltype;
+
+	dltype = pcap_datalink(pcap);
+	switch (dltype) {
+	case DLT_EN10MB:
+		link_hdr_len = 14;
+		ethertype_offset = 12;
+		break;
+	case DLT_RAW:
+		link_hdr_len = 0;
+		break;
+	case DLT_LINUX_SLL:
+		link_hdr_len = 16;
+		ethertype_offset = 14;
+		break;
+	default:
+		fprintf(stderr, "error: unsupported data link type %d\n",
+			dltype);
+		exit(1);
+	}
+}
+
+static void
+rtp_stream_logic(rtp_hdr, pkt_idx)
+	u_char *rtp_hdr;
+	unsigned pkt_idx;
+{
+	unsigned cur_seq, cur_tstamp, cur_ssrc;
+
+	cur_seq = (rtp_hdr[2] << 8) | rtp_hdr[3];
+	cur_tstamp = (rtp_hdr[4] << 24) | (rtp_hdr[5] << 16) |
+			(rtp_hdr[6] << 8) | rtp_hdr[7];
+	cur_ssrc = (rtp_hdr[8] << 24) | (rtp_hdr[9] << 16) |
+			(rtp_hdr[10] << 8) | rtp_hdr[11];
+	if (stream_init_flag) {
+		if (cur_ssrc != stream_ssrc) {
+			fprintf(stderr,
+		"error in packet #%u: SSRC change from 0x%08X to 0x%08X\n",
+				pkt_idx, stream_ssrc, cur_ssrc);
+			exit(1);
+		}
+		if (cur_seq != last_seq + 1 &&
+		    (cur_seq != 0 || last_seq != 0xFFFF)) {
+			fprintf(stderr,
+		"error in packet #%u: seq break from 0x%04X to 0x%04X\n",
+				pkt_idx, last_seq, cur_seq);
+			exit(1);
+		}
+		if (cur_tstamp != last_tstamp + 160) {
+			fprintf(stderr,
+		"error in packet #%u: timestamp break from 0x%08X to 0x%08X\n",
+				pkt_idx, last_tstamp, cur_tstamp);
+			exit(1);
+		}
+	} else {
+		stream_init_flag = 1;
+		stream_ssrc = cur_ssrc;
+	}
+	last_seq = cur_seq;
+	last_tstamp = cur_tstamp;
+}
+
+static void
+process_packet(pkt, caplen, pkt_idx)
+	u_char *pkt;
+	unsigned caplen, pkt_idx;
+{
+	unsigned udplen, payload_len;
+	u_char synth_bfi[2];
+
+	if (caplen < link_hdr_len + 28)
+		return;
+	if (link_hdr_len) {
+		if (pkt[ethertype_offset] != 0x08)
+			return;
+		if (pkt[ethertype_offset+1] != 0x00)
+			return;
+		pkt += link_hdr_len;
+		caplen -= link_hdr_len;
+	}
+	/* check IP header */
+	if (pkt[0] != 0x45)
+		return;
+	if (pkt[9] != 17)	/* UDP */
+		return;
+	if (bcmp(pkt + iphdr_addr_offset, &match_ip_addr, 4))
+		return;
+	/* check UDP header */
+	if (bcmp(pkt + 20 + udphdr_port_offset, &match_udp_port, 2))
+		return;
+	/* it is our target - now scrutinize it */
+	udplen = (pkt[24] << 8) | pkt[25];
+	if (caplen < udplen + 20) {
+		fprintf(stderr,
+			"error: packet #%u is truncated in the capture\n",
+			pkt_idx);
+		exit(1);
+	}
+	if (udplen < 20) {
+		fprintf(stderr,
+		"error in packet #%u: UDP length is too short for RTP header\n",
+			pkt_idx);
+		exit(1);
+	}
+	if (pkt[28] != 0x80) {
+		fprintf(stderr,
+		"error in packet #%u: unsupported RTP header structure\n",
+			pkt_idx);
+		exit(1);
+	}
+	rtp_stream_logic(pkt + 28, pkt_idx);
+	payload_len = udplen - 20;
+	switch (payload_len) {
+	case 0:
+		synth_bfi[0] = 0xBF;
+		synth_bfi[1] = 0;
+	emit_synth_bfi:
+		fwrite(synth_bfi, 1, 2, outfile);
+		return;
+	case 1:
+		if ((pkt[40] & 0xF6) != 0xE6)
+			break;
+	traulike_bfi:
+		synth_bfi[0] = 0xBF;
+		synth_bfi[1] = pkt[40] & 1;
+		goto emit_synth_bfi;
+	case 2:
+		if (pkt[40] != 0xBF)
+			break;
+	emit_payload:
+		fwrite(pkt + 40, 1, payload_len, outfile);
+		return;
+	case 31:
+		if ((pkt[40] & 0xF0) != 0xC0)
+			break;
+		goto emit_payload;
+	case 32:
+		if ((pkt[40] & 0xF4) != 0xE0)
+			break;
+		if ((pkt[41] & 0xF0) != 0xC0)
+			break;
+		if (pkt[40] & 2)
+			goto traulike_bfi;
+		fwrite(pkt + 41, 1, 31, outfile);
+		return;
+	case 33:
+		if ((pkt[40] & 0xF0) != 0xD0)
+			break;
+		goto emit_payload;
+	case 34:
+		if ((pkt[40] & 0xF4) != 0xE0)
+			break;
+		if ((pkt[41] & 0xF0) != 0xD0)
+			break;
+		if (pkt[40] & 2)
+			goto traulike_bfi;
+		fwrite(pkt + 41, 1, 33, outfile);
+		return;
+	}
+	fprintf(stderr, "error in packet #%u: unsupported payload\n", pkt_idx);
+	exit(1);
+}
+
+main(argc, argv)
+	char **argv;
+{
+	char errbuf[PCAP_ERRBUF_SIZE];
+	u_char *pkt;
+	struct pcap_pkthdr pkthdr;
+	unsigned pkt_idx;
+
+	if (argc != 6) {
+		fprintf(stderr,
+		"usage: %s pcap-file src|dest ip-addr udp-port outfile\n",
+			argv[0]);
+		exit(1);
+	}
+	pcap = pcap_open_offline(argv[1], errbuf);
+	if (!pcap) {
+		fprintf(stderr, "%s: %s\n", argv[1], errbuf);
+		exit(1);
+	}
+	check_dl_type();
+	if (!strcmp(argv[2], "src")) {
+		iphdr_addr_offset = 12;
+		udphdr_port_offset = 0;
+	} else if (!strcmp(argv[2], "dest")) {
+		iphdr_addr_offset = 16;
+		udphdr_port_offset = 2;
+	} else {
+		fprintf(stderr,
+		"error: direction argument must be \"src\" or \"dest\"\n");
+		exit(1);
+	}
+	match_ip_addr = inet_addr(argv[3]);
+	if (match_ip_addr == INADDR_NONE) {
+		fprintf(stderr, "error: IP address argument is invalid\n");
+		exit(1);
+	}
+	match_udp_port = htons(strtoul(argv[4], 0, 0));
+	outfile = fopen(argv[5], "w");
+	if (!outfile) {
+		perror(argv[5]);
+		exit(1);
+	}
+	for (pkt_idx = 0; ; pkt_idx++) {
+		pkt = pcap_next(pcap, &pkthdr);
+		if (!pkt)
+			break;
+		process_packet(pkt, (unsigned) pkthdr.caplen, pkt_idx);
+	}
+	if (!stream_init_flag) {
+		fprintf(stderr, "error: specified RTP stream not found\n");
+		exit(1);
+	}
+	fclose(outfile);
+	exit(0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pcap-study/rtp-jitter-view.c	Wed May 15 01:44:46 2024 +0000
@@ -0,0 +1,220 @@
+/*
+ * This program reads a pcap file, extracts packets belonging to a
+ * particular RTP stream as identified by a source or destination
+ * IP:port, checks its continuity at the packet header level
+ * (verifies that the sequence number always increments by 1 and
+ * that the timestamp always increments by 160 units) and prints out
+ * the Rx time delta of each stream packet (the capture time of
+ * the current packet minus the capture time of the previous packet)
+ * on stdout, allowing visual analysis of timing jitter.
+ *
+ * The codec can be anything, and this program can also be used to
+ * examine the jitter of RTP streams coming from PSTN/SIP, but the
+ * core assumption is that packets must arrive every 20 ms, with
+ * the timestamp field incrementing by 160 units each time.
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <pcap/pcap.h>
+
+static pcap_t *pcap;
+static in_addr_t match_ip_addr;
+static u_short match_udp_port;
+static unsigned iphdr_addr_offset, udphdr_port_offset;
+static unsigned link_hdr_len, ethertype_offset;
+static int stream_init_flag;
+static unsigned last_seq, last_tstamp, stream_ssrc;
+static struct timeval last_pkt_time;
+
+static void
+check_dl_type()
+{
+	int dltype;
+
+	dltype = pcap_datalink(pcap);
+	switch (dltype) {
+	case DLT_EN10MB:
+		link_hdr_len = 14;
+		ethertype_offset = 12;
+		break;
+	case DLT_RAW:
+		link_hdr_len = 0;
+		break;
+	case DLT_LINUX_SLL:
+		link_hdr_len = 16;
+		ethertype_offset = 14;
+		break;
+	default:
+		fprintf(stderr, "error: unsupported data link type %d\n",
+			dltype);
+		exit(1);
+	}
+}
+
+static void
+rtp_stream_logic(rtp_hdr, pkt_idx, pkt_time)
+	u_char *rtp_hdr;
+	unsigned pkt_idx;
+	struct timeval *pkt_time;
+{
+	unsigned cur_seq, cur_tstamp, cur_ssrc;
+	struct timeval deltat;
+
+	cur_seq = (rtp_hdr[2] << 8) | rtp_hdr[3];
+	cur_tstamp = (rtp_hdr[4] << 24) | (rtp_hdr[5] << 16) |
+			(rtp_hdr[6] << 8) | rtp_hdr[7];
+	cur_ssrc = (rtp_hdr[8] << 24) | (rtp_hdr[9] << 16) |
+			(rtp_hdr[10] << 8) | rtp_hdr[11];
+	if (stream_init_flag) {
+		if (cur_ssrc != stream_ssrc) {
+			fprintf(stderr,
+		"error in packet #%u: SSRC change from 0x%08X to 0x%08X\n",
+				pkt_idx, stream_ssrc, cur_ssrc);
+			exit(1);
+		}
+		if (cur_seq != last_seq + 1 &&
+		    (cur_seq != 0 || last_seq != 0xFFFF)) {
+			fprintf(stderr,
+		"error in packet #%u: seq break from 0x%04X to 0x%04X\n",
+				pkt_idx, last_seq, cur_seq);
+			exit(1);
+		}
+		if (cur_tstamp != last_tstamp + 160) {
+			fprintf(stderr,
+		"error in packet #%u: timestamp break from 0x%08X to 0x%08X\n",
+				pkt_idx, last_tstamp, cur_tstamp);
+			exit(1);
+		}
+		if (timercmp(pkt_time, &last_pkt_time, <)) {
+			fprintf(stderr,
+			"packet #%u timing error: Rx time goes backward\n",
+				pkt_idx);
+			exit(1);
+		}
+		timersub(pkt_time, &last_pkt_time, &deltat);
+		if (deltat.tv_sec) {
+			fprintf(stderr,
+				"packet #%u timing error: Rx time gap >= 1 s\n",
+				pkt_idx);
+			exit(1);
+		}
+		printf("Packet #%u: time delta %u us\n", pkt_idx,
+			(unsigned) deltat.tv_usec);
+	} else {
+		stream_init_flag = 1;
+		stream_ssrc = cur_ssrc;
+	}
+	last_seq = cur_seq;
+	last_tstamp = cur_tstamp;
+	bcopy(pkt_time, &last_pkt_time, sizeof(struct timeval));
+}
+
+static void
+process_packet(pkt, caplen, pkt_idx, pkt_time)
+	u_char *pkt;
+	unsigned caplen, pkt_idx;
+	struct timeval *pkt_time;
+{
+	unsigned udplen;
+
+	if (caplen < link_hdr_len + 28)
+		return;
+	if (link_hdr_len) {
+		if (pkt[ethertype_offset] != 0x08)
+			return;
+		if (pkt[ethertype_offset+1] != 0x00)
+			return;
+		pkt += link_hdr_len;
+		caplen -= link_hdr_len;
+	}
+	/* check IP header */
+	if (pkt[0] != 0x45)
+		return;
+	if (pkt[9] != 17)	/* UDP */
+		return;
+	if (bcmp(pkt + iphdr_addr_offset, &match_ip_addr, 4))
+		return;
+	/* check UDP header */
+	if (bcmp(pkt + 20 + udphdr_port_offset, &match_udp_port, 2))
+		return;
+	/* it is our target - now scrutinize it */
+	udplen = (pkt[24] << 8) | pkt[25];
+	if (caplen < udplen + 20) {
+		fprintf(stderr,
+			"error: packet #%u is truncated in the capture\n",
+			pkt_idx);
+		exit(1);
+	}
+	if (udplen < 20) {
+		fprintf(stderr,
+		"error in packet #%u: UDP length is too short for RTP header\n",
+			pkt_idx);
+		exit(1);
+	}
+	if (pkt[28] != 0x80) {
+		fprintf(stderr,
+		"error in packet #%u: unsupported RTP header structure\n",
+			pkt_idx);
+		exit(1);
+	}
+	rtp_stream_logic(pkt + 28, pkt_idx, pkt_time);
+}
+
+main(argc, argv)
+	char **argv;
+{
+	char errbuf[PCAP_ERRBUF_SIZE];
+	u_char *pkt;
+	struct pcap_pkthdr pkthdr;
+	unsigned pkt_idx;
+
+	if (argc != 5) {
+		fprintf(stderr,
+			"usage: %s pcap-file src|dest ip-addr udp-port\n",
+			argv[0]);
+		exit(1);
+	}
+	pcap = pcap_open_offline(argv[1], errbuf);
+	if (!pcap) {
+		fprintf(stderr, "%s: %s\n", argv[1], errbuf);
+		exit(1);
+	}
+	check_dl_type();
+	if (!strcmp(argv[2], "src")) {
+		iphdr_addr_offset = 12;
+		udphdr_port_offset = 0;
+	} else if (!strcmp(argv[2], "dest")) {
+		iphdr_addr_offset = 16;
+		udphdr_port_offset = 2;
+	} else {
+		fprintf(stderr,
+		"error: direction argument must be \"src\" or \"dest\"\n");
+		exit(1);
+	}
+	match_ip_addr = inet_addr(argv[3]);
+	if (match_ip_addr == INADDR_NONE) {
+		fprintf(stderr, "error: IP address argument is invalid\n");
+		exit(1);
+	}
+	match_udp_port = htons(strtoul(argv[4], 0, 0));
+	for (pkt_idx = 0; ; pkt_idx++) {
+		pkt = pcap_next(pcap, &pkthdr);
+		if (!pkt)
+			break;
+		process_packet(pkt, (unsigned) pkthdr.caplen, pkt_idx,
+				&pkthdr.ts);
+	}
+	if (!stream_init_flag) {
+		fprintf(stderr, "error: specified RTP stream not found\n");
+		exit(1);
+	}
+	exit(0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pcap-study/rtp-stream-dump.c	Wed May 15 01:44:46 2024 +0000
@@ -0,0 +1,188 @@
+/*
+ * This program is an aid for analyzing arbitrary RTP streams:
+ * it reads a pcap file, extracts packets belonging to a particular
+ * RTP stream as identified by a source or destination IP:port,
+ * and displays a one-line summary of every RTP packet.
+ * Discontinuities are treated as non-fatal errors: an error message
+ * is printed, but analysis continues.
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <pcap/pcap.h>
+
+static pcap_t *pcap;
+static in_addr_t match_ip_addr;
+static u_short match_udp_port;
+static unsigned iphdr_addr_offset, udphdr_port_offset;
+static unsigned link_hdr_len, ethertype_offset;
+static int stream_init_flag;
+static unsigned last_seq, last_tstamp, stream_ssrc;
+
+static void
+check_dl_type()
+{
+	int dltype;
+
+	dltype = pcap_datalink(pcap);
+	switch (dltype) {
+	case DLT_EN10MB:
+		link_hdr_len = 14;
+		ethertype_offset = 12;
+		break;
+	case DLT_RAW:
+		link_hdr_len = 0;
+		break;
+	case DLT_LINUX_SLL:
+		link_hdr_len = 16;
+		ethertype_offset = 14;
+		break;
+	default:
+		fprintf(stderr, "error: unsupported data link type %d\n",
+			dltype);
+		exit(1);
+	}
+}
+
+static void
+rtp_stream_logic(rtp_hdr, pkt_idx)
+	u_char *rtp_hdr;
+	unsigned pkt_idx;
+{
+	unsigned cur_seq, cur_tstamp, cur_ssrc;
+
+	cur_seq = (rtp_hdr[2] << 8) | rtp_hdr[3];
+	cur_tstamp = (rtp_hdr[4] << 24) | (rtp_hdr[5] << 16) |
+			(rtp_hdr[6] << 8) | rtp_hdr[7];
+	cur_ssrc = (rtp_hdr[8] << 24) | (rtp_hdr[9] << 16) |
+			(rtp_hdr[10] << 8) | rtp_hdr[11];
+	if (stream_init_flag) {
+		if (cur_ssrc != stream_ssrc) {
+			printf(
+		"error in packet #%u: SSRC change from 0x%08X to 0x%08X\n",
+				pkt_idx, stream_ssrc, cur_ssrc);
+		} else if (cur_seq != last_seq + 1 &&
+			   (cur_seq != 0 || last_seq != 0xFFFF)) {
+			printf(
+		"error in packet #%u: seq break from 0x%04X to 0x%04X\n",
+				pkt_idx, last_seq, cur_seq);
+		} else if (cur_tstamp != last_tstamp + 160) {
+			printf(
+		"error in packet #%u: timestamp break from 0x%08X to 0x%08X\n",
+				pkt_idx, last_tstamp, cur_tstamp);
+		}
+	} else
+		stream_init_flag = 1;
+	last_seq = cur_seq;
+	last_tstamp = cur_tstamp;
+	stream_ssrc = cur_ssrc;
+}
+
+static void
+process_packet(pkt, caplen, pkt_idx)
+	u_char *pkt;
+	unsigned caplen, pkt_idx;
+{
+	unsigned udplen, payload_len;
+
+	if (caplen < link_hdr_len + 28)
+		return;
+	if (link_hdr_len) {
+		if (pkt[ethertype_offset] != 0x08)
+			return;
+		if (pkt[ethertype_offset+1] != 0x00)
+			return;
+		pkt += link_hdr_len;
+		caplen -= link_hdr_len;
+	}
+	/* check IP header */
+	if (pkt[0] != 0x45)
+		return;
+	if (pkt[9] != 17)	/* UDP */
+		return;
+	if (bcmp(pkt + iphdr_addr_offset, &match_ip_addr, 4))
+		return;
+	/* check UDP header */
+	if (bcmp(pkt + 20 + udphdr_port_offset, &match_udp_port, 2))
+		return;
+	/* it is our target - now scrutinize it */
+	udplen = (pkt[24] << 8) | pkt[25];
+	if (caplen < udplen + 20) {
+		fprintf(stderr,
+			"error: packet #%u is truncated in the capture\n",
+			pkt_idx);
+		exit(1);
+	}
+	if (udplen < 20) {
+		fprintf(stderr,
+		"error in packet #%u: UDP length is too short for RTP header\n",
+			pkt_idx);
+		exit(1);
+	}
+	if (pkt[28] != 0x80) {
+		fprintf(stderr,
+		"error in packet #%u: unsupported RTP header structure\n",
+			pkt_idx);
+		exit(1);
+	}
+	rtp_stream_logic(pkt + 28, pkt_idx);
+	printf("pkt #%u seq 0x%04X ts 0x%08X: pt=%u M=%u len=%u\n", pkt_idx,
+		last_seq, last_tstamp, pkt[29] & 0x7F, pkt[29] >> 7,
+		udplen - 20);
+}
+
+main(argc, argv)
+	char **argv;
+{
+	char errbuf[PCAP_ERRBUF_SIZE];
+	u_char *pkt;
+	struct pcap_pkthdr pkthdr;
+	unsigned pkt_idx;
+
+	if (argc != 5) {
+		fprintf(stderr,
+			"usage: %s pcap-file src|dest ip-addr udp-port\n",
+			argv[0]);
+		exit(1);
+	}
+	pcap = pcap_open_offline(argv[1], errbuf);
+	if (!pcap) {
+		fprintf(stderr, "%s: %s\n", argv[1], errbuf);
+		exit(1);
+	}
+	check_dl_type();
+	if (!strcmp(argv[2], "src")) {
+		iphdr_addr_offset = 12;
+		udphdr_port_offset = 0;
+	} else if (!strcmp(argv[2], "dest")) {
+		iphdr_addr_offset = 16;
+		udphdr_port_offset = 2;
+	} else {
+		fprintf(stderr,
+		"error: direction argument must be \"src\" or \"dest\"\n");
+		exit(1);
+	}
+	match_ip_addr = inet_addr(argv[3]);
+	if (match_ip_addr == INADDR_NONE) {
+		fprintf(stderr, "error: IP address argument is invalid\n");
+		exit(1);
+	}
+	match_udp_port = htons(strtoul(argv[4], 0, 0));
+	for (pkt_idx = 0; ; pkt_idx++) {
+		pkt = pcap_next(pcap, &pkthdr);
+		if (!pkt)
+			break;
+		process_packet(pkt, (unsigned) pkthdr.caplen, pkt_idx);
+	}
+	if (!stream_init_flag) {
+		fprintf(stderr, "error: specified RTP stream not found\n");
+		exit(1);
+	}
+	exit(0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pcap-study/rtp-tfo-trace.c	Wed May 15 01:44:46 2024 +0000
@@ -0,0 +1,338 @@
+/*
+ * This program reads a pcap file containing RTP packets of a PSTN call
+ * (PCMU or PCMA, 160 samples per RTP packet), flowing in one or both
+ * directions, and looks for TFO IS messages.
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <pcap/pcap.h>
+
+static pcap_t *pcap;
+static in_addr_t match_ip_addr;
+static u_short match_udp_port;
+static unsigned link_hdr_len, ethertype_offset;
+
+static struct onedir {
+	int		init_flag;
+	unsigned	last_seq;
+	unsigned	last_tstamp;
+	unsigned	stream_ssrc;
+	u_char		is_hunt_buf[320];
+	int		is_state;
+	unsigned	is_hunt_fill;
+	unsigned	is_offset;
+	unsigned	is_alignment;
+	unsigned	is_bit_count;
+	unsigned	is_rx_word;
+} rx_state, tx_state;
+
+static const u_char hdr_pattern[20] =	{0, 1, 0, 1, 0, 1, 1, 0, 1, 0,
+					 0, 1, 1, 0, 1, 0, 1, 0, 0, 1};
+
+static void
+check_dl_type()
+{
+	int dltype;
+
+	dltype = pcap_datalink(pcap);
+	switch (dltype) {
+	case DLT_EN10MB:
+		link_hdr_len = 14;
+		ethertype_offset = 12;
+		break;
+	case DLT_RAW:
+		link_hdr_len = 0;
+		break;
+	case DLT_LINUX_SLL:
+		link_hdr_len = 16;
+		ethertype_offset = 14;
+		break;
+	default:
+		fprintf(stderr, "error: unsupported data link type %d\n",
+			dltype);
+		exit(1);
+	}
+}
+
+static void
+rtp_stream_logic(rtp_hdr, pkt_idx, st, dir_str)
+	u_char *rtp_hdr;
+	unsigned pkt_idx;
+	struct onedir *st;
+	char *dir_str;
+{
+	unsigned cur_seq, cur_tstamp, cur_ssrc;
+
+	cur_seq = (rtp_hdr[2] << 8) | rtp_hdr[3];
+	cur_tstamp = (rtp_hdr[4] << 24) | (rtp_hdr[5] << 16) |
+			(rtp_hdr[6] << 8) | rtp_hdr[7];
+	cur_ssrc = (rtp_hdr[8] << 24) | (rtp_hdr[9] << 16) |
+			(rtp_hdr[10] << 8) | rtp_hdr[11];
+	if (st->init_flag) {
+		if (cur_ssrc != st->stream_ssrc) {
+			printf(
+		"error in %s packet #%u: SSRC change from 0x%08X to 0x%08X\n",
+				dir_str, pkt_idx, st->stream_ssrc, cur_ssrc);
+		} else if (cur_seq != st->last_seq + 1 &&
+			   (cur_seq != 0 || st->last_seq != 0xFFFF)) {
+			printf(
+		"error in %s packet #%u: seq break from 0x%04X to 0x%04X\n",
+				dir_str, pkt_idx, st->last_seq, cur_seq);
+		} else if (cur_tstamp != st->last_tstamp + 160) {
+			printf(
+	      "error in %s packet #%u: timestamp break from 0x%08X to 0x%08X\n",
+				dir_str, pkt_idx, st->last_tstamp, cur_tstamp);
+		}
+	} else
+		st->init_flag = 1;
+	st->last_seq = cur_seq;
+	st->last_tstamp = cur_tstamp;
+	st->stream_ssrc = cur_ssrc;
+}
+
+static void
+is_rx_hunt(input_pos, pkt_idx, st, dir_str)
+	unsigned input_pos;
+	unsigned pkt_idx;
+	struct onedir *st;
+	char *dir_str;
+{
+	unsigned offset, n;
+
+	for (offset = 0; offset < 16; offset++) {
+		for (n = 0; n < 20; n++)
+			if ((st->is_hunt_buf[offset + n*16] & 1) !=
+			    hdr_pattern[n])
+				break;
+		if (n == 20)
+			break;
+	}
+	if (n != 20)
+		return;
+	st->is_offset = offset;
+	st->is_alignment = input_pos * 16 + offset;
+	st->is_state = 1;
+	st->is_bit_count = 0;
+	st->is_rx_word = 0;
+	st->is_hunt_fill = 0;
+}
+
+static void
+is_process_cmd(pkt_idx, st, dir_str)
+	unsigned pkt_idx;
+	struct onedir *st;
+	char *dir_str;
+{
+	int cont;
+
+	printf("#%u: %s (align %u) ", pkt_idx, dir_str, st->is_alignment);
+	switch (st->is_rx_word) {
+	case 0x05D:
+		printf("IS_REQ\n");
+		cont = 1;
+		break;
+	case 0x0BA:
+		printf("IS_ACK\n");
+		cont = 1;
+		break;
+	case 0x0E7:
+		printf("IS_IPE\n");
+		cont = 1;
+		break;
+	case 0x129:
+		printf("IS_FILL\n");
+		cont = 0;
+		break;
+	case 0x174:
+		printf("IS_DUP\n");
+		cont = 0;
+		break;
+	case 0x193:
+		printf("IS_SYL\n");
+		cont = 0;
+		break;
+	default:
+		printf("Unknown IS_Command 0x%03X\n", st->is_rx_word);
+		cont = 0;
+	}
+	if (cont) {
+		st->is_state = 2;
+		st->is_bit_count = 0;
+		st->is_rx_word = 0;
+	} else
+		st->is_state = 0;
+}
+
+static void
+is_process_ext(pkt_idx, st, dir_str)
+	unsigned pkt_idx;
+	struct onedir *st;
+	char *dir_str;
+{
+	printf("#%u: %s IS_Extension: 0x%05X", pkt_idx, dir_str,
+		st->is_rx_word);
+	if (st->is_rx_word & 0x80200) {
+		printf(" (bad sync)\n");
+		st->is_state = 0;
+		return;
+	}
+	switch (st->is_rx_word & 3) {
+	case 0:
+		printf(" (final)\n");
+		st->is_state = 0;
+		return;
+	case 3:
+		printf(" (continue)\n");
+		st->is_state = 2;
+		st->is_bit_count = 0;
+		st->is_rx_word = 0;
+		return;
+	default:
+		printf(" (bad EX)\n");
+		st->is_state = 0;
+	}
+}
+
+static void
+is_rx_process(input, input_pos, pkt_idx, st, dir_str)
+	uint8_t *input;
+	unsigned input_pos;
+	unsigned pkt_idx;
+	struct onedir *st;
+	char *dir_str;
+{
+	unsigned new_bit;
+
+	memmove(st->is_hunt_buf, st->is_hunt_buf + 16, 304);
+	memcpy(st->is_hunt_buf + 304, input, 16);
+	if (!st->is_state) {
+		if (st->is_hunt_fill < 20)
+			st->is_hunt_fill++;
+		if (st->is_hunt_fill == 20)
+			is_rx_hunt(input_pos, pkt_idx, st, dir_str);
+		return;
+	}
+	new_bit = input[st->is_offset] & 1;
+	st->is_rx_word <<= 1;
+	st->is_rx_word |= new_bit;
+	st->is_bit_count++;
+	if (st->is_state == 1 && st->is_bit_count == 10)
+		is_process_cmd(pkt_idx, st, dir_str);
+	else if (st->is_state == 2 && st->is_bit_count == 20)
+		is_process_ext(pkt_idx, st, dir_str);
+}
+
+static void
+process_packet_onedir(pkt, caplen, pkt_idx, st, dir_str)
+	u_char *pkt;
+	unsigned caplen, pkt_idx;
+	struct onedir *st;
+	char *dir_str;
+{
+	unsigned udplen, payload_len;
+	unsigned is_chunk;
+
+	udplen = (pkt[24] << 8) | pkt[25];
+	if (caplen < udplen + 20) {
+		printf("error: %s packet #%u is truncated in the capture\n",
+			dir_str, pkt_idx);
+		return;
+	}
+	if (udplen < 20) {
+		printf(
+	    "error in %s packet #%u: UDP length is too short for RTP header\n",
+			dir_str, pkt_idx);
+		return;
+	}
+	if (pkt[28] != 0x80) {
+		printf(
+		"error in %s packet #%u: unsupported RTP header structure\n",
+			dir_str, pkt_idx);
+		return;
+	}
+	rtp_stream_logic(pkt + 28, pkt_idx, st, dir_str);
+	payload_len = udplen - 20;
+	if (payload_len != 160) {
+		printf("error in %s packet #%u: wrong payload length\n",
+			dir_str, pkt_idx);
+		return;
+	}
+	for (is_chunk = 0; is_chunk < 10; is_chunk++)
+		is_rx_process(pkt + 40 + is_chunk * 16, is_chunk, pkt_idx, st,
+			      dir_str);
+}
+
+static void
+process_packet(pkt, caplen, pkt_idx)
+	u_char *pkt;
+	unsigned caplen, pkt_idx;
+{
+	if (caplen < link_hdr_len + 28)
+		return;
+	if (link_hdr_len) {
+		if (pkt[ethertype_offset] != 0x08)
+			return;
+		if (pkt[ethertype_offset+1] != 0x00)
+			return;
+		pkt += link_hdr_len;
+		caplen -= link_hdr_len;
+	}
+	/* check IP header */
+	if (pkt[0] != 0x45)
+		return;
+	if (pkt[9] != 17)	/* UDP */
+		return;
+	if (!bcmp(pkt + 12, &match_ip_addr, 4) &&
+	    !bcmp(pkt + 20, &match_udp_port, 2))
+		process_packet_onedir(pkt, caplen, pkt_idx, &tx_state, "-->");
+	else if (!bcmp(pkt + 16, &match_ip_addr, 4) &&
+		 !bcmp(pkt + 22, &match_udp_port, 2))
+		process_packet_onedir(pkt, caplen, pkt_idx, &rx_state, "<--");
+}
+
+main(argc, argv)
+	char **argv;
+{
+	char errbuf[PCAP_ERRBUF_SIZE];
+	u_char *pkt;
+	struct pcap_pkthdr pkthdr;
+	unsigned pkt_idx;
+
+	if (argc != 4) {
+		fprintf(stderr, "usage: %s pcap-file ip-addr udp-port\n",
+			argv[0]);
+		exit(1);
+	}
+	pcap = pcap_open_offline(argv[1], errbuf);
+	if (!pcap) {
+		fprintf(stderr, "%s: %s\n", argv[1], errbuf);
+		exit(1);
+	}
+	check_dl_type();
+	match_ip_addr = inet_addr(argv[2]);
+	if (match_ip_addr == INADDR_NONE) {
+		fprintf(stderr, "error: IP address argument is invalid\n");
+		exit(1);
+	}
+	match_udp_port = htons(strtoul(argv[3], 0, 0));
+	for (pkt_idx = 0; ; pkt_idx++) {
+		pkt = pcap_next(pcap, &pkthdr);
+		if (!pkt)
+			break;
+		process_packet(pkt, (unsigned) pkthdr.caplen, pkt_idx);
+	}
+	if (!tx_state.init_flag)
+		printf(
+	"Warning: found no packets with src matching specified IP:port\n");
+	if (!rx_state.init_flag)
+		printf(
+	"Warning: found no packets with dest matching specified IP:port\n");
+	exit(0);
+}
--- a/rtp-cont-check.c	Sun Mar 10 02:27:37 2024 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,234 +0,0 @@
-/*
- * This program reads a pcap file, extracts packets belonging to a
- * particular RTP stream as identified by a source or destination
- * IP:port, and checks its continuity: verifies that the sequence
- * number always increments by 1 and that the timestamp always
- * increments by 160 units.  Finally, this program prints out
- * the minimum and maximum observed capture time deltas between
- * successive packets of the stream.
- *
- * The codec can be anything, and this program can also be used to
- * check continuity of RTP streams coming from PSTN/SIP, but the
- * core assumption is that packets must arrive every 20 ms, with
- * the timestamp field incrementing by 160 units each time.
- */
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/time.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <strings.h>
-#include <pcap/pcap.h>
-
-static pcap_t *pcap;
-static in_addr_t match_ip_addr;
-static u_short match_udp_port;
-static unsigned iphdr_addr_offset, udphdr_port_offset;
-static unsigned link_hdr_len, ethertype_offset;
-static int stream_init_flag, deltat_init_flag;
-static unsigned last_seq, last_tstamp, stream_ssrc;
-static struct timeval last_pkt_time;
-static unsigned deltat_min, deltat_max;
-
-static void
-check_dl_type()
-{
-	int dltype;
-
-	dltype = pcap_datalink(pcap);
-	switch (dltype) {
-	case DLT_EN10MB:
-		link_hdr_len = 14;
-		ethertype_offset = 12;
-		break;
-	case DLT_RAW:
-		link_hdr_len = 0;
-		break;
-	case DLT_LINUX_SLL:
-		link_hdr_len = 16;
-		ethertype_offset = 14;
-		break;
-	default:
-		fprintf(stderr, "error: unsupported data link type %d\n",
-			dltype);
-		exit(1);
-	}
-}
-
-static void
-rtp_stream_logic(rtp_hdr, pkt_idx, pkt_time)
-	u_char *rtp_hdr;
-	unsigned pkt_idx;
-	struct timeval *pkt_time;
-{
-	unsigned cur_seq, cur_tstamp, cur_ssrc;
-	struct timeval deltat;
-
-	cur_seq = (rtp_hdr[2] << 8) | rtp_hdr[3];
-	cur_tstamp = (rtp_hdr[4] << 24) | (rtp_hdr[5] << 16) |
-			(rtp_hdr[6] << 8) | rtp_hdr[7];
-	cur_ssrc = (rtp_hdr[8] << 24) | (rtp_hdr[9] << 16) |
-			(rtp_hdr[10] << 8) | rtp_hdr[11];
-	if (stream_init_flag) {
-		if (cur_ssrc != stream_ssrc) {
-			fprintf(stderr,
-		"error in packet #%u: SSRC change from 0x%08X to 0x%08X\n",
-				pkt_idx, stream_ssrc, cur_ssrc);
-			exit(1);
-		}
-		if (cur_seq != last_seq + 1 &&
-		    (cur_seq != 0 || last_seq != 0xFFFF)) {
-			fprintf(stderr,
-		"error in packet #%u: seq break from 0x%04X to 0x%04X\n",
-				pkt_idx, last_seq, cur_seq);
-			exit(1);
-		}
-		if (cur_tstamp != last_tstamp + 160) {
-			fprintf(stderr,
-		"error in packet #%u: timestamp break from 0x%08X to 0x%08X\n",
-				pkt_idx, last_tstamp, cur_tstamp);
-			exit(1);
-		}
-		if (timercmp(pkt_time, &last_pkt_time, <)) {
-			fprintf(stderr,
-			"packet #%u timing error: Rx time goes backward\n",
-				pkt_idx);
-			exit(1);
-		}
-		timersub(pkt_time, &last_pkt_time, &deltat);
-		if (deltat.tv_sec) {
-			fprintf(stderr,
-				"packet #%u timing error: Rx time gap >= 1 s\n",
-				pkt_idx);
-			exit(1);
-		}
-		if (deltat_init_flag) {
-			if (deltat.tv_usec < deltat_min)
-				deltat_min = deltat.tv_usec;
-			if (deltat.tv_usec > deltat_max)
-				deltat_max = deltat.tv_usec;
-		} else {
-			deltat_min = deltat.tv_usec;
-			deltat_max = deltat.tv_usec;
-			deltat_init_flag = 1;
-		}
-	} else {
-		stream_init_flag = 1;
-		stream_ssrc = cur_ssrc;
-	}
-	last_seq = cur_seq;
-	last_tstamp = cur_tstamp;
-	bcopy(pkt_time, &last_pkt_time, sizeof(struct timeval));
-}
-
-static void
-process_packet(pkt, caplen, pkt_idx, pkt_time)
-	u_char *pkt;
-	unsigned caplen, pkt_idx;
-	struct timeval *pkt_time;
-{
-	unsigned udplen;
-
-	if (caplen < link_hdr_len + 28)
-		return;
-	if (link_hdr_len) {
-		if (pkt[ethertype_offset] != 0x08)
-			return;
-		if (pkt[ethertype_offset+1] != 0x00)
-			return;
-		pkt += link_hdr_len;
-		caplen -= link_hdr_len;
-	}
-	/* check IP header */
-	if (pkt[0] != 0x45)
-		return;
-	if (pkt[9] != 17)	/* UDP */
-		return;
-	if (bcmp(pkt + iphdr_addr_offset, &match_ip_addr, 4))
-		return;
-	/* check UDP header */
-	if (bcmp(pkt + 20 + udphdr_port_offset, &match_udp_port, 2))
-		return;
-	/* it is our target - now scrutinize it */
-	udplen = (pkt[24] << 8) | pkt[25];
-	if (caplen < udplen + 20) {
-		fprintf(stderr,
-			"error: packet #%u is truncated in the capture\n",
-			pkt_idx);
-		exit(1);
-	}
-	if (udplen < 20) {
-		fprintf(stderr,
-		"error in packet #%u: UDP length is too short for RTP header\n",
-			pkt_idx);
-		exit(1);
-	}
-	if (pkt[28] != 0x80) {
-		fprintf(stderr,
-		"error in packet #%u: unsupported RTP header structure\n",
-			pkt_idx);
-		exit(1);
-	}
-	rtp_stream_logic(pkt + 28, pkt_idx, pkt_time);
-}
-
-main(argc, argv)
-	char **argv;
-{
-	char errbuf[PCAP_ERRBUF_SIZE];
-	u_char *pkt;
-	struct pcap_pkthdr pkthdr;
-	unsigned pkt_idx;
-
-	if (argc != 5) {
-		fprintf(stderr,
-			"usage: %s pcap-file src|dest ip-addr udp-port\n",
-			argv[0]);
-		exit(1);
-	}
-	pcap = pcap_open_offline(argv[1], errbuf);
-	if (!pcap) {
-		fprintf(stderr, "%s: %s\n", argv[1], errbuf);
-		exit(1);
-	}
-	check_dl_type();
-	if (!strcmp(argv[2], "src")) {
-		iphdr_addr_offset = 12;
-		udphdr_port_offset = 0;
-	} else if (!strcmp(argv[2], "dest")) {
-		iphdr_addr_offset = 16;
-		udphdr_port_offset = 2;
-	} else {
-		fprintf(stderr,
-		"error: direction argument must be \"src\" or \"dest\"\n");
-		exit(1);
-	}
-	match_ip_addr = inet_addr(argv[3]);
-	if (match_ip_addr == INADDR_NONE) {
-		fprintf(stderr, "error: IP address argument is invalid\n");
-		exit(1);
-	}
-	match_udp_port = htons(strtoul(argv[4], 0, 0));
-	for (pkt_idx = 0; ; pkt_idx++) {
-		pkt = pcap_next(pcap, &pkthdr);
-		if (!pkt)
-			break;
-		process_packet(pkt, (unsigned) pkthdr.caplen, pkt_idx,
-				&pkthdr.ts);
-	}
-	if (!stream_init_flag) {
-		fprintf(stderr, "error: specified RTP stream not found\n");
-		exit(1);
-	}
-	if (!deltat_init_flag) {
-		fprintf(stderr, "error: found only one matching packet\n");
-		exit(1);
-	}
-	printf("Minimum time delta: %u us\n", deltat_min);
-	printf("Maximum time delta: %u us\n", deltat_max);
-	exit(0);
-}
--- a/rtp-g711-extr.c	Sun Mar 10 02:27:37 2024 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,212 +0,0 @@
-/*
- * This program reads a pcap file, extracts packets belonging to a
- * particular RTP stream as identified by a source or destination
- * IP:port, and verifies that an unbroken RTP stream is present,
- * with 160-byte payloads corresponding to timestamp increments
- * of 160 units per packet, as expected for a G.711 (PCMU or PCMA)
- * RTP stream with 20 ms packetization.  The extracted G.711 stream
- * is written to a raw binary file.
- */
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <strings.h>
-#include <pcap/pcap.h>
-
-static pcap_t *pcap;
-static in_addr_t match_ip_addr;
-static u_short match_udp_port;
-static unsigned iphdr_addr_offset, udphdr_port_offset;
-static unsigned link_hdr_len, ethertype_offset;
-static FILE *outfile;
-static int stream_init_flag;
-static unsigned last_seq, last_tstamp, stream_ssrc;
-
-static void
-check_dl_type()
-{
-	int dltype;
-
-	dltype = pcap_datalink(pcap);
-	switch (dltype) {
-	case DLT_EN10MB:
-		link_hdr_len = 14;
-		ethertype_offset = 12;
-		break;
-	case DLT_RAW:
-		link_hdr_len = 0;
-		break;
-	case DLT_LINUX_SLL:
-		link_hdr_len = 16;
-		ethertype_offset = 14;
-		break;
-	default:
-		fprintf(stderr, "error: unsupported data link type %d\n",
-			dltype);
-		exit(1);
-	}
-}
-
-static void
-rtp_stream_logic(rtp_hdr, pkt_idx)
-	u_char *rtp_hdr;
-	unsigned pkt_idx;
-{
-	unsigned cur_seq, cur_tstamp, cur_ssrc;
-
-	cur_seq = (rtp_hdr[2] << 8) | rtp_hdr[3];
-	cur_tstamp = (rtp_hdr[4] << 24) | (rtp_hdr[5] << 16) |
-			(rtp_hdr[6] << 8) | rtp_hdr[7];
-	cur_ssrc = (rtp_hdr[8] << 24) | (rtp_hdr[9] << 16) |
-			(rtp_hdr[10] << 8) | rtp_hdr[11];
-	if (stream_init_flag) {
-		if (cur_ssrc != stream_ssrc) {
-			fprintf(stderr,
-		"error in packet #%u: SSRC change from 0x%08X to 0x%08X\n",
-				pkt_idx, stream_ssrc, cur_ssrc);
-			exit(1);
-		}
-		if (cur_seq != last_seq + 1 &&
-		    (cur_seq != 0 || last_seq != 0xFFFF)) {
-			fprintf(stderr,
-		"error in packet #%u: seq break from 0x%04X to 0x%04X\n",
-				pkt_idx, last_seq, cur_seq);
-			exit(1);
-		}
-		if (cur_tstamp != last_tstamp + 160) {
-			fprintf(stderr,
-		"error in packet #%u: timestamp break from 0x%08X to 0x%08X\n",
-				pkt_idx, last_tstamp, cur_tstamp);
-			exit(1);
-		}
-	} else {
-		stream_init_flag = 1;
-		stream_ssrc = cur_ssrc;
-	}
-	last_seq = cur_seq;
-	last_tstamp = cur_tstamp;
-}
-
-static void
-process_packet(pkt, caplen, pkt_idx)
-	u_char *pkt;
-	unsigned caplen, pkt_idx;
-{
-	unsigned udplen, payload_len;
-
-	if (caplen < link_hdr_len + 28)
-		return;
-	if (link_hdr_len) {
-		if (pkt[ethertype_offset] != 0x08)
-			return;
-		if (pkt[ethertype_offset+1] != 0x00)
-			return;
-		pkt += link_hdr_len;
-		caplen -= link_hdr_len;
-	}
-	/* check IP header */
-	if (pkt[0] != 0x45)
-		return;
-	if (pkt[9] != 17)	/* UDP */
-		return;
-	if (bcmp(pkt + iphdr_addr_offset, &match_ip_addr, 4))
-		return;
-	/* check UDP header */
-	if (bcmp(pkt + 20 + udphdr_port_offset, &match_udp_port, 2))
-		return;
-	/* it is our target - now scrutinize it */
-	udplen = (pkt[24] << 8) | pkt[25];
-	if (caplen < udplen + 20) {
-		fprintf(stderr,
-			"error: packet #%u is truncated in the capture\n",
-			pkt_idx);
-		exit(1);
-	}
-	if (udplen < 20) {
-		fprintf(stderr,
-		"error in packet #%u: UDP length is too short for RTP header\n",
-			pkt_idx);
-		exit(1);
-	}
-	if (pkt[28] != 0x80) {
-		fprintf(stderr,
-		"error in packet #%u: unsupported RTP header structure\n",
-			pkt_idx);
-		exit(1);
-	}
-	rtp_stream_logic(pkt + 28, pkt_idx);
-	payload_len = udplen - 20;
-	if (payload_len != 160) {
-		fprintf(stderr, "error in packet #%u: unsupported payload\n",
-			pkt_idx);
-		exit(1);
-	}
-	fwrite(pkt + 40, 1, payload_len, outfile);
-}
-
-main(argc, argv)
-	char **argv;
-{
-	char errbuf[PCAP_ERRBUF_SIZE];
-	u_char *pkt;
-	struct pcap_pkthdr pkthdr;
-	unsigned pkt_idx, skip_num;
-
-	if (argc < 6 || argc > 7) {
-		fprintf(stderr,
-	"usage: %s pcap-file src|dest ip-addr udp-port outfile [skip-count]\n",
-			argv[0]);
-		exit(1);
-	}
-	pcap = pcap_open_offline(argv[1], errbuf);
-	if (!pcap) {
-		fprintf(stderr, "%s: %s\n", argv[1], errbuf);
-		exit(1);
-	}
-	check_dl_type();
-	if (!strcmp(argv[2], "src")) {
-		iphdr_addr_offset = 12;
-		udphdr_port_offset = 0;
-	} else if (!strcmp(argv[2], "dest")) {
-		iphdr_addr_offset = 16;
-		udphdr_port_offset = 2;
-	} else {
-		fprintf(stderr,
-		"error: direction argument must be \"src\" or \"dest\"\n");
-		exit(1);
-	}
-	match_ip_addr = inet_addr(argv[3]);
-	if (match_ip_addr == INADDR_NONE) {
-		fprintf(stderr, "error: IP address argument is invalid\n");
-		exit(1);
-	}
-	match_udp_port = htons(strtoul(argv[4], 0, 0));
-	outfile = fopen(argv[5], "w");
-	if (!outfile) {
-		perror(argv[5]);
-		exit(1);
-	}
-	if (argv[6])
-		skip_num = strtoul(argv[6], 0, 0);
-	else
-		skip_num = 0;
-	for (pkt_idx = 0; ; pkt_idx++) {
-		pkt = pcap_next(pcap, &pkthdr);
-		if (!pkt)
-			break;
-		if (pkt_idx < skip_num)
-			continue;
-		process_packet(pkt, (unsigned) pkthdr.caplen, pkt_idx);
-	}
-	if (!stream_init_flag) {
-		fprintf(stderr, "error: specified RTP stream not found\n");
-		exit(1);
-	}
-	fclose(outfile);
-	exit(0);
-}
--- a/rtp-gsmfr-dump.c	Sun Mar 10 02:27:37 2024 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,276 +0,0 @@
-/*
- * This program is a combination of rtp-gsmfr-extr and gsmrec-dump into
- * one step: it reads a pcap file, extracts packets belonging to a
- * particular RTP stream as identified by a source or destination
- * IP:port, verifies that an unbroken RTP stream is present, which is
- * expected to be in GSM FR or EFR codec, but instead of writing this
- * FR/EFR frame stream to a gsmx file, decodes it like gsmrec-dump.
- *
- * The advantage of this program over running rtp-gsmfr-extr followed
- * by gsmrec-dump is that TRAUlike Extension Headers (if present) are
- * dumped for analysis, rather than discarded.
- */
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <strings.h>
-#include <pcap/pcap.h>
-#include <gsm.h>
-#include <gsm_efr.h>
-
-static pcap_t *pcap;
-static in_addr_t match_ip_addr;
-static u_short match_udp_port;
-static unsigned iphdr_addr_offset, udphdr_port_offset;
-static unsigned link_hdr_len, ethertype_offset;
-static int stream_init_flag;
-static unsigned last_seq, last_tstamp, stream_ssrc;
-static gsm dummy_state;
-
-static void
-check_dl_type()
-{
-	int dltype;
-
-	dltype = pcap_datalink(pcap);
-	switch (dltype) {
-	case DLT_EN10MB:
-		link_hdr_len = 14;
-		ethertype_offset = 12;
-		break;
-	case DLT_RAW:
-		link_hdr_len = 0;
-		break;
-	case DLT_LINUX_SLL:
-		link_hdr_len = 16;
-		ethertype_offset = 14;
-		break;
-	default:
-		fprintf(stderr, "error: unsupported data link type %d\n",
-			dltype);
-		exit(1);
-	}
-}
-
-static void
-rtp_stream_logic(rtp_hdr, pkt_idx)
-	u_char *rtp_hdr;
-	unsigned pkt_idx;
-{
-	unsigned cur_seq, cur_tstamp, cur_ssrc;
-
-	cur_seq = (rtp_hdr[2] << 8) | rtp_hdr[3];
-	cur_tstamp = (rtp_hdr[4] << 24) | (rtp_hdr[5] << 16) |
-			(rtp_hdr[6] << 8) | rtp_hdr[7];
-	cur_ssrc = (rtp_hdr[8] << 24) | (rtp_hdr[9] << 16) |
-			(rtp_hdr[10] << 8) | rtp_hdr[11];
-	if (stream_init_flag) {
-		if (cur_ssrc != stream_ssrc) {
-			printf(
-		"error in packet #%u: SSRC change from 0x%08X to 0x%08X\n",
-				pkt_idx, stream_ssrc, cur_ssrc);
-		} else if (cur_seq != last_seq + 1 &&
-			   (cur_seq != 0 || last_seq != 0xFFFF)) {
-			printf(
-		"error in packet #%u: seq break from 0x%04X to 0x%04X\n",
-				pkt_idx, last_seq, cur_seq);
-		} else if (cur_tstamp != last_tstamp + 160) {
-			printf(
-		"error in packet #%u: timestamp break from 0x%08X to 0x%08X\n",
-				pkt_idx, last_tstamp, cur_tstamp);
-		}
-	} else
-		stream_init_flag = 1;
-	last_seq = cur_seq;
-	last_tstamp = cur_tstamp;
-	stream_ssrc = cur_ssrc;
-}
-
-static void
-process_payload(payload, payload_len)
-	u_char *payload;
-	unsigned payload_len;
-{
-	gsm_signal params[76];
-	int i, j, n;
-
-	printf("seq 0x%04X ts 0x%08X: ", last_seq, last_tstamp);
-	switch (payload_len) {
-	case 0:
-		printf("zero-length payload\n");
-		return;
-	case 1:
-		if ((payload[0] & 0xF6) != 0xE6)
-			break;
-		printf("TEH 0x%02X\n", payload[0]);
-		return;
-	case 2:
-		if (payload[0] != 0xBF)
-			break;
-		printf("old BFI TAF=%u\n", payload[1] & 1);
-		return;
-	case 31:
-		if ((payload[0] & 0xF0) != 0xC0)
-			break;
-		printf("std EFR SID=%d LPC", EFR_sid_classify(payload));
-		EFR_frame2params(payload, params);
-	print_efr:
-		n = 0;
-		for (i = 0; i < 5; i++)
-			printf(" %d", params[n++]);
-		putchar('\n');
-		for (i = 0; i < 4; i++) {
-			putchar(' ');
-			for (j = 0; j < 13; j++)
-				printf(" %d", params[n++]);
-			putchar('\n');
-		}
-		return;
-	case 32:
-		if ((payload[0] & 0xF4) != 0xE0)
-			break;
-		if ((payload[1] & 0xF0) != 0xC0)
-			break;
-		printf("TEH 0x%02X EFR SID=%d LPC", payload[0],
-			EFR_sid_classify(payload+1));
-		EFR_frame2params(payload+1, params);
-		goto print_efr;
-	case 33:
-		if ((payload[0] & 0xF0) != 0xD0)
-			break;
-		fputs("std FR", stdout);
-		gsm_explode(dummy_state, payload, params);
-	print_fr:
-		n = 0;
-		for (i = 0; i < 8; i++)
-			printf(" %d", params[n++]);
-		putchar('\n');
-		for (i = 0; i < 4; i++) {
-			putchar(' ');
-			for (j = 0; j < 17; j++)
-				printf(" %d", params[n++]);
-			putchar('\n');
-		}
-		return;
-	case 34:
-		if ((payload[0] & 0xF4) != 0xE0)
-			break;
-		if ((payload[1] & 0xF0) != 0xD0)
-			break;
-		printf("TEH 0x%02X FR", payload[0]);
-		gsm_explode(dummy_state, payload+1, params);
-		goto print_fr;
-	}
-	printf("unknown payload format, length=%u\n", payload_len);
-}
-
-static void
-process_packet(pkt, caplen, pkt_idx)
-	u_char *pkt;
-	unsigned caplen, pkt_idx;
-{
-	unsigned udplen, payload_len;
-
-	if (caplen < link_hdr_len + 28)
-		return;
-	if (link_hdr_len) {
-		if (pkt[ethertype_offset] != 0x08)
-			return;
-		if (pkt[ethertype_offset+1] != 0x00)
-			return;
-		pkt += link_hdr_len;
-		caplen -= link_hdr_len;
-	}
-	/* check IP header */
-	if (pkt[0] != 0x45)
-		return;
-	if (pkt[9] != 17)	/* UDP */
-		return;
-	if (bcmp(pkt + iphdr_addr_offset, &match_ip_addr, 4))
-		return;
-	/* check UDP header */
-	if (bcmp(pkt + 20 + udphdr_port_offset, &match_udp_port, 2))
-		return;
-	/* it is our target - now scrutinize it */
-	udplen = (pkt[24] << 8) | pkt[25];
-	if (caplen < udplen + 20) {
-		fprintf(stderr,
-			"error: packet #%u is truncated in the capture\n",
-			pkt_idx);
-		exit(1);
-	}
-	if (udplen < 20) {
-		fprintf(stderr,
-		"error in packet #%u: UDP length is too short for RTP header\n",
-			pkt_idx);
-		exit(1);
-	}
-	if (pkt[28] != 0x80) {
-		fprintf(stderr,
-		"error in packet #%u: unsupported RTP header structure\n",
-			pkt_idx);
-		exit(1);
-	}
-	rtp_stream_logic(pkt + 28, pkt_idx);
-	process_payload(pkt + 40, udplen - 20);
-}
-
-main(argc, argv)
-	char **argv;
-{
-	char errbuf[PCAP_ERRBUF_SIZE];
-	u_char *pkt;
-	struct pcap_pkthdr pkthdr;
-	unsigned pkt_idx;
-
-	if (argc != 5) {
-		fprintf(stderr,
-			"usage: %s pcap-file src|dest ip-addr udp-port\n",
-			argv[0]);
-		exit(1);
-	}
-	pcap = pcap_open_offline(argv[1], errbuf);
-	if (!pcap) {
-		fprintf(stderr, "%s: %s\n", argv[1], errbuf);
-		exit(1);
-	}
-	check_dl_type();
-	if (!strcmp(argv[2], "src")) {
-		iphdr_addr_offset = 12;
-		udphdr_port_offset = 0;
-	} else if (!strcmp(argv[2], "dest")) {
-		iphdr_addr_offset = 16;
-		udphdr_port_offset = 2;
-	} else {
-		fprintf(stderr,
-		"error: direction argument must be \"src\" or \"dest\"\n");
-		exit(1);
-	}
-	match_ip_addr = inet_addr(argv[3]);
-	if (match_ip_addr == INADDR_NONE) {
-		fprintf(stderr, "error: IP address argument is invalid\n");
-		exit(1);
-	}
-	match_udp_port = htons(strtoul(argv[4], 0, 0));
-	dummy_state = gsm_create();
-	if (!dummy_state) {
-		fprintf(stderr, "gsm_create() failed!\n");
-		exit(1);
-	}
-	for (pkt_idx = 0; ; pkt_idx++) {
-		pkt = pcap_next(pcap, &pkthdr);
-		if (!pkt)
-			break;
-		process_packet(pkt, (unsigned) pkthdr.caplen, pkt_idx);
-	}
-	if (!stream_init_flag) {
-		fprintf(stderr, "error: specified RTP stream not found\n");
-		exit(1);
-	}
-	exit(0);
-}
--- a/rtp-gsmfr-extr.c	Sun Mar 10 02:27:37 2024 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,249 +0,0 @@
-/*
- * This program reads a pcap file, extracts packets belonging to a
- * particular RTP stream as identified by a source or destination
- * IP:port, verifies that an unbroken RTP stream is present, in
- * GSM FR or EFR codec, and writes the FR/EFR frame stream to our
- * extended-libgsm format binary file, to be fed to decoding test
- * programs.
- */
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <strings.h>
-#include <pcap/pcap.h>
-
-static pcap_t *pcap;
-static in_addr_t match_ip_addr;
-static u_short match_udp_port;
-static unsigned iphdr_addr_offset, udphdr_port_offset;
-static unsigned link_hdr_len, ethertype_offset;
-static FILE *outfile;
-static int stream_init_flag;
-static unsigned last_seq, last_tstamp, stream_ssrc;
-
-static void
-check_dl_type()
-{
-	int dltype;
-
-	dltype = pcap_datalink(pcap);
-	switch (dltype) {
-	case DLT_EN10MB:
-		link_hdr_len = 14;
-		ethertype_offset = 12;
-		break;
-	case DLT_RAW:
-		link_hdr_len = 0;
-		break;
-	case DLT_LINUX_SLL:
-		link_hdr_len = 16;
-		ethertype_offset = 14;
-		break;
-	default:
-		fprintf(stderr, "error: unsupported data link type %d\n",
-			dltype);
-		exit(1);
-	}
-}
-
-static void
-rtp_stream_logic(rtp_hdr, pkt_idx)
-	u_char *rtp_hdr;
-	unsigned pkt_idx;
-{
-	unsigned cur_seq, cur_tstamp, cur_ssrc;
-
-	cur_seq = (rtp_hdr[2] << 8) | rtp_hdr[3];
-	cur_tstamp = (rtp_hdr[4] << 24) | (rtp_hdr[5] << 16) |
-			(rtp_hdr[6] << 8) | rtp_hdr[7];
-	cur_ssrc = (rtp_hdr[8] << 24) | (rtp_hdr[9] << 16) |
-			(rtp_hdr[10] << 8) | rtp_hdr[11];
-	if (stream_init_flag) {
-		if (cur_ssrc != stream_ssrc) {
-			fprintf(stderr,
-		"error in packet #%u: SSRC change from 0x%08X to 0x%08X\n",
-				pkt_idx, stream_ssrc, cur_ssrc);
-			exit(1);
-		}
-		if (cur_seq != last_seq + 1 &&
-		    (cur_seq != 0 || last_seq != 0xFFFF)) {
-			fprintf(stderr,
-		"error in packet #%u: seq break from 0x%04X to 0x%04X\n",
-				pkt_idx, last_seq, cur_seq);
-			exit(1);
-		}
-		if (cur_tstamp != last_tstamp + 160) {
-			fprintf(stderr,
-		"error in packet #%u: timestamp break from 0x%08X to 0x%08X\n",
-				pkt_idx, last_tstamp, cur_tstamp);
-			exit(1);
-		}
-	} else {
-		stream_init_flag = 1;
-		stream_ssrc = cur_ssrc;
-	}
-	last_seq = cur_seq;
-	last_tstamp = cur_tstamp;
-}
-
-static void
-process_packet(pkt, caplen, pkt_idx)
-	u_char *pkt;
-	unsigned caplen, pkt_idx;
-{
-	unsigned udplen, payload_len;
-	u_char synth_bfi[2];
-
-	if (caplen < link_hdr_len + 28)
-		return;
-	if (link_hdr_len) {
-		if (pkt[ethertype_offset] != 0x08)
-			return;
-		if (pkt[ethertype_offset+1] != 0x00)
-			return;
-		pkt += link_hdr_len;
-		caplen -= link_hdr_len;
-	}
-	/* check IP header */
-	if (pkt[0] != 0x45)
-		return;
-	if (pkt[9] != 17)	/* UDP */
-		return;
-	if (bcmp(pkt + iphdr_addr_offset, &match_ip_addr, 4))
-		return;
-	/* check UDP header */
-	if (bcmp(pkt + 20 + udphdr_port_offset, &match_udp_port, 2))
-		return;
-	/* it is our target - now scrutinize it */
-	udplen = (pkt[24] << 8) | pkt[25];
-	if (caplen < udplen + 20) {
-		fprintf(stderr,
-			"error: packet #%u is truncated in the capture\n",
-			pkt_idx);
-		exit(1);
-	}
-	if (udplen < 20) {
-		fprintf(stderr,
-		"error in packet #%u: UDP length is too short for RTP header\n",
-			pkt_idx);
-		exit(1);
-	}
-	if (pkt[28] != 0x80) {
-		fprintf(stderr,
-		"error in packet #%u: unsupported RTP header structure\n",
-			pkt_idx);
-		exit(1);
-	}
-	rtp_stream_logic(pkt + 28, pkt_idx);
-	payload_len = udplen - 20;
-	switch (payload_len) {
-	case 0:
-		synth_bfi[0] = 0xBF;
-		synth_bfi[1] = 0;
-	emit_synth_bfi:
-		fwrite(synth_bfi, 1, 2, outfile);
-		return;
-	case 1:
-		if ((pkt[40] & 0xF6) != 0xE6)
-			break;
-	traulike_bfi:
-		synth_bfi[0] = 0xBF;
-		synth_bfi[1] = pkt[40] & 1;
-		goto emit_synth_bfi;
-	case 2:
-		if (pkt[40] != 0xBF)
-			break;
-	emit_payload:
-		fwrite(pkt + 40, 1, payload_len, outfile);
-		return;
-	case 31:
-		if ((pkt[40] & 0xF0) != 0xC0)
-			break;
-		goto emit_payload;
-	case 32:
-		if ((pkt[40] & 0xF4) != 0xE0)
-			break;
-		if ((pkt[41] & 0xF0) != 0xC0)
-			break;
-		if (pkt[40] & 2)
-			goto traulike_bfi;
-		fwrite(pkt + 41, 1, 31, outfile);
-		return;
-	case 33:
-		if ((pkt[40] & 0xF0) != 0xD0)
-			break;
-		goto emit_payload;
-	case 34:
-		if ((pkt[40] & 0xF4) != 0xE0)
-			break;
-		if ((pkt[41] & 0xF0) != 0xD0)
-			break;
-		if (pkt[40] & 2)
-			goto traulike_bfi;
-		fwrite(pkt + 41, 1, 33, outfile);
-		return;
-	}
-	fprintf(stderr, "error in packet #%u: unsupported payload\n", pkt_idx);
-	exit(1);
-}
-
-main(argc, argv)
-	char **argv;
-{
-	char errbuf[PCAP_ERRBUF_SIZE];
-	u_char *pkt;
-	struct pcap_pkthdr pkthdr;
-	unsigned pkt_idx;
-
-	if (argc != 6) {
-		fprintf(stderr,
-		"usage: %s pcap-file src|dest ip-addr udp-port outfile\n",
-			argv[0]);
-		exit(1);
-	}
-	pcap = pcap_open_offline(argv[1], errbuf);
-	if (!pcap) {
-		fprintf(stderr, "%s: %s\n", argv[1], errbuf);
-		exit(1);
-	}
-	check_dl_type();
-	if (!strcmp(argv[2], "src")) {
-		iphdr_addr_offset = 12;
-		udphdr_port_offset = 0;
-	} else if (!strcmp(argv[2], "dest")) {
-		iphdr_addr_offset = 16;
-		udphdr_port_offset = 2;
-	} else {
-		fprintf(stderr,
-		"error: direction argument must be \"src\" or \"dest\"\n");
-		exit(1);
-	}
-	match_ip_addr = inet_addr(argv[3]);
-	if (match_ip_addr == INADDR_NONE) {
-		fprintf(stderr, "error: IP address argument is invalid\n");
-		exit(1);
-	}
-	match_udp_port = htons(strtoul(argv[4], 0, 0));
-	outfile = fopen(argv[5], "w");
-	if (!outfile) {
-		perror(argv[5]);
-		exit(1);
-	}
-	for (pkt_idx = 0; ; pkt_idx++) {
-		pkt = pcap_next(pcap, &pkthdr);
-		if (!pkt)
-			break;
-		process_packet(pkt, (unsigned) pkthdr.caplen, pkt_idx);
-	}
-	if (!stream_init_flag) {
-		fprintf(stderr, "error: specified RTP stream not found\n");
-		exit(1);
-	}
-	fclose(outfile);
-	exit(0);
-}
--- a/rtp-jitter-view.c	Sun Mar 10 02:27:37 2024 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,220 +0,0 @@
-/*
- * This program reads a pcap file, extracts packets belonging to a
- * particular RTP stream as identified by a source or destination
- * IP:port, checks its continuity at the packet header level
- * (verifies that the sequence number always increments by 1 and
- * that the timestamp always increments by 160 units) and prints out
- * the Rx time delta of each stream packet (the capture time of
- * the current packet minus the capture time of the previous packet)
- * on stdout, allowing visual analysis of timing jitter.
- *
- * The codec can be anything, and this program can also be used to
- * examine the jitter of RTP streams coming from PSTN/SIP, but the
- * core assumption is that packets must arrive every 20 ms, with
- * the timestamp field incrementing by 160 units each time.
- */
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/time.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <strings.h>
-#include <pcap/pcap.h>
-
-static pcap_t *pcap;
-static in_addr_t match_ip_addr;
-static u_short match_udp_port;
-static unsigned iphdr_addr_offset, udphdr_port_offset;
-static unsigned link_hdr_len, ethertype_offset;
-static int stream_init_flag;
-static unsigned last_seq, last_tstamp, stream_ssrc;
-static struct timeval last_pkt_time;
-
-static void
-check_dl_type()
-{
-	int dltype;
-
-	dltype = pcap_datalink(pcap);
-	switch (dltype) {
-	case DLT_EN10MB:
-		link_hdr_len = 14;
-		ethertype_offset = 12;
-		break;
-	case DLT_RAW:
-		link_hdr_len = 0;
-		break;
-	case DLT_LINUX_SLL:
-		link_hdr_len = 16;
-		ethertype_offset = 14;
-		break;
-	default:
-		fprintf(stderr, "error: unsupported data link type %d\n",
-			dltype);
-		exit(1);
-	}
-}
-
-static void
-rtp_stream_logic(rtp_hdr, pkt_idx, pkt_time)
-	u_char *rtp_hdr;
-	unsigned pkt_idx;
-	struct timeval *pkt_time;
-{
-	unsigned cur_seq, cur_tstamp, cur_ssrc;
-	struct timeval deltat;
-
-	cur_seq = (rtp_hdr[2] << 8) | rtp_hdr[3];
-	cur_tstamp = (rtp_hdr[4] << 24) | (rtp_hdr[5] << 16) |
-			(rtp_hdr[6] << 8) | rtp_hdr[7];
-	cur_ssrc = (rtp_hdr[8] << 24) | (rtp_hdr[9] << 16) |
-			(rtp_hdr[10] << 8) | rtp_hdr[11];
-	if (stream_init_flag) {
-		if (cur_ssrc != stream_ssrc) {
-			fprintf(stderr,
-		"error in packet #%u: SSRC change from 0x%08X to 0x%08X\n",
-				pkt_idx, stream_ssrc, cur_ssrc);
-			exit(1);
-		}
-		if (cur_seq != last_seq + 1 &&
-		    (cur_seq != 0 || last_seq != 0xFFFF)) {
-			fprintf(stderr,
-		"error in packet #%u: seq break from 0x%04X to 0x%04X\n",
-				pkt_idx, last_seq, cur_seq);
-			exit(1);
-		}
-		if (cur_tstamp != last_tstamp + 160) {
-			fprintf(stderr,
-		"error in packet #%u: timestamp break from 0x%08X to 0x%08X\n",
-				pkt_idx, last_tstamp, cur_tstamp);
-			exit(1);
-		}
-		if (timercmp(pkt_time, &last_pkt_time, <)) {
-			fprintf(stderr,
-			"packet #%u timing error: Rx time goes backward\n",
-				pkt_idx);
-			exit(1);
-		}
-		timersub(pkt_time, &last_pkt_time, &deltat);
-		if (deltat.tv_sec) {
-			fprintf(stderr,
-				"packet #%u timing error: Rx time gap >= 1 s\n",
-				pkt_idx);
-			exit(1);
-		}
-		printf("Packet #%u: time delta %u us\n", pkt_idx,
-			(unsigned) deltat.tv_usec);
-	} else {
-		stream_init_flag = 1;
-		stream_ssrc = cur_ssrc;
-	}
-	last_seq = cur_seq;
-	last_tstamp = cur_tstamp;
-	bcopy(pkt_time, &last_pkt_time, sizeof(struct timeval));
-}
-
-static void
-process_packet(pkt, caplen, pkt_idx, pkt_time)
-	u_char *pkt;
-	unsigned caplen, pkt_idx;
-	struct timeval *pkt_time;
-{
-	unsigned udplen;
-
-	if (caplen < link_hdr_len + 28)
-		return;
-	if (link_hdr_len) {
-		if (pkt[ethertype_offset] != 0x08)
-			return;
-		if (pkt[ethertype_offset+1] != 0x00)
-			return;
-		pkt += link_hdr_len;
-		caplen -= link_hdr_len;
-	}
-	/* check IP header */
-	if (pkt[0] != 0x45)
-		return;
-	if (pkt[9] != 17)	/* UDP */
-		return;
-	if (bcmp(pkt + iphdr_addr_offset, &match_ip_addr, 4))
-		return;
-	/* check UDP header */
-	if (bcmp(pkt + 20 + udphdr_port_offset, &match_udp_port, 2))
-		return;
-	/* it is our target - now scrutinize it */
-	udplen = (pkt[24] << 8) | pkt[25];
-	if (caplen < udplen + 20) {
-		fprintf(stderr,
-			"error: packet #%u is truncated in the capture\n",
-			pkt_idx);
-		exit(1);
-	}
-	if (udplen < 20) {
-		fprintf(stderr,
-		"error in packet #%u: UDP length is too short for RTP header\n",
-			pkt_idx);
-		exit(1);
-	}
-	if (pkt[28] != 0x80) {
-		fprintf(stderr,
-		"error in packet #%u: unsupported RTP header structure\n",
-			pkt_idx);
-		exit(1);
-	}
-	rtp_stream_logic(pkt + 28, pkt_idx, pkt_time);
-}
-
-main(argc, argv)
-	char **argv;
-{
-	char errbuf[PCAP_ERRBUF_SIZE];
-	u_char *pkt;
-	struct pcap_pkthdr pkthdr;
-	unsigned pkt_idx;
-
-	if (argc != 5) {
-		fprintf(stderr,
-			"usage: %s pcap-file src|dest ip-addr udp-port\n",
-			argv[0]);
-		exit(1);
-	}
-	pcap = pcap_open_offline(argv[1], errbuf);
-	if (!pcap) {
-		fprintf(stderr, "%s: %s\n", argv[1], errbuf);
-		exit(1);
-	}
-	check_dl_type();
-	if (!strcmp(argv[2], "src")) {
-		iphdr_addr_offset = 12;
-		udphdr_port_offset = 0;
-	} else if (!strcmp(argv[2], "dest")) {
-		iphdr_addr_offset = 16;
-		udphdr_port_offset = 2;
-	} else {
-		fprintf(stderr,
-		"error: direction argument must be \"src\" or \"dest\"\n");
-		exit(1);
-	}
-	match_ip_addr = inet_addr(argv[3]);
-	if (match_ip_addr == INADDR_NONE) {
-		fprintf(stderr, "error: IP address argument is invalid\n");
-		exit(1);
-	}
-	match_udp_port = htons(strtoul(argv[4], 0, 0));
-	for (pkt_idx = 0; ; pkt_idx++) {
-		pkt = pcap_next(pcap, &pkthdr);
-		if (!pkt)
-			break;
-		process_packet(pkt, (unsigned) pkthdr.caplen, pkt_idx,
-				&pkthdr.ts);
-	}
-	if (!stream_init_flag) {
-		fprintf(stderr, "error: specified RTP stream not found\n");
-		exit(1);
-	}
-	exit(0);
-}
--- a/rtp-stream-dump.c	Sun Mar 10 02:27:37 2024 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,188 +0,0 @@
-/*
- * This program is an aid for analyzing arbitrary RTP streams:
- * it reads a pcap file, extracts packets belonging to a particular
- * RTP stream as identified by a source or destination IP:port,
- * and displays a one-line summary of every RTP packet.
- * Discontinuities are treated as non-fatal errors: an error message
- * is printed, but analysis continues.
- */
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <strings.h>
-#include <pcap/pcap.h>
-
-static pcap_t *pcap;
-static in_addr_t match_ip_addr;
-static u_short match_udp_port;
-static unsigned iphdr_addr_offset, udphdr_port_offset;
-static unsigned link_hdr_len, ethertype_offset;
-static int stream_init_flag;
-static unsigned last_seq, last_tstamp, stream_ssrc;
-
-static void
-check_dl_type()
-{
-	int dltype;
-
-	dltype = pcap_datalink(pcap);
-	switch (dltype) {
-	case DLT_EN10MB:
-		link_hdr_len = 14;
-		ethertype_offset = 12;
-		break;
-	case DLT_RAW:
-		link_hdr_len = 0;
-		break;
-	case DLT_LINUX_SLL:
-		link_hdr_len = 16;
-		ethertype_offset = 14;
-		break;
-	default:
-		fprintf(stderr, "error: unsupported data link type %d\n",
-			dltype);
-		exit(1);
-	}
-}
-
-static void
-rtp_stream_logic(rtp_hdr, pkt_idx)
-	u_char *rtp_hdr;
-	unsigned pkt_idx;
-{
-	unsigned cur_seq, cur_tstamp, cur_ssrc;
-
-	cur_seq = (rtp_hdr[2] << 8) | rtp_hdr[3];
-	cur_tstamp = (rtp_hdr[4] << 24) | (rtp_hdr[5] << 16) |
-			(rtp_hdr[6] << 8) | rtp_hdr[7];
-	cur_ssrc = (rtp_hdr[8] << 24) | (rtp_hdr[9] << 16) |
-			(rtp_hdr[10] << 8) | rtp_hdr[11];
-	if (stream_init_flag) {
-		if (cur_ssrc != stream_ssrc) {
-			printf(
-		"error in packet #%u: SSRC change from 0x%08X to 0x%08X\n",
-				pkt_idx, stream_ssrc, cur_ssrc);
-		} else if (cur_seq != last_seq + 1 &&
-			   (cur_seq != 0 || last_seq != 0xFFFF)) {
-			printf(
-		"error in packet #%u: seq break from 0x%04X to 0x%04X\n",
-				pkt_idx, last_seq, cur_seq);
-		} else if (cur_tstamp != last_tstamp + 160) {
-			printf(
-		"error in packet #%u: timestamp break from 0x%08X to 0x%08X\n",
-				pkt_idx, last_tstamp, cur_tstamp);
-		}
-	} else
-		stream_init_flag = 1;
-	last_seq = cur_seq;
-	last_tstamp = cur_tstamp;
-	stream_ssrc = cur_ssrc;
-}
-
-static void
-process_packet(pkt, caplen, pkt_idx)
-	u_char *pkt;
-	unsigned caplen, pkt_idx;
-{
-	unsigned udplen, payload_len;
-
-	if (caplen < link_hdr_len + 28)
-		return;
-	if (link_hdr_len) {
-		if (pkt[ethertype_offset] != 0x08)
-			return;
-		if (pkt[ethertype_offset+1] != 0x00)
-			return;
-		pkt += link_hdr_len;
-		caplen -= link_hdr_len;
-	}
-	/* check IP header */
-	if (pkt[0] != 0x45)
-		return;
-	if (pkt[9] != 17)	/* UDP */
-		return;
-	if (bcmp(pkt + iphdr_addr_offset, &match_ip_addr, 4))
-		return;
-	/* check UDP header */
-	if (bcmp(pkt + 20 + udphdr_port_offset, &match_udp_port, 2))
-		return;
-	/* it is our target - now scrutinize it */
-	udplen = (pkt[24] << 8) | pkt[25];
-	if (caplen < udplen + 20) {
-		fprintf(stderr,
-			"error: packet #%u is truncated in the capture\n",
-			pkt_idx);
-		exit(1);
-	}
-	if (udplen < 20) {
-		fprintf(stderr,
-		"error in packet #%u: UDP length is too short for RTP header\n",
-			pkt_idx);
-		exit(1);
-	}
-	if (pkt[28] != 0x80) {
-		fprintf(stderr,
-		"error in packet #%u: unsupported RTP header structure\n",
-			pkt_idx);
-		exit(1);
-	}
-	rtp_stream_logic(pkt + 28, pkt_idx);
-	printf("pkt #%u seq 0x%04X ts 0x%08X: pt=%u M=%u len=%u\n", pkt_idx,
-		last_seq, last_tstamp, pkt[29] & 0x7F, pkt[29] >> 7,
-		udplen - 20);
-}
-
-main(argc, argv)
-	char **argv;
-{
-	char errbuf[PCAP_ERRBUF_SIZE];
-	u_char *pkt;
-	struct pcap_pkthdr pkthdr;
-	unsigned pkt_idx;
-
-	if (argc != 5) {
-		fprintf(stderr,
-			"usage: %s pcap-file src|dest ip-addr udp-port\n",
-			argv[0]);
-		exit(1);
-	}
-	pcap = pcap_open_offline(argv[1], errbuf);
-	if (!pcap) {
-		fprintf(stderr, "%s: %s\n", argv[1], errbuf);
-		exit(1);
-	}
-	check_dl_type();
-	if (!strcmp(argv[2], "src")) {
-		iphdr_addr_offset = 12;
-		udphdr_port_offset = 0;
-	} else if (!strcmp(argv[2], "dest")) {
-		iphdr_addr_offset = 16;
-		udphdr_port_offset = 2;
-	} else {
-		fprintf(stderr,
-		"error: direction argument must be \"src\" or \"dest\"\n");
-		exit(1);
-	}
-	match_ip_addr = inet_addr(argv[3]);
-	if (match_ip_addr == INADDR_NONE) {
-		fprintf(stderr, "error: IP address argument is invalid\n");
-		exit(1);
-	}
-	match_udp_port = htons(strtoul(argv[4], 0, 0));
-	for (pkt_idx = 0; ; pkt_idx++) {
-		pkt = pcap_next(pcap, &pkthdr);
-		if (!pkt)
-			break;
-		process_packet(pkt, (unsigned) pkthdr.caplen, pkt_idx);
-	}
-	if (!stream_init_flag) {
-		fprintf(stderr, "error: specified RTP stream not found\n");
-		exit(1);
-	}
-	exit(0);
-}
--- a/rtp-stream-gen.c	Sun Mar 10 02:27:37 2024 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,162 +0,0 @@
-/*
- * This program generates a dummy RTP stream, sending RTP packets with
- * a dummy payload to the specified destination IP:port, paced in time
- * every 20 ms.  The purpose is to test the behaviour of affordably-available
- * Internet connections when presented with such traffic: the intent is
- * to capture this packet stream on the receiving end with tcpdump and then
- * analyze the pcap for problem signs of packet loss, jitter and reordering.
- */
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/time.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <stdio.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <string.h>
-#include <strings.h>
-#include <unistd.h>
-
-#define	RTP_PACKET_HDR_SIZE	12
-#define	RTP_MAX_PAYLOAD		160
-#define	GSM_FR_BYTES		33
-
-struct rtp_packet {
-	uint8_t		v_p_x_cc;
-	uint8_t		m_pt;
-	uint16_t	seq;
-	uint32_t	tstamp;
-	uint32_t	ssrc;
-	uint8_t		payload[RTP_MAX_PAYLOAD];
-};
-
-static const uint8_t gsmfr_silence_frame[GSM_FR_BYTES] = {
-	0xDA, 0xA7, 0xAA, 0xA5, 0x1A,
-	0x50, 0x20, 0x38, 0xE4, 0x6D, 0xB9, 0x1B,
-	0x50, 0x20, 0x38, 0xE4, 0x6D, 0xB9, 0x1B,
-	0x50, 0x20, 0x38, 0xE4, 0x6D, 0xB9, 0x1B,
-	0x50, 0x20, 0x38, 0xE4, 0x6D, 0xB9, 0x1B,
-};
-
-static struct sockaddr_in sin_src, sin_dest;
-static struct rtp_packet rtp_pkt;
-static unsigned rtp_pkt_len, req_packet_count;
-static int udp_fd;
-
-static void
-parse_ip_port(arg, sin)
-	char *arg;
-	struct sockaddr_in *sin;
-{
-	char *cp;
-	int rc;
-
-	cp = index(arg, ':');
-	if (!cp) {
-		fprintf(stderr, "error: missing ':' in IP:port argument\n");
-		exit(1);
-	}
-	*cp++ = '\0';
-	sin->sin_family = AF_INET;
-	rc = inet_aton(arg, &sin->sin_addr);
-	if (!rc) {
-		fprintf(stderr, "error: invalid IP address argument\n");
-		exit(1);
-	}
-	sin->sin_port = htons(atoi(cp));
-}
-
-static void
-prepare_rtp_payload(type_arg)
-	char *type_arg;
-{
-	unsigned pl_len;
-
-	if (!strcmp(type_arg, "pcmu")) {
-		rtp_pkt.m_pt = 0;
-		memset(rtp_pkt.payload, 0xFF, RTP_MAX_PAYLOAD);
-		pl_len = RTP_MAX_PAYLOAD;
-	} else if (!strcmp(type_arg, "pcma")) {
-		rtp_pkt.m_pt = 8;
-		memset(rtp_pkt.payload, 0xD5, RTP_MAX_PAYLOAD);
-		pl_len = RTP_MAX_PAYLOAD;
-	} else if (!strcmp(type_arg, "gsm")) {
-		rtp_pkt.m_pt = 3;
-		memcpy(rtp_pkt.payload, gsmfr_silence_frame, GSM_FR_BYTES);
-		pl_len = GSM_FR_BYTES;
-	} else {
-		fprintf(stderr, "error: invalid PL type argument \"%s\"\n",
-			type_arg);
-		exit(1);
-	}
-	rtp_pkt_len = RTP_PACKET_HDR_SIZE + pl_len;
-}
-
-static void
-assign_rtpout_ssrc()
-{
-	struct timeval curtime;
-
-	gettimeofday(&curtime, 0);
-	rtp_pkt.ssrc = curtime.tv_sec ^ curtime.tv_usec ^ getpid();
-}
-
-static void
-prepare_udp_socket()
-{
-	int rc;
-
-	udp_fd = socket(AF_INET, SOCK_DGRAM, 0);
-	if (udp_fd < 0) {
-		perror("socket(AF_INET, SOCK_DGRAM, 0)");
-		exit(1);
-	}
-	rc = bind(udp_fd, (struct sockaddr *) &sin_src, sizeof sin_src);
-	if (rc < 0) {
-		perror("bind");
-		exit(1);
-	}
-	rc = connect(udp_fd, (struct sockaddr *) &sin_dest, sizeof sin_dest);
-	if (rc < 0) {
-		perror("connect");
-		exit(1);
-	}
-}
-
-static void
-send_out_packets()
-{
-	unsigned n, seq, ts;
-
-	seq = 0;
-	ts = 0;
-	for (n = 0; n < req_packet_count; n++) {
-		rtp_pkt.seq = htons(seq);
-		rtp_pkt.tstamp = htonl(ts);
-		send(udp_fd, &rtp_pkt, rtp_pkt_len, 0);
-		seq++;
-		ts += 160;
-		usleep(20000);
-	}
-}
-
-main(argc, argv)
-	char **argv;
-{
-	if (argc != 5) {
-		fprintf(stderr, "usage: %s src-IP:port dest-IP:port type num\n",
-			argv[0]);
-		exit(1);
-	}
-	parse_ip_port(argv[1], &sin_src);
-	parse_ip_port(argv[2], &sin_dest);
-	prepare_rtp_payload(argv[3]);
-	rtp_pkt.v_p_x_cc = 0x80;
-	assign_rtpout_ssrc();
-	req_packet_count = atoi(argv[4]);
-	prepare_udp_socket();
-	send_out_packets();
-	exit(0);
-}
--- a/rtp-tfo-trace.c	Sun Mar 10 02:27:37 2024 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,338 +0,0 @@
-/*
- * This program reads a pcap file containing RTP packets of a PSTN call
- * (PCMU or PCMA, 160 samples per RTP packet), flowing in one or both
- * directions, and looks for TFO IS messages.
- */
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <strings.h>
-#include <pcap/pcap.h>
-
-static pcap_t *pcap;
-static in_addr_t match_ip_addr;
-static u_short match_udp_port;
-static unsigned link_hdr_len, ethertype_offset;
-
-static struct onedir {
-	int		init_flag;
-	unsigned	last_seq;
-	unsigned	last_tstamp;
-	unsigned	stream_ssrc;
-	u_char		is_hunt_buf[320];
-	int		is_state;
-	unsigned	is_hunt_fill;
-	unsigned	is_offset;
-	unsigned	is_alignment;
-	unsigned	is_bit_count;
-	unsigned	is_rx_word;
-} rx_state, tx_state;
-
-static const u_char hdr_pattern[20] =	{0, 1, 0, 1, 0, 1, 1, 0, 1, 0,
-					 0, 1, 1, 0, 1, 0, 1, 0, 0, 1};
-
-static void
-check_dl_type()
-{
-	int dltype;
-
-	dltype = pcap_datalink(pcap);
-	switch (dltype) {
-	case DLT_EN10MB:
-		link_hdr_len = 14;
-		ethertype_offset = 12;
-		break;
-	case DLT_RAW:
-		link_hdr_len = 0;
-		break;
-	case DLT_LINUX_SLL:
-		link_hdr_len = 16;
-		ethertype_offset = 14;
-		break;
-	default:
-		fprintf(stderr, "error: unsupported data link type %d\n",
-			dltype);
-		exit(1);
-	}
-}
-
-static void
-rtp_stream_logic(rtp_hdr, pkt_idx, st, dir_str)
-	u_char *rtp_hdr;
-	unsigned pkt_idx;
-	struct onedir *st;
-	char *dir_str;
-{
-	unsigned cur_seq, cur_tstamp, cur_ssrc;
-
-	cur_seq = (rtp_hdr[2] << 8) | rtp_hdr[3];
-	cur_tstamp = (rtp_hdr[4] << 24) | (rtp_hdr[5] << 16) |
-			(rtp_hdr[6] << 8) | rtp_hdr[7];
-	cur_ssrc = (rtp_hdr[8] << 24) | (rtp_hdr[9] << 16) |
-			(rtp_hdr[10] << 8) | rtp_hdr[11];
-	if (st->init_flag) {
-		if (cur_ssrc != st->stream_ssrc) {
-			printf(
-		"error in %s packet #%u: SSRC change from 0x%08X to 0x%08X\n",
-				dir_str, pkt_idx, st->stream_ssrc, cur_ssrc);
-		} else if (cur_seq != st->last_seq + 1 &&
-			   (cur_seq != 0 || st->last_seq != 0xFFFF)) {
-			printf(
-		"error in %s packet #%u: seq break from 0x%04X to 0x%04X\n",
-				dir_str, pkt_idx, st->last_seq, cur_seq);
-		} else if (cur_tstamp != st->last_tstamp + 160) {
-			printf(
-	      "error in %s packet #%u: timestamp break from 0x%08X to 0x%08X\n",
-				dir_str, pkt_idx, st->last_tstamp, cur_tstamp);
-		}
-	} else
-		st->init_flag = 1;
-	st->last_seq = cur_seq;
-	st->last_tstamp = cur_tstamp;
-	st->stream_ssrc = cur_ssrc;
-}
-
-static void
-is_rx_hunt(input_pos, pkt_idx, st, dir_str)
-	unsigned input_pos;
-	unsigned pkt_idx;
-	struct onedir *st;
-	char *dir_str;
-{
-	unsigned offset, n;
-
-	for (offset = 0; offset < 16; offset++) {
-		for (n = 0; n < 20; n++)
-			if ((st->is_hunt_buf[offset + n*16] & 1) !=
-			    hdr_pattern[n])
-				break;
-		if (n == 20)
-			break;
-	}
-	if (n != 20)
-		return;
-	st->is_offset = offset;
-	st->is_alignment = input_pos * 16 + offset;
-	st->is_state = 1;
-	st->is_bit_count = 0;
-	st->is_rx_word = 0;
-	st->is_hunt_fill = 0;
-}
-
-static void
-is_process_cmd(pkt_idx, st, dir_str)
-	unsigned pkt_idx;
-	struct onedir *st;
-	char *dir_str;
-{
-	int cont;
-
-	printf("#%u: %s (align %u) ", pkt_idx, dir_str, st->is_alignment);
-	switch (st->is_rx_word) {
-	case 0x05D:
-		printf("IS_REQ\n");
-		cont = 1;
-		break;
-	case 0x0BA:
-		printf("IS_ACK\n");
-		cont = 1;
-		break;
-	case 0x0E7:
-		printf("IS_IPE\n");
-		cont = 1;
-		break;
-	case 0x129:
-		printf("IS_FILL\n");
-		cont = 0;
-		break;
-	case 0x174:
-		printf("IS_DUP\n");
-		cont = 0;
-		break;
-	case 0x193:
-		printf("IS_SYL\n");
-		cont = 0;
-		break;
-	default:
-		printf("Unknown IS_Command 0x%03X\n", st->is_rx_word);
-		cont = 0;
-	}
-	if (cont) {
-		st->is_state = 2;
-		st->is_bit_count = 0;
-		st->is_rx_word = 0;
-	} else
-		st->is_state = 0;
-}
-
-static void
-is_process_ext(pkt_idx, st, dir_str)
-	unsigned pkt_idx;
-	struct onedir *st;
-	char *dir_str;
-{
-	printf("#%u: %s IS_Extension: 0x%05X", pkt_idx, dir_str,
-		st->is_rx_word);
-	if (st->is_rx_word & 0x80200) {
-		printf(" (bad sync)\n");
-		st->is_state = 0;
-		return;
-	}
-	switch (st->is_rx_word & 3) {
-	case 0:
-		printf(" (final)\n");
-		st->is_state = 0;
-		return;
-	case 3:
-		printf(" (continue)\n");
-		st->is_state = 2;
-		st->is_bit_count = 0;
-		st->is_rx_word = 0;
-		return;
-	default:
-		printf(" (bad EX)\n");
-		st->is_state = 0;
-	}
-}
-
-static void
-is_rx_process(input, input_pos, pkt_idx, st, dir_str)
-	uint8_t *input;
-	unsigned input_pos;
-	unsigned pkt_idx;
-	struct onedir *st;
-	char *dir_str;
-{
-	unsigned new_bit;
-
-	memmove(st->is_hunt_buf, st->is_hunt_buf + 16, 304);
-	memcpy(st->is_hunt_buf + 304, input, 16);
-	if (!st->is_state) {
-		if (st->is_hunt_fill < 20)
-			st->is_hunt_fill++;
-		if (st->is_hunt_fill == 20)
-			is_rx_hunt(input_pos, pkt_idx, st, dir_str);
-		return;
-	}
-	new_bit = input[st->is_offset] & 1;
-	st->is_rx_word <<= 1;
-	st->is_rx_word |= new_bit;
-	st->is_bit_count++;
-	if (st->is_state == 1 && st->is_bit_count == 10)
-		is_process_cmd(pkt_idx, st, dir_str);
-	else if (st->is_state == 2 && st->is_bit_count == 20)
-		is_process_ext(pkt_idx, st, dir_str);
-}
-
-static void
-process_packet_onedir(pkt, caplen, pkt_idx, st, dir_str)
-	u_char *pkt;
-	unsigned caplen, pkt_idx;
-	struct onedir *st;
-	char *dir_str;
-{
-	unsigned udplen, payload_len;
-	unsigned is_chunk;
-
-	udplen = (pkt[24] << 8) | pkt[25];
-	if (caplen < udplen + 20) {
-		printf("error: %s packet #%u is truncated in the capture\n",
-			dir_str, pkt_idx);
-		return;
-	}
-	if (udplen < 20) {
-		printf(
-	    "error in %s packet #%u: UDP length is too short for RTP header\n",
-			dir_str, pkt_idx);
-		return;
-	}
-	if (pkt[28] != 0x80) {
-		printf(
-		"error in %s packet #%u: unsupported RTP header structure\n",
-			dir_str, pkt_idx);
-		return;
-	}
-	rtp_stream_logic(pkt + 28, pkt_idx, st, dir_str);
-	payload_len = udplen - 20;
-	if (payload_len != 160) {
-		printf("error in %s packet #%u: wrong payload length\n",
-			dir_str, pkt_idx);
-		return;
-	}
-	for (is_chunk = 0; is_chunk < 10; is_chunk++)
-		is_rx_process(pkt + 40 + is_chunk * 16, is_chunk, pkt_idx, st,
-			      dir_str);
-}
-
-static void
-process_packet(pkt, caplen, pkt_idx)
-	u_char *pkt;
-	unsigned caplen, pkt_idx;
-{
-	if (caplen < link_hdr_len + 28)
-		return;
-	if (link_hdr_len) {
-		if (pkt[ethertype_offset] != 0x08)
-			return;
-		if (pkt[ethertype_offset+1] != 0x00)
-			return;
-		pkt += link_hdr_len;
-		caplen -= link_hdr_len;
-	}
-	/* check IP header */
-	if (pkt[0] != 0x45)
-		return;
-	if (pkt[9] != 17)	/* UDP */
-		return;
-	if (!bcmp(pkt + 12, &match_ip_addr, 4) &&
-	    !bcmp(pkt + 20, &match_udp_port, 2))
-		process_packet_onedir(pkt, caplen, pkt_idx, &tx_state, "-->");
-	else if (!bcmp(pkt + 16, &match_ip_addr, 4) &&
-		 !bcmp(pkt + 22, &match_udp_port, 2))
-		process_packet_onedir(pkt, caplen, pkt_idx, &rx_state, "<--");
-}
-
-main(argc, argv)
-	char **argv;
-{
-	char errbuf[PCAP_ERRBUF_SIZE];
-	u_char *pkt;
-	struct pcap_pkthdr pkthdr;
-	unsigned pkt_idx;
-
-	if (argc != 4) {
-		fprintf(stderr, "usage: %s pcap-file ip-addr udp-port\n",
-			argv[0]);
-		exit(1);
-	}
-	pcap = pcap_open_offline(argv[1], errbuf);
-	if (!pcap) {
-		fprintf(stderr, "%s: %s\n", argv[1], errbuf);
-		exit(1);
-	}
-	check_dl_type();
-	match_ip_addr = inet_addr(argv[2]);
-	if (match_ip_addr == INADDR_NONE) {
-		fprintf(stderr, "error: IP address argument is invalid\n");
-		exit(1);
-	}
-	match_udp_port = htons(strtoul(argv[3], 0, 0));
-	for (pkt_idx = 0; ; pkt_idx++) {
-		pkt = pcap_next(pcap, &pkthdr);
-		if (!pkt)
-			break;
-		process_packet(pkt, (unsigned) pkthdr.caplen, pkt_idx);
-	}
-	if (!tx_state.init_flag)
-		printf(
-	"Warning: found no packets with src matching specified IP:port\n");
-	if (!rx_state.init_flag)
-		printf(
-	"Warning: found no packets with dest matching specified IP:port\n");
-	exit(0);
-}
--- a/udp-test-sink.c	Sun Mar 10 02:27:37 2024 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,96 +0,0 @@
-/*
- * This program is a simple sink for UDP: it binds to a UDP port and sinks
- * (reads and discards) all packets that arrive at it.  Upon receiving a
- * burst or stream of packets followed by a prolonged pause, it prints
- * the number of packets that were received.
- */
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/time.h>
-#include <sys/errno.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <strings.h>
-#include <unistd.h>
-
-static void
-parse_ip_port(arg, sin)
-	char *arg;
-	struct sockaddr_in *sin;
-{
-	char *cp;
-	int rc;
-
-	cp = index(arg, ':');
-	if (!cp) {
-		fprintf(stderr, "error: missing ':' in IP:port argument\n");
-		exit(1);
-	}
-	*cp++ = '\0';
-	sin->sin_family = AF_INET;
-	rc = inet_aton(arg, &sin->sin_addr);
-	if (!rc) {
-		fprintf(stderr, "error: invalid IP address argument\n");
-		exit(1);
-	}
-	sin->sin_port = htons(atoi(cp));
-}
-
-main(argc, argv)
-	char **argv;
-{
-	struct sockaddr_in bindsin;
-	int udp_fd, rc;
-	unsigned idle_sec, rx_count;
-	fd_set fds;
-	struct timeval tv;
-	u_char dummybuf[256];
-
-	if (argc < 2 || argc > 3) {
-		fprintf(stderr, "usage: bind-IP:port [idle-sec]\n", argv[0]);
-		exit(1);
-	}
-	parse_ip_port(argv[1], &bindsin);
-	if (argc >= 3)
-		idle_sec = atoi(argv[2]);
-	else
-		idle_sec = 0;
-	udp_fd = socket(AF_INET, SOCK_DGRAM, 0);
-	if (udp_fd < 0) {
-		perror("socket(AF_INET, SOCK_DGRAM, 0)");
-		exit(1);
-	}
-	rc = bind(udp_fd, (struct sockaddr *) &bindsin, sizeof bindsin);
-	if (rc < 0) {
-		perror("bind");
-		exit(1);
-	}
-	for (rx_count = 0; ; ) {
-		FD_ZERO(&fds);
-		FD_SET(udp_fd, &fds);
-		if (rx_count && idle_sec) {
-			tv.tv_sec = idle_sec;
-			tv.tv_usec = 0;
-			rc = select(udp_fd+1, &fds, 0, 0, &tv);
-		} else
-			rc = select(udp_fd+1, &fds, 0, 0, 0);
-		if (rc < 0) {
-			if (errno == EINTR)
-				continue;
-			perror("select");
-			exit(1);
-		}
-		if (FD_ISSET(udp_fd, &fds)) {
-			recv(udp_fd, dummybuf, sizeof dummybuf, 0);
-			rx_count++;
-		} else {
-			printf("Received %u packet%s\n", rx_count,
-				rx_count != 1 ? "s" : "");
-			rx_count = 0;
-		}
-	}
-}