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