# HG changeset patch # User Mychaela Falconia # Date 1679089531 28800 # Node ID f8a33603288f3f9308407aed55b0795336eb27d9 # Parent 6ac96217c44292ad319ecda74113aa8ccfcc9a79 sip-manual-out: generate outgoing RTP stream with PCM silence diff -r 6ac96217c442 -r f8a33603288f sip-manual-out/Makefile --- a/sip-manual-out/Makefile Fri Mar 17 12:07:17 2023 -0800 +++ b/sip-manual-out/Makefile Fri Mar 17 13:45:31 2023 -0800 @@ -1,8 +1,8 @@ CC= gcc CFLAGS= -O2 PROG= sip-manual-out -OBJS= bye_in.o disc_cmd.o main.o readconf.o reinvite.o rtp.o sdp_in.o \ - sip_log.o sip_udp.o uac.o uas.o +OBJS= bye_in.o disc_cmd.o main.o readconf.o reinvite.o rtp_rx.o rtp_tx.o \ + sdp_in.o sip_log.o sip_udp.o uac.o uas.o LIBS= ../libsip/libsip.a ../librtpalloc/librtpalloc.a ../libutil/libutil.a INSTBIN=/usr/local/bin diff -r 6ac96217c442 -r f8a33603288f sip-manual-out/bye_in.c --- a/sip-manual-out/bye_in.c Fri Mar 17 12:07:17 2023 -0800 +++ b/sip-manual-out/bye_in.c Fri Mar 17 13:45:31 2023 -0800 @@ -14,6 +14,7 @@ #include "../libsip/out_msg.h" extern char call_id[]; +extern int rtp_out_enable; static void bye_correct_call(req, ess, sin) @@ -25,6 +26,7 @@ int rc; printf("Received BYE for our call, responding with 200\n"); + rtp_out_enable = 0; start_response_out_msg(&resp, "200 OK"); rc = add_resp_basic_headers(&resp, ess, req->req_method); if (rc < 0) { diff -r 6ac96217c442 -r f8a33603288f sip-manual-out/disc_cmd.c --- a/sip-manual-out/disc_cmd.c Fri Mar 17 12:07:17 2023 -0800 +++ b/sip-manual-out/disc_cmd.c Fri Mar 17 13:45:31 2023 -0800 @@ -14,12 +14,14 @@ extern struct sockaddr_in sip_dest_sin; extern char to_uri[]; +extern int rtp_out_enable; send_cancel_req() { struct sip_msg_out msg; int rc; + rtp_out_enable = 0; rc = start_request_out_msg(&msg, "CANCEL", to_uri); if (rc < 0) { msg_size_err: fprintf(stderr, "composing CANCEL message: size error\n"); @@ -38,6 +40,7 @@ struct sip_msg_out msg; int rc; + rtp_out_enable = 0; rc = start_request_out_msg(&msg, "BYE", to_uri); if (rc < 0) { msg_size_err: fprintf(stderr, "composing BYE message: size error\n"); diff -r 6ac96217c442 -r f8a33603288f sip-manual-out/main.c --- a/sip-manual-out/main.c Fri Mar 17 12:07:17 2023 -0800 +++ b/sip-manual-out/main.c Fri Mar 17 13:45:31 2023 -0800 @@ -22,6 +22,7 @@ extern char sip_dest_domain[]; extern struct sockaddr_in rtp_local_addr; extern int rtp_udp_fd, rtcp_udp_fd; +extern int rtp_out_enable; struct sockaddr_in sip_dest_sin; char from_uri[128], to_uri[128], call_id[128]; @@ -130,7 +131,8 @@ char **argv; { fd_set fds; - int rc, max_fd; + struct timeval next_rtp_out, timeout; + int rc, max_fd, rtp_out_running; preliminary_proc(argc, argv); gettimeofday(&cur_event_time, 0); @@ -144,13 +146,39 @@ max_fd = rtp_udp_fd; if (rtcp_udp_fd > max_fd) max_fd = rtcp_udp_fd; + rtp_out_running = 0; for (;;) { FD_ZERO(&fds); FD_SET(0, &fds); FD_SET(sip_socket, &fds); FD_SET(rtp_udp_fd, &fds); FD_SET(rtcp_udp_fd, &fds); - rc = select(max_fd+1, &fds, 0, 0, 0); + if (rtp_out_enable) { + if (!rtp_out_running) { + printf("Starting RTP output\n"); + bcopy(&cur_event_time, &next_rtp_out, + sizeof(struct timeval)); + rtp_out_running = 1; + } else { + next_rtp_out.tv_usec += 20000; + if (next_rtp_out.tv_usec >= 1000000) { + next_rtp_out.tv_sec++; + next_rtp_out.tv_usec -= 1000000; + } + } + if (timercmp(&cur_event_time, &next_rtp_out, <)) + timersub(&next_rtp_out, &cur_event_time, + &timeout); + else + timerclear(&timeout); + rc = select(max_fd+1, &fds, 0, 0, &timeout); + } else { + if (rtp_out_running) { + printf("Stopping RTP output\n"); + rtp_out_running = 0; + } + rc = select(max_fd+1, &fds, 0, 0, 0); + } if (rc < 0) { if (errno == EINTR) continue; @@ -166,5 +194,7 @@ rtp_rx_select(); if (FD_ISSET(rtcp_udp_fd, &fds)) rtcp_rx_select(); + if (rtp_out_running && (rc == 0)) + generate_rtp_packet(); } } diff -r 6ac96217c442 -r f8a33603288f sip-manual-out/rtp.c --- a/sip-manual-out/rtp.c Fri Mar 17 12:07:17 2023 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,266 +0,0 @@ -/* - * 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 -#include -#include -#include -#include -#include -#include -#include -#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; -static uint32_t is_rx_word; - -static void -reset_is_hunt() -{ - memset(is_hunt_buf, 0xFF, 320); - is_state = 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; -} - -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) { - 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; - } -} diff -r 6ac96217c442 -r f8a33603288f sip-manual-out/rtp_rx.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sip-manual-out/rtp_rx.c Fri Mar 17 13:45:31 2023 -0800 @@ -0,0 +1,266 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include +#include +#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; +static uint32_t is_rx_word; + +static void +reset_is_hunt() +{ + memset(is_hunt_buf, 0xFF, 320); + is_state = 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; +} + +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) { + 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; + } +} diff -r 6ac96217c442 -r f8a33603288f sip-manual-out/rtp_tx.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sip-manual-out/rtp_tx.c Fri Mar 17 13:45:31 2023 -0800 @@ -0,0 +1,48 @@ +/* + * In this module we implement outgoing RTP stream generation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "../include/tmgw_const.h" +#include "../include/rtp_defs.h" + +extern struct sockaddr_in rtp_local_addr, rtp_remote_addr; +extern int rtp_udp_fd, rtcp_udp_fd, pcma_selected; +extern struct timeval cur_event_time; + +static uint32_t rtp_ssrc; +static uint32_t rtp_out_ts; +static uint16_t rtp_out_seq; + +void +assign_rtpout_ssrc() +{ + rtp_ssrc = cur_event_time.tv_sec ^ cur_event_time.tv_usec ^ getpid(); +} + +void +generate_rtp_packet() +{ + struct rtp_packet pkt; + socklen_t addrlen; + + pkt.v_p_x_cc = 0x80; + pkt.m_pt = pcma_selected ? PSTN_CODEC_PCMA : PSTN_CODEC_PCMU; + pkt.seq = htons(rtp_out_seq++); + pkt.tstamp = htonl(rtp_out_ts); + rtp_out_ts += 160; + pkt.ssrc = rtp_ssrc; + memset(pkt.payload, pcma_selected ? 0xD5 : 0xFF, RTP_MAX_PAYLOAD); + addrlen = sizeof(struct sockaddr_in); + sendto(rtp_udp_fd, &pkt, RTP_PACKET_SIZE_PSTN, 0, + (struct sockaddr *) &rtp_remote_addr, addrlen); +} diff -r 6ac96217c442 -r f8a33603288f sip-manual-out/sdp_in.c --- a/sip-manual-out/sdp_in.c Fri Mar 17 12:07:17 2023 -0800 +++ b/sip-manual-out/sdp_in.c Fri Mar 17 13:45:31 2023 -0800 @@ -17,7 +17,7 @@ extern char *extract_to_tag(); struct sockaddr_in rtp_remote_addr; -int pcma_selected; +int pcma_selected, rtp_out_enable; static check_sdp_present(msg) @@ -71,4 +71,6 @@ rtp_remote_addr.sin_family = AF_INET; rtp_remote_addr.sin_addr = sdp_parse.ip_addr; rtp_remote_addr.sin_port = htons(sdp_parse.audio_port); + rtp_out_enable = 1; + assign_rtpout_ssrc(); }