comparison mgw/gsm2pstn.c @ 103:3b3f07b112f3

mgw: implement GSM to PSTN forwarding
author Mychaela Falconia <falcon@freecalypso.org>
date Mon, 26 Sep 2022 20:46:19 -0800
parents
children f062c32a5116
comparison
equal deleted inserted replaced
102:d26d97974c8a 103:3b3f07b112f3
1 /*
2 * In this module we implement our RTP gateway function
3 * in the GSM to PSTN 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 #define ERR_WRONG_UDP_SRC 0x0001
24 #define ERR_BAD_RTP_PACKET 0x0002
25 #define ERR_SSRC_CHANGE 0x0004
26 #define ERR_SEQ_BREAK 0x0008
27 #define ERR_TSTAMP_BREAK 0x0010
28
29 void
30 gsm2pstn_rtp_in(in_fd, ep)
31 struct endpoint *ep;
32 {
33 struct rtp_packet pkt;
34 struct sockaddr_in sin_from;
35 socklen_t addrlen;
36 int16_t seq_delta;
37 int32_t ts_delta;
38 int16_t pcm_samples[SAMPLES_PER_FRAME];
39 int rc, m_out;
40
41 addrlen = sizeof(struct sockaddr_in);
42 rc = recvfrom(in_fd, &pkt, sizeof pkt, 0,
43 (struct sockaddr *) &sin_from, &addrlen);
44 if (rc < 0)
45 return;
46 if (sin_from.sin_addr.s_addr != ep->rtp_gsm.remote_addr.sin_addr.s_addr
47 || sin_from.sin_port != ep->rtp_gsm.remote_addr.sin_port) {
48 if (!(ep->g2p_err_flags & ERR_WRONG_UDP_SRC)) {
49 syslog(LOG_ERR,
50 "GSM RTP ep got UDP packet from wrong source");
51 ep->g2p_err_flags |= ERR_WRONG_UDP_SRC;
52 }
53 return;
54 }
55 if (rc != ep->gsm_rtp_pkt_size) {
56 bad_rtp_pkt: if (!(ep->g2p_err_flags & ERR_BAD_RTP_PACKET)) {
57 syslog(LOG_ERR, "Rx bad RTP packet on GSM side");
58 ep->g2p_err_flags |= ERR_BAD_RTP_PACKET;
59 }
60 return;
61 }
62 if (pkt.v_p_x_cc != 0x80)
63 goto bad_rtp_pkt;
64 if ((pkt.m_pt & 0x7F) != ep->gsm_payload_type)
65 goto bad_rtp_pkt;
66 if ((pkt.payload[0] & 0xF0) != ep->gsm_payload_magic)
67 goto bad_rtp_pkt;
68 if (ep->g2p_state && pkt.ssrc != ep->g2p_ssrc) {
69 if (!(ep->g2p_err_flags & ERR_SSRC_CHANGE)) {
70 syslog(LOG_ERR, "GSM RTP stream changed SSRC");
71 ep->g2p_err_flags |= ERR_SSRC_CHANGE;
72 }
73 ep->g2p_state = 0;
74 }
75 if (ep->g2p_state) {
76 seq_delta = ntohs(pkt.seq) - ep->g2p_last_seq;
77 ts_delta = ntohl(pkt.tstamp) - ep->g2p_last_ts;
78 if (seq_delta <= 0)
79 return; /* discard old or duplicate */
80 if (seq_delta != 1) {
81 if (!(ep->g2p_err_flags & ERR_SEQ_BREAK)) {
82 syslog(LOG_ERR, "GSM RTP stream seq break");
83 ep->g2p_err_flags |= ERR_SEQ_BREAK;
84 }
85 m_out = 1;
86 } else {
87 if (ts_delta == SAMPLES_PER_FRAME)
88 m_out = 0;
89 else if (ts_delta > 0 &&
90 ts_delta % SAMPLES_PER_FRAME == 0)
91 m_out = 1;
92 else {
93 if (!(ep->g2p_err_flags & ERR_TSTAMP_BREAK)) {
94 syslog(LOG_ERR,
95 "GSM RTP stream tstamp break");
96 ep->g2p_err_flags |= ERR_TSTAMP_BREAK;
97 }
98 m_out = 1;
99 }
100 }
101 } else
102 m_out = 1;
103 ep->g2p_state = 1;
104 ep->g2p_ssrc = pkt.ssrc;
105 ep->g2p_last_ts = ntohl(pkt.tstamp);
106 ep->g2p_last_seq = ntohs(pkt.seq);
107 /* actual transcoding and forwarding */
108 if (!(ep->fwd_mode & TMGW_FWD_ENABLE_GSM2PSTN)) {
109 ep->g2p_drop_flag = 1;
110 return;
111 }
112 if (ep->g2p_drop_flag) {
113 ep->g2p_drop_flag = 0;
114 m_out = 1;
115 }
116 switch (ep->gsm_payload_msg_type) {
117 case GSM_TCHF_FRAME:
118 gsm_decode(ep->gsm_decoder_state, pkt.payload, pcm_samples);
119 break;
120 }
121 pkt.m_pt = ep->pstn_payload_type;
122 if (m_out)
123 pkt.m_pt |= 0x80;
124 pkt.seq = htons(++ep->g2p_out_seq);
125 g711_encode_frame(pcm_samples, pkt.payload, ep->pstn_payload_type);
126 addrlen = sizeof(struct sockaddr_in);
127 sendto(ep->rtp_pstn.rtp_fd, &pkt, RTP_PACKET_SIZE_PSTN, 0,
128 (struct sockaddr *) &ep->rtp_pstn.remote_addr, addrlen);
129 }
130
131 gsm2pstn_init(ep)
132 struct endpoint *ep;
133 {
134 if (ep->gsm_decoder_state)
135 return TMGW_RESP_OK;
136 switch (ep->gsm_payload_msg_type) {
137 case GSM_TCHF_FRAME:
138 ep->gsm_decoder_state = gsm_create();
139 if (!ep->gsm_decoder_state)
140 return TMGW_RESP_ERR_RSRC;
141 break;
142 }
143 select_handlers[ep->rtp_gsm.rtp_fd] = gsm2pstn_rtp_in;
144 return TMGW_RESP_OK;
145 }