| 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 } |