aboutsummaryrefslogtreecommitdiffstats
path: root/src/mgcp_ss7.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mgcp_ss7.c')
-rw-r--r--src/mgcp_ss7.c72
1 files changed, 72 insertions, 0 deletions
diff --git a/src/mgcp_ss7.c b/src/mgcp_ss7.c
index 47c162b..c9e9b4f 100644
--- a/src/mgcp_ss7.c
+++ b/src/mgcp_ss7.c
@@ -70,6 +70,44 @@ static void mgcp_ss7_do_exec(struct mgcp_ss7 *mgcp, uint8_t type, struct mgcp_en
/* Contains a mapping from UniPorte to the MGCP side of things */
static struct mgcp_endpoint *s_endpoints[240];
+static void play_pending_tones(struct mgcp_endpoint *endp)
+{
+ ToneGenerationT toneGeneration;
+ char tones[25];
+
+ /* Check if we need to play anything? */
+ dtmf_state_get_pending(&endp->dtmf_state, tones);
+
+ /* nothing to play? */
+ if (strlen(tones) == 0)
+ return;
+
+ /* fill out the data now */
+ osmo_static_assert(sizeof(tones) <= sizeof(toneGeneration.list), Enough_space_for_tones);
+ memset(&toneGeneration, 0, sizeof(toneGeneration));
+ toneGeneration.count = strlen(tones);
+ strcpy(toneGeneration.list, tones);
+ MtnSaSetMOB(endp->audio_port, ChannelType_PORT,
+ PredefMob_C_TONE_GENERATION, (char *) &toneGeneration,
+ sizeof(toneGeneration), 1);
+}
+
+static void send_dtmf(struct mgcp_endpoint *mgw_endp, int ascii_tone)
+{
+ int rc;
+ rc = dtmf_state_add(&mgw_endp->dtmf_state, ascii_tone);
+ if (rc != 0) {
+ fprintf(stderr, "DTMF queue too long on 0x%x\n",
+ ENDPOINT_NUMBER(mgw_endp));
+ syslog(LOG_ERR, "DTMF queue too long on 0x%x\n",
+ ENDPOINT_NUMBER(mgw_endp));
+ return;
+ }
+
+ if (!mgw_endp->dtmf_state.playing)
+ play_pending_tones(mgw_endp);
+}
+
static int select_voice_port(struct mgcp_endpoint *endp)
{
int mgw_port;
@@ -200,6 +238,24 @@ static int uniporte_events(unsigned long port, EventTypeT event,
fprintf(stderr, "State change on a non blocked port. ERROR.\n");
}
endp->block_processing = 0;
+ } else if (info->trapId == Trap_TONE_GENERATION_COMPLETE) {
+ sprintf(text, "DTMF complete on #%ld", port);
+ puts(text);
+
+ /* update the mgcp state */
+ if (port >= ARRAY_SIZE(s_endpoints)) {
+ syslog(LOG_ERR, "The port is bigger than we can manage.\n");
+ fprintf(stderr, "The port is bigger than we can manage.\n");
+ return 0;
+ }
+
+ endp = s_endpoints[port];
+ if (!endp) {
+ syslog(LOG_ERR, "Unexpected event on port %d\n", port);
+ fprintf(stderr, "Unexpected event on port %d\n", port);
+ return 0;
+ }
+ play_pending_tones(endp);
}
}
else if ( event == Event_MANAGED_OBJECT_SET_COMPLETE ) {
@@ -356,6 +412,9 @@ static void allocate_endp(struct mgcp_ss7 *ss7, struct mgcp_endpoint *endp)
int mgw_port;
unsigned long mgw_address, loc_address;
+ /* reset the DTMF state */
+ dtmf_state_init(&endp->dtmf_state);
+
/* now find the voice processor we want to use */
mgw_port = select_voice_port(endp);
if (mgw_port < 0)
@@ -471,6 +530,10 @@ static void mgcp_ss7_do_exec(struct mgcp_ss7 *mgcp, uint8_t type,
if (mgw_endp->audio_port != UINT_MAX)
update_mute_status(mgw_endp->audio_port, param);
break;
+ case MGCP_SS7_DTMF:
+ if (mgw_endp->audio_port != UINT_MAX)
+ send_dtmf(mgw_endp, param);
+ break;
case MGCP_SS7_DELETE:
if (mgw_endp->audio_port != UINT_MAX) {
rc = MtnSaDisconnect(mgw_endp->audio_port);
@@ -487,6 +550,7 @@ static void mgcp_ss7_do_exec(struct mgcp_ss7 *mgcp, uint8_t type,
mgw_endp->audio_port = UINT_MAX;
mgw_endp->block_processing = 1;
}
+ dtmf_state_init(&mgw_endp->dtmf_state);
hw_maybe_loop_endp(mgw_endp);
break;
case MGCP_SS7_ALLOCATE:
@@ -579,6 +643,12 @@ static int mgcp_ss7_policy(struct mgcp_trunk_config *tcfg, int endp_no, int stat
return rc;
}
+static int mgcp_dtmf_cb(struct mgcp_endpoint *endp, char tone, const char *data)
+{
+ mgcp_ss7_exec(endp, MGCP_SS7_DTMF, tone);
+ return 0;
+}
+
static void enqueue_msg(struct osmo_wqueue *queue, struct sockaddr_in *addr, struct msgb *msg)
{
struct sockaddr_in *data;
@@ -905,6 +975,8 @@ int main(int argc, char **argv)
return -1;
}
+ g_cfg->rqnt_cb = mgcp_dtmf_cb;
+
if (mgcp_parse_config(config_file, g_cfg) != 0) {
LOGP(DMGCP, LOGL_ERROR,
"Failed to parse the config file: '%s'\n", config_file);