FreeCalypso > hg > sipout-test-utils
diff test-voice/rtp_rx.c @ 0:35c0d9f03c0a
beginning with sipout-test-voice,
a copy of sip-manual-out from themwi-system-sw
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Sun, 03 Mar 2024 23:20:19 -0800 |
parents | |
children | 4f81b959a5f5 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test-voice/rtp_rx.c Sun Mar 03 23:20:19 2024 -0800 @@ -0,0 +1,270 @@ +/* + * In this module we implement our RTP handling: obtaining a PSTN-side + * RTP endpoint from themwi-rtp-mgr, then handling read select on RTP + * and RTCP UDP sockets. + */ + +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <stdio.h> +#include <stdint.h> +#include <stdlib.h> +#include <string.h> +#include <strings.h> +#include "../include/tmgw_const.h" +#include "../include/rtp_defs.h" +#include "../librtpalloc/rtp_alloc_simple.h" + +struct sockaddr_in rtp_local_addr; +int rtp_udp_fd, rtcp_udp_fd; + +static int rtp_start_flag, rtp_bad_flag, rtp_ssrc_chg_flag; +static int rtp_seq_brk_flag, rtp_seq_zero_flag, rtp_seq_neg_flag; +static int rtp_ts_brk_flag; +static uint32_t rtp_ssrc; +static uint32_t rtp_last_ts; +static uint16_t rtp_last_seq; +static int got_some_rtcp; + +static const uint8_t hdr_pattern[20] = {0, 1, 0, 1, 0, 1, 1, 0, 1, 0, + 0, 1, 1, 0, 1, 0, 1, 0, 0, 1}; + +static uint8_t is_hunt_buf[320]; +static int is_state; +static unsigned is_offset, is_bit_count, is_hunt_fill; +static uint32_t is_rx_word; + +static void +reset_is_hunt() +{ + is_state = 0; + is_hunt_fill = 0; +} + +static void +is_rx_hunt(input_pos) + unsigned input_pos; +{ + unsigned offset, n; + + for (offset = 0; offset < 16; offset++) { + for (n = 0; n < 20; n++) + if ((is_hunt_buf[offset + n*16] & 1) != hdr_pattern[n]) + break; + if (n == 20) + break; + } + if (n != 20) + return; + printf("Found IS_Header, last bit offset %u\n", + input_pos * 16 + offset); + is_offset = offset; + is_state = 1; + is_bit_count = 0; + is_rx_word = 0; + is_hunt_fill = 0; +} + +static void +is_process_cmd() +{ + int cont; + + printf("IS_Command: 0x%03X", is_rx_word); + switch (is_rx_word) { + case 0x05D: + printf(" (REQ)\n"); + cont = 1; + break; + case 0x0BA: + printf(" (ACK)\n"); + cont = 1; + break; + case 0x0E7: + printf(" (IPE)\n"); + cont = 1; + break; + case 0x129: + printf(" (FILL)\n"); + cont = 0; + break; + case 0x174: + printf(" (DUP)\n"); + cont = 0; + break; + case 0x193: + printf(" (SYL)\n"); + cont = 0; + break; + default: + printf(" (bad)\n"); + cont = 0; + } + if (cont) { + is_state = 2; + is_bit_count = 0; + is_rx_word = 0; + } else + is_state = 0; +} + +static void +is_process_ext() +{ + printf("IS_Extension: 0x%05X", is_rx_word); + if (is_rx_word & 0x80200) { + printf(" (bad sync)\n"); + is_state = 0; + return; + } + switch (is_rx_word & 3) { + case 0: + printf(" (final)\n"); + is_state = 0; + return; + case 3: + printf(" (continue)\n"); + is_state = 2; + is_bit_count = 0; + is_rx_word = 0; + return; + default: + printf(" (bad EX)\n"); + is_state = 0; + } +} + +static void +is_rx_process(input, input_pos) + uint8_t *input; + unsigned input_pos; +{ + unsigned new_bit; + + memmove(is_hunt_buf, is_hunt_buf + 16, 304); + memcpy(is_hunt_buf + 304, input, 16); + if (!is_state) { + if (is_hunt_fill < 20) + is_hunt_fill++; + if (is_hunt_fill == 20) + is_rx_hunt(input_pos); + return; + } + new_bit = input[is_offset] & 1; + is_rx_word <<= 1; + is_rx_word |= new_bit; + is_bit_count++; + if (is_state == 1 && is_bit_count == 10) + is_process_cmd(); + else if (is_state == 2 && is_bit_count == 20) + is_process_ext(); +} + +void +obtain_rtp_endp() +{ + int rc; + struct rtp_alloc_simple res; + + rc = rtp_alloc_simple(TMGW_EP_TYPE_PSTN_ONLY, &res); + if (rc < 0) + exit(1); /* error msg already printed */ + bcopy(&res.pstn_addr, &rtp_local_addr, sizeof(struct sockaddr_in)); + rtp_udp_fd = res.pstn_rtp_fd; + rtcp_udp_fd = res.pstn_rtcp_fd; + reset_is_hunt(); +} + +void +rtp_rx_select() +{ + struct rtp_packet pkt; + struct sockaddr_in sin_from; + socklen_t addrlen; + int16_t seq_delta; + int32_t ts_delta; + int rc; + unsigned is_chunk; + + addrlen = sizeof(struct sockaddr_in); + rc = recvfrom(rtp_udp_fd, &pkt, sizeof pkt, 0, + (struct sockaddr *) &sin_from, &addrlen); + if (rc < 0) + return; + if (rc != RTP_PACKET_SIZE_PSTN) { +bad_rtp_pkt: if (!rtp_bad_flag) { + printf("Got a bad RTP packet\n"); + rtp_bad_flag = 1; + } + return; + } + if (pkt.v_p_x_cc != 0x80) + goto bad_rtp_pkt; + switch (pkt.m_pt & 0x7F) { + case PSTN_CODEC_PCMU: + case PSTN_CODEC_PCMA: + break; + default: + goto bad_rtp_pkt; + } + if (rtp_start_flag && pkt.ssrc != rtp_ssrc) { + if (!rtp_ssrc_chg_flag) { + printf("Rx RTP stream changed SSRC\n"); + rtp_ssrc_chg_flag = 1; + } + reset_is_hunt(); + } else if (rtp_start_flag) { + seq_delta = ntohs(pkt.seq) - rtp_last_seq; + ts_delta = ntohl(pkt.tstamp) - rtp_last_ts; + if (seq_delta == 0) { + if (!rtp_seq_zero_flag) { + printf("Rx RTP seq zero increment\n"); + rtp_seq_zero_flag = 1; + } + return; + } + if (seq_delta < 0) { + if (!rtp_seq_neg_flag) { + printf("Rx RTP seq negative increment\n"); + rtp_seq_neg_flag = 1; + } + return; + } + if (seq_delta != 1) { + if (!rtp_seq_brk_flag) { + printf("Rx RTP stream seq break\n"); + rtp_seq_brk_flag = 1; + } + reset_is_hunt(); + } else if (ts_delta != 160) { + if (!rtp_ts_brk_flag) { + printf("Rx RTP stream tstamp break\n"); + rtp_ts_brk_flag = 1; + } + reset_is_hunt(); + } + } + rtp_ssrc = pkt.ssrc; + rtp_last_ts = ntohl(pkt.tstamp); + rtp_last_seq = ntohs(pkt.seq); + if (!rtp_start_flag) { + printf("Rx RTP stream begins with seq=%u ts=%u\n", + rtp_last_seq, rtp_last_ts); + rtp_start_flag = 1; + } + for (is_chunk = 0; is_chunk < 10; is_chunk++) + is_rx_process(pkt.payload + is_chunk * 16, is_chunk); +} + +void +rtcp_rx_select() +{ + u_char buf[512]; + + recv(rtcp_udp_fd, buf, sizeof buf, 0); + if (!got_some_rtcp) { + printf("Got some RTCP\n"); + got_some_rtcp = 1; + } +}