comparison mgw/pstn2gsm.c @ 95:f280328e7e2e

themwi-mgw: initial implementation of PSTN to GSM forwarding
author Mychaela Falconia <falcon@freecalypso.org>
date Sun, 25 Sep 2022 19:17:44 -0800
parents
children f24bbfd23c9d
comparison
equal deleted inserted replaced
94:2c22b40408fb 95:f280328e7e2e
1 /*
2 * In this module we implement our RTP gateway function
3 * in the PSTN to GSM direction.
4 */
5
6 #include <sys/types.h>
7 #include <sys/socket.h>
8 #include <netinet/in.h>
9 #include <stdio.h>
10 #include <stdint.h>
11 #include <stdlib.h>
12 #include <string.h>
13 #include <strings.h>
14 #include <syslog.h>
15 #include <unistd.h>
16 #include <gsm.h> /* libgsm dependency */
17 #include "../include/tmgw_ctrl.h"
18 #include "../include/tmgw_const.h"
19 #include "struct.h"
20 #include "select.h"
21 #include "int_defs.h"
22
23 extern uint16_t pcmu_decode_table[256];
24 extern uint16_t pcma_decode_table[256];
25
26 #define ERR_WRONG_UDP_SRC 0x0001
27 #define ERR_BAD_RTP_PACKET 0x0002
28 #define ERR_SSRC_CHANGE 0x0004
29 #define ERR_SEQ_BREAK 0x0008
30 #define ERR_TSTAMP_BREAK 0x0010
31
32 void
33 pstn2gsm_rtp_in(in_fd, ep)
34 struct endpoint *ep;
35 {
36 struct rtp_packet pkt;
37 struct sockaddr_in sin_from;
38 socklen_t addrlen;
39 uint16_t *pcm_dec_table;
40 int16_t seq_delta;
41 int32_t ts_delta;
42 int16_t pcm_samples[SAMPLES_PER_FRAME];
43 unsigned n;
44 int rc, m_out;
45
46 addrlen = sizeof(struct sockaddr_in);
47 rc = recvfrom(in_fd, &pkt, sizeof pkt, 0,
48 (struct sockaddr *) &sin_from, &addrlen);
49 if (rc < 0)
50 return;
51 if (sin_from.sin_addr.s_addr != ep->rtp_pstn.remote_addr.sin_addr.s_addr
52 || sin_from.sin_port != ep->rtp_pstn.remote_addr.sin_port) {
53 if (!(ep->p2g_err_flags & ERR_WRONG_UDP_SRC)) {
54 syslog(LOG_ERR,
55 "PSTN RTP ep got UDP packet from wrong source");
56 ep->p2g_err_flags |= ERR_WRONG_UDP_SRC;
57 }
58 return;
59 }
60 if (rc != RTP_PACKET_SIZE_PSTN) {
61 bad_rtp_pkt: if (!(ep->p2g_err_flags & ERR_BAD_RTP_PACKET)) {
62 syslog(LOG_ERR, "Rx bad RTP packet on PSTN side");
63 ep->p2g_err_flags |= ERR_BAD_RTP_PACKET;
64 }
65 return;
66 }
67 if (pkt.v_p_x_cc != 0x80)
68 goto bad_rtp_pkt;
69 switch (pkt.m_pt & 0x7F) {
70 case PSTN_CODEC_PCMU:
71 pcm_dec_table = pcmu_decode_table;
72 break;
73 case PSTN_CODEC_PCMA:
74 pcm_dec_table = pcma_decode_table;
75 break;
76 default:
77 goto bad_rtp_pkt;
78 }
79 if (ep->p2g_state && pkt.ssrc != ep->p2g_ssrc) {
80 if (!(ep->p2g_err_flags & ERR_SSRC_CHANGE)) {
81 syslog(LOG_ERR, "PSTN RTP stream changed SSRC");
82 ep->p2g_err_flags |= ERR_SSRC_CHANGE;
83 }
84 ep->p2g_state = 0;
85 }
86 if (ep->p2g_state) {
87 seq_delta = ntohs(pkt.seq) - ep->p2g_last_seq;
88 ts_delta = ntohl(pkt.tstamp) - ep->p2g_last_ts;
89 if (seq_delta <= 0)
90 return; /* discard old or duplicate */
91 if (seq_delta != 1) {
92 if (!(ep->p2g_err_flags & ERR_SEQ_BREAK)) {
93 syslog(LOG_ERR, "PSTN RTP stream seq break");
94 ep->p2g_err_flags |= ERR_SEQ_BREAK;
95 }
96 m_out = 1;
97 } else if (ts_delta != SAMPLES_PER_FRAME) {
98 if (!(ep->p2g_err_flags & ERR_TSTAMP_BREAK)) {
99 syslog(LOG_ERR, "PSTN RTP stream tstamp break");
100 ep->p2g_err_flags |= ERR_TSTAMP_BREAK;
101 }
102 m_out = 1;
103 } else
104 m_out = 0;
105 } else
106 m_out = 1;
107 ep->p2g_state = 1;
108 ep->p2g_ssrc = pkt.ssrc;
109 ep->p2g_last_ts = htonl(pkt.tstamp);
110 ep->p2g_last_seq = htons(pkt.seq);
111 /* actual transcoding and forwarding */
112 for (n = 0; n < SAMPLES_PER_FRAME; n++)
113 pcm_samples[n] = pcm_dec_table[pkt.payload[n]];
114 pkt.m_pt = ep->gsm_payload_type;
115 if (m_out)
116 pkt.m_pt |= 0x80;
117 switch (ep->gsm_payload_msg_type) {
118 case GSM_TCHF_FRAME:
119 gsm_encode(ep->gsm_encoder_state, pcm_samples, pkt.payload);
120 n = RTP_PACKET_SIZE_GSM_FR;
121 break;
122 }
123 addrlen = sizeof(struct sockaddr_in);
124 sendto(ep->rtp_gsm.rtp_fd, &pkt, n, 0,
125 (struct sockaddr *) &ep->rtp_gsm.remote_addr, addrlen);
126 }
127
128 pstn2gsm_init(ep)
129 struct endpoint *ep;
130 {
131 switch (ep->gsm_payload_msg_type) {
132 case GSM_TCHF_FRAME:
133 ep->gsm_encoder_state = gsm_create();
134 if (!ep->gsm_encoder_state)
135 return TMGW_RESP_ERR_RSRC;
136 break;
137 }
138 select_handlers[ep->rtp_pstn.rtp_fd] = pstn2gsm_rtp_in;
139 return TMGW_RESP_OK;
140 }