annotate mgw/dtmf_ctrl.c @ 150:529906fddcfa

mgw DTMF timing fix in the corner case of no speech arriving between the end of one DTMF and the start of next
author Mychaela Falconia <falcon@freecalypso.org>
date Tue, 11 Oct 2022 14:10:29 -0800
parents f062c32a5116
children a6eb2de277f6
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
127
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
1 /*
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
2 * In this module we implement start/stop control of DTMF generation
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
3 * toward PSTN on GSM-to-PSTN gateway endpoints.
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
4 */
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
5
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
6 #include <sys/types.h>
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
7 #include <sys/socket.h>
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
8 #include <sys/time.h>
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
9 #include <netinet/in.h>
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
10 #include <stdio.h>
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
11 #include <stdint.h>
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
12 #include <stdlib.h>
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
13 #include <string.h>
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
14 #include <strings.h>
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
15 #include <syslog.h>
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
16 #include "../include/tmgw_ctrl.h"
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
17 #include "../include/tmgw_const.h"
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
18 #include "struct.h"
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
19 #include "int_defs.h"
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
20 #include "dtmf_defs.h"
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
21
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
22 extern struct endpoint *find_ep_by_id();
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
23
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
24 extern struct timeval cur_event_time;
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
25 extern struct dtmf_desc dtmf_table[];
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
26 extern int dtmf_timer_running;
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
27
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
28 struct endpoint *dtmf_list_head;
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
29
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
30 static void
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
31 add_to_dtmf_list(new_ep)
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
32 struct endpoint *new_ep;
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
33 {
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
34 struct endpoint *ep, **epp;
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
35
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
36 for (epp = &dtmf_list_head; *epp; epp = &ep->dtmf_next)
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
37 ;
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
38 *epp = new_ep;
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
39 new_ep->dtmf_pp = epp;
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
40 }
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
41
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
42 void
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
43 dtmf_stop_immediate(ep)
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
44 struct endpoint *ep;
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
45 {
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
46 if (ep->dtmf_frames_sent)
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
47 ep->dtmf_aftermath = 1;
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
48 *ep->dtmf_pp = ep->dtmf_next;
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
49 if (ep->dtmf_next)
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
50 ep->dtmf_next->dtmf_pp = ep->dtmf_pp;
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
51 ep->dtmf_pp = 0;
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
52 ep->dtmf_next = 0;
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
53 if (!dtmf_list_head)
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
54 dtmf_timer_running = 0;
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
55 }
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
56
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
57 void
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
58 process_dtmf_start(conn, req, resp)
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
59 struct ctrl_conn *conn;
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
60 struct tmgw_ctrl_req *req;
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
61 struct tmgw_ctrl_resp *resp;
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
62 {
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
63 struct endpoint *ep;
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
64 struct dtmf_desc *desc;
150
529906fddcfa mgw DTMF timing fix in the corner case of no speech
Mychaela Falconia <falcon@freecalypso.org>
parents: 127
diff changeset
65 struct timeval tv_last, tv_diff;
127
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
66 unsigned delta_frames;
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
67
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
68 ep = find_ep_by_id(conn, req->ep_id);
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
69 if (!ep) {
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
70 protocol_err: resp->res = TMGW_RESP_ERR_PROT;
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
71 return;
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
72 }
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
73 if (ep->ep_type != TMGW_EP_TYPE_GATEWAY)
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
74 goto protocol_err;
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
75 if (!(ep->fwd_mode & TMGW_FWD_ENABLE_GSM2PSTN))
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
76 goto protocol_err;
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
77 for (desc = dtmf_table; desc->digit; desc++)
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
78 if (desc->digit == req->fwd_mode)
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
79 break;
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
80 if (!desc->digit) {
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
81 resp->res = TMGW_RESP_ERR_PARAM;
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
82 return;
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
83 }
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
84 if (ep->dtmf_pp) {
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
85 resp->res = TMGW_RESP_ERR_BUSY;
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
86 return;
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
87 }
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
88 if (!ep->g2p_state) {
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
89 resp->res = TMGW_RESP_ERR_NOTRDY;
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
90 return;
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
91 }
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
92 /* figure out starting timestamp */
150
529906fddcfa mgw DTMF timing fix in the corner case of no speech
Mychaela Falconia <falcon@freecalypso.org>
parents: 127
diff changeset
93 if (ep->dtmf_aftermath)
529906fddcfa mgw DTMF timing fix in the corner case of no speech
Mychaela Falconia <falcon@freecalypso.org>
parents: 127
diff changeset
94 tv_last = ep->dtmf_last_time;
529906fddcfa mgw DTMF timing fix in the corner case of no speech
Mychaela Falconia <falcon@freecalypso.org>
parents: 127
diff changeset
95 else {
127
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
96 ep->dtmf_last_ts = ep->g2p_last_ts;
150
529906fddcfa mgw DTMF timing fix in the corner case of no speech
Mychaela Falconia <falcon@freecalypso.org>
parents: 127
diff changeset
97 tv_last = ep->g2p_local_time;
529906fddcfa mgw DTMF timing fix in the corner case of no speech
Mychaela Falconia <falcon@freecalypso.org>
parents: 127
diff changeset
98 }
127
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
99 ep->dtmf_m_bit = 0;
150
529906fddcfa mgw DTMF timing fix in the corner case of no speech
Mychaela Falconia <falcon@freecalypso.org>
parents: 127
diff changeset
100 if (timercmp(&cur_event_time, &tv_last, >)) {
529906fddcfa mgw DTMF timing fix in the corner case of no speech
Mychaela Falconia <falcon@freecalypso.org>
parents: 127
diff changeset
101 timersub(&cur_event_time, &tv_last, &tv_diff);
127
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
102 delta_frames = tv_diff.tv_sec * 50 + tv_diff.tv_usec / 20000;
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
103 if (delta_frames) {
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
104 ep->dtmf_last_ts += delta_frames * SAMPLES_PER_FRAME;
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
105 ep->dtmf_m_bit = 1;
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
106 }
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
107 }
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
108 /* initialize other state vars */
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
109 ep->dtmf_frames_sent = 0;
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
110 ep->dtmf_sample_ptr = desc->samples;
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
111 ep->dtmf_stop_req = 0;
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
112 /* link it and start it */
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
113 add_to_dtmf_list(ep);
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
114 start_dtmf_timer();
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
115 /* return success */
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
116 resp->res = TMGW_RESP_OK;
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
117 }
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
118
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
119 void
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
120 process_dtmf_stop(conn, req, resp)
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
121 struct ctrl_conn *conn;
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
122 struct tmgw_ctrl_req *req;
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
123 struct tmgw_ctrl_resp *resp;
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
124 {
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
125 struct endpoint *ep;
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
126
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
127 ep = find_ep_by_id(conn, req->ep_id);
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
128 if (!ep) {
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
129 protocol_err: resp->res = TMGW_RESP_ERR_PROT;
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
130 return;
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
131 }
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
132 if (ep->ep_type != TMGW_EP_TYPE_GATEWAY)
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
133 goto protocol_err;
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
134 /* return OK whether we stop a tone or if there was none running */
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
135 resp->res = TMGW_RESP_OK;
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
136 if (ep->dtmf_pp) {
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
137 ep->dtmf_stop_req = 1;
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
138 if (ep->dtmf_frames_sent >= DTMF_MIN_FRAMES)
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
139 dtmf_stop_immediate(ep);
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
140 }
f062c32a5116 mgw: implement DTMF
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
141 }