FreeCalypso > hg > sipout-test-utils
view test-voice/rtp_rx.c @ 18:f7321b25195e default tip
new build system for ThemWi sw components
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Tue, 14 May 2024 18:08:35 -0800 |
parents | 4f81b959a5f5 |
children |
line wrap: on
line source
/* * 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; pcmu_catcher_reset(); } 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); switch (pkt.m_pt & 0x7F) { case PSTN_CODEC_PCMU: pcmu_catcher_process(pkt.payload); break; } } 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; } }