FreeCalypso > hg > themwi-system-sw
view mgw/gsm2pstn.c @ 169:648a64b2e16b
mgw: accept Themyscira-extension RTP BFI packets
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Sat, 19 Nov 2022 23:08:49 -0800 |
parents | 8c28426abef0 |
children | a6eb2de277f6 |
line wrap: on
line source
/* * In this module we implement our RTP gateway function * in the GSM to PSTN direction. */ #include <sys/types.h> #include <sys/socket.h> #include <sys/time.h> #include <netinet/in.h> #include <stdio.h> #include <stdint.h> #include <stdlib.h> #include <string.h> #include <strings.h> #include <syslog.h> #include <unistd.h> #include <gsm.h> /* libgsm dependency */ #include <gsm_fr_preproc.h> #include "../include/tmgw_ctrl.h" #include "../include/tmgw_const.h" #include "struct.h" #include "select.h" #include "int_defs.h" extern struct timeval cur_event_time; #define ERR_WRONG_UDP_SRC 0x0001 #define ERR_BAD_RTP_PACKET 0x0002 #define ERR_SSRC_CHANGE 0x0004 #define ERR_SEQ_BREAK 0x0008 #define ERR_TSTAMP_BREAK 0x0010 void gsm2pstn_rtp_in(in_fd, ep) struct endpoint *ep; { struct rtp_packet pkt; struct sockaddr_in sin_from; socklen_t addrlen; unsigned pktsize; int16_t seq_delta; int32_t ts_delta; int16_t pcm_samples[SAMPLES_PER_FRAME]; int rc, bfi, taf, m_out; addrlen = sizeof(struct sockaddr_in); rc = recvfrom(in_fd, &pkt, sizeof pkt, 0, (struct sockaddr *) &sin_from, &addrlen); if (rc < 0) return; pktsize = rc; if (sin_from.sin_addr.s_addr != ep->rtp_gsm.remote_addr.sin_addr.s_addr || sin_from.sin_port != ep->rtp_gsm.remote_addr.sin_port) { if (!(ep->g2p_err_flags & ERR_WRONG_UDP_SRC)) { syslog(LOG_ERR, "GSM RTP ep got UDP packet from wrong source"); ep->g2p_err_flags |= ERR_WRONG_UDP_SRC; } return; } if (pktsize < RTP_PACKET_SIZE_BFI) { bad_rtp_pkt: if (!(ep->g2p_err_flags & ERR_BAD_RTP_PACKET)) { syslog(LOG_ERR, "Rx bad RTP packet on GSM side"); ep->g2p_err_flags |= ERR_BAD_RTP_PACKET; } return; } if (pkt.v_p_x_cc != 0x80) goto bad_rtp_pkt; if ((pkt.m_pt & 0x7F) != ep->gsm_payload_type) goto bad_rtp_pkt; if (pktsize == ep->gsm_rtp_pkt_size && (pkt.payload[0] & 0xF0) == ep->gsm_payload_magic) bfi = 0; else if (pktsize == RTP_PACKET_SIZE_BFI && pkt.payload[0] == 0xBF) { bfi = 1; taf = pkt.payload[1] & 1; } else goto bad_rtp_pkt; if (ep->g2p_state && pkt.ssrc != ep->g2p_ssrc) { if (!(ep->g2p_err_flags & ERR_SSRC_CHANGE)) { syslog(LOG_ERR, "GSM RTP stream changed SSRC"); ep->g2p_err_flags |= ERR_SSRC_CHANGE; } ep->g2p_state = 0; if (ep->dtmf_pp) dtmf_stop_immediate(ep); } if (ep->g2p_state) { seq_delta = ntohs(pkt.seq) - ep->g2p_last_seq; ts_delta = ntohl(pkt.tstamp) - ep->g2p_last_ts; if (seq_delta <= 0) return; /* discard old or duplicate */ if (seq_delta != 1) { if (!(ep->g2p_err_flags & ERR_SEQ_BREAK)) { syslog(LOG_ERR, "GSM RTP stream seq break"); ep->g2p_err_flags |= ERR_SEQ_BREAK; } m_out = 1; } else { if (ts_delta == SAMPLES_PER_FRAME) m_out = 0; else if (ts_delta > 0 && ts_delta % SAMPLES_PER_FRAME == 0) m_out = 1; else { if (!(ep->g2p_err_flags & ERR_TSTAMP_BREAK)) { syslog(LOG_ERR, "GSM RTP stream tstamp break"); ep->g2p_err_flags |= ERR_TSTAMP_BREAK; } m_out = 1; } } } else m_out = 1; ep->g2p_state = 1; ep->g2p_ssrc = pkt.ssrc; ep->g2p_last_ts = ntohl(pkt.tstamp); ep->g2p_last_seq = ntohs(pkt.seq); ep->g2p_local_time = cur_event_time; /* actual transcoding and forwarding */ if (!(ep->fwd_mode & TMGW_FWD_ENABLE_GSM2PSTN)) { ep->g2p_drop_flag = 1; return; } if (ep->dtmf_pp) return; if (ep->g2p_drop_flag) { ep->g2p_drop_flag = 0; m_out = 1; } if (ep->dtmf_aftermath) { ts_delta = ep->g2p_last_ts - ep->dtmf_last_ts; if (ts_delta <= 0) return; ep->dtmf_aftermath = 0; if (ts_delta == SAMPLES_PER_FRAME) m_out = 0; else m_out = 1; } switch (ep->gsm_payload_msg_type) { case GSM_TCHF_FRAME: if (bfi) gsmfr_preproc_bfi(ep->gsm_decoder_extra_state, taf, pkt.payload); else gsmfr_preproc_good_frame(ep->gsm_decoder_extra_state, pkt.payload); gsm_decode(ep->gsm_decoder_state, pkt.payload, pcm_samples); break; } pkt.m_pt = ep->pstn_payload_type; if (m_out) pkt.m_pt |= 0x80; pkt.seq = htons(++ep->g2p_out_seq); g711_encode_frame(pcm_samples, pkt.payload, ep->pstn_payload_type); addrlen = sizeof(struct sockaddr_in); sendto(ep->rtp_pstn.rtp_fd, &pkt, RTP_PACKET_SIZE_PSTN, 0, (struct sockaddr *) &ep->rtp_pstn.remote_addr, addrlen); } gsm2pstn_init(ep) struct endpoint *ep; { if (ep->gsm_decoder_state) return TMGW_RESP_OK; switch (ep->gsm_payload_msg_type) { case GSM_TCHF_FRAME: ep->gsm_decoder_state = gsm_create(); if (!ep->gsm_decoder_state) return TMGW_RESP_ERR_RSRC; ep->gsm_decoder_extra_state = gsmfr_preproc_create(); if (!ep->gsm_decoder_extra_state) { free(ep->gsm_decoder_state); ep->gsm_decoder_state = 0; return TMGW_RESP_ERR_RSRC; } break; } select_handlers[ep->rtp_gsm.rtp_fd] = gsm2pstn_rtp_in; return TMGW_RESP_OK; }