FreeCalypso > hg > themwi-system-sw
view mgw/dtmf_ctrl.c @ 128:5685412bd6aa
sip-in: pass DTMF start & stop to themwi-mgw
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Sat, 01 Oct 2022 23:07:01 -0800 |
parents | f062c32a5116 |
children | 529906fddcfa |
line wrap: on
line source
/* * In this module we implement start/stop control of DTMF generation * toward PSTN on GSM-to-PSTN gateway endpoints. */ #include <sys/types.h> #include <sys/socket.h> #include <sys/time.h> #include <netinet/in.h> #include <stdio.h> #include <stdint.h> #include <stdlib.h> #include <string.h> #include <strings.h> #include <syslog.h> #include "../include/tmgw_ctrl.h" #include "../include/tmgw_const.h" #include "struct.h" #include "int_defs.h" #include "dtmf_defs.h" extern struct endpoint *find_ep_by_id(); extern struct timeval cur_event_time; extern struct dtmf_desc dtmf_table[]; extern int dtmf_timer_running; struct endpoint *dtmf_list_head; static void add_to_dtmf_list(new_ep) struct endpoint *new_ep; { struct endpoint *ep, **epp; for (epp = &dtmf_list_head; *epp; epp = &ep->dtmf_next) ; *epp = new_ep; new_ep->dtmf_pp = epp; } void dtmf_stop_immediate(ep) struct endpoint *ep; { if (ep->dtmf_frames_sent) ep->dtmf_aftermath = 1; *ep->dtmf_pp = ep->dtmf_next; if (ep->dtmf_next) ep->dtmf_next->dtmf_pp = ep->dtmf_pp; ep->dtmf_pp = 0; ep->dtmf_next = 0; if (!dtmf_list_head) dtmf_timer_running = 0; } void process_dtmf_start(conn, req, resp) struct ctrl_conn *conn; struct tmgw_ctrl_req *req; struct tmgw_ctrl_resp *resp; { struct endpoint *ep; struct dtmf_desc *desc; struct timeval tv_diff; unsigned delta_frames; ep = find_ep_by_id(conn, req->ep_id); if (!ep) { protocol_err: resp->res = TMGW_RESP_ERR_PROT; return; } if (ep->ep_type != TMGW_EP_TYPE_GATEWAY) goto protocol_err; if (!(ep->fwd_mode & TMGW_FWD_ENABLE_GSM2PSTN)) goto protocol_err; for (desc = dtmf_table; desc->digit; desc++) if (desc->digit == req->fwd_mode) break; if (!desc->digit) { resp->res = TMGW_RESP_ERR_PARAM; return; } if (ep->dtmf_pp) { resp->res = TMGW_RESP_ERR_BUSY; return; } if (!ep->g2p_state) { resp->res = TMGW_RESP_ERR_NOTRDY; return; } /* figure out starting timestamp */ if (!ep->dtmf_aftermath) ep->dtmf_last_ts = ep->g2p_last_ts; ep->dtmf_m_bit = 0; if (timercmp(&cur_event_time, &ep->g2p_local_time, >)) { timersub(&cur_event_time, &ep->g2p_local_time, &tv_diff); delta_frames = tv_diff.tv_sec * 50 + tv_diff.tv_usec / 20000; if (delta_frames) { ep->dtmf_last_ts += delta_frames * SAMPLES_PER_FRAME; ep->dtmf_m_bit = 1; } } /* initialize other state vars */ ep->dtmf_frames_sent = 0; ep->dtmf_sample_ptr = desc->samples; ep->dtmf_stop_req = 0; /* link it and start it */ add_to_dtmf_list(ep); start_dtmf_timer(); /* return success */ resp->res = TMGW_RESP_OK; } void process_dtmf_stop(conn, req, resp) struct ctrl_conn *conn; struct tmgw_ctrl_req *req; struct tmgw_ctrl_resp *resp; { struct endpoint *ep; ep = find_ep_by_id(conn, req->ep_id); if (!ep) { protocol_err: resp->res = TMGW_RESP_ERR_PROT; return; } if (ep->ep_type != TMGW_EP_TYPE_GATEWAY) goto protocol_err; /* return OK whether we stop a tone or if there was none running */ resp->res = TMGW_RESP_OK; if (ep->dtmf_pp) { ep->dtmf_stop_req = 1; if (ep->dtmf_frames_sent >= DTMF_MIN_FRAMES) dtmf_stop_immediate(ep); } }