mirror of
https://github.com/signalwire/freeswitch.git
synced 2026-07-23 20:51:58 +00:00
dtmf overhaul testers wanted
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@6952 d0543943-73ff-0310-b7d9-9358b9ac24b2
This commit is contained in:
@@ -540,9 +540,9 @@ static switch_status_t sofia_read_frame(switch_core_session_t *session, switch_f
|
||||
payload = tech_pvt->read_frame.payload;
|
||||
|
||||
if (switch_rtp_has_dtmf(tech_pvt->rtp_session)) {
|
||||
char dtmf[128];
|
||||
switch_rtp_dequeue_dtmf(tech_pvt->rtp_session, dtmf, sizeof(dtmf));
|
||||
switch_channel_queue_dtmf(channel, dtmf);
|
||||
switch_dtmf_t dtmf = {0};
|
||||
switch_rtp_dequeue_dtmf(tech_pvt->rtp_session, &dtmf);
|
||||
switch_channel_queue_dtmf(channel, &dtmf);
|
||||
}
|
||||
|
||||
|
||||
@@ -696,15 +696,31 @@ static switch_status_t sofia_waitfor_write(switch_core_session_t *session, int m
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static switch_status_t sofia_send_dtmf(switch_core_session_t *session, char *digits)
|
||||
static switch_status_t sofia_send_dtmf(switch_core_session_t *session, const switch_dtmf_t *dtmf)
|
||||
{
|
||||
private_object_t *tech_pvt;
|
||||
char message[128] = "";
|
||||
|
||||
tech_pvt = (private_object_t *) switch_core_session_get_private(session);
|
||||
switch_assert(tech_pvt != NULL);
|
||||
|
||||
return switch_rtp_queue_rfc2833(tech_pvt->rtp_session,
|
||||
digits, tech_pvt->profile->dtmf_duration * (tech_pvt->read_codec.implementation->samples_per_second / 1000));
|
||||
switch (tech_pvt->dtmf_type) {
|
||||
case DTMF_2833:
|
||||
return switch_rtp_queue_rfc2833(tech_pvt->rtp_session, dtmf);
|
||||
|
||||
case DTMF_INFO:
|
||||
snprintf(message, sizeof(message), "Signal=%c\r\nDuration=%d\r\n", dtmf->digit, dtmf->duration);
|
||||
nua_info(tech_pvt->nh,
|
||||
//NUTAG_WITH_THIS(tech_pvt->profile->nua),
|
||||
SIPTAG_CONTENT_TYPE_STR("application/dtmf-relay"),
|
||||
SIPTAG_PAYLOAD_STR(message),
|
||||
TAG_END());
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static switch_status_t sofia_receive_message(switch_core_session_t *session, switch_core_session_message_t *msg)
|
||||
|
||||
@@ -83,6 +83,13 @@ typedef struct private_object private_object_t;
|
||||
#include <sofia-sip/nea.h>
|
||||
#include <sofia-sip/msg_addr.h>
|
||||
|
||||
|
||||
typedef enum {
|
||||
DTMF_2833,
|
||||
DTMF_INFO,
|
||||
DTMF_NONE
|
||||
} sofia_dtmf_t;
|
||||
|
||||
struct sofia_private {
|
||||
char uuid[SWITCH_UUID_FORMATTED_LENGTH + 1];
|
||||
sofia_gateway_t *gateway;
|
||||
@@ -232,6 +239,8 @@ struct sofia_profile {
|
||||
char *tls_cert_dir;
|
||||
char *reg_domain;
|
||||
char *user_agent;
|
||||
char *record_template;
|
||||
sofia_dtmf_t dtmf_type;
|
||||
int sip_port;
|
||||
int tls_sip_port;
|
||||
char *codec_string;
|
||||
@@ -357,6 +366,7 @@ struct private_object {
|
||||
switch_payload_t video_agreed_pt;
|
||||
char *video_fmtp_out;
|
||||
uint32_t video_count;
|
||||
sofia_dtmf_t dtmf_type;
|
||||
};
|
||||
|
||||
struct callback_t {
|
||||
@@ -547,3 +557,4 @@ sofia_transport_t sofia_glue_url2transport(const url_t *url);
|
||||
const char *sofia_glue_transport2str(const sofia_transport_t tp);
|
||||
|
||||
int sofia_glue_transport_has_tls(const sofia_transport_t tp);
|
||||
const char *sofia_glue_get_unknown_header(sip_t const *sip, const char *name);
|
||||
|
||||
@@ -884,6 +884,16 @@ switch_status_t config_sofia(int reload, char *profile_name)
|
||||
|
||||
} else if (!strcasecmp(var, "user-agent-string")) {
|
||||
profile->user_agent = switch_core_strdup(profile->pool, val);;
|
||||
} else if (!strcasecmp(var, "dtmf-type")) {
|
||||
if (!strcasecmp(val, "rfc2833")) {
|
||||
profile->dtmf_type = DTMF_2833;
|
||||
} else if (!strcasecmp(val, "info")) {
|
||||
profile->dtmf_type = DTMF_INFO;
|
||||
} else {
|
||||
profile->dtmf_type = DTMF_NONE;
|
||||
}
|
||||
} else if (!strcasecmp(var, "record-template")) {
|
||||
profile->record_template = switch_core_strdup(profile->pool, val);;
|
||||
} else if (!strcasecmp(var, "inbound-no-media") && switch_true(val)) {
|
||||
switch_set_flag(profile, TFLAG_INB_NOMEDIA);
|
||||
} else if (!strcasecmp(var, "inbound-late-negotiation") && switch_true(val)) {
|
||||
@@ -1916,57 +1926,108 @@ void sofia_handle_sip_i_info(nua_t *nua, sofia_profile_t *profile, nua_handle_t
|
||||
{
|
||||
struct private_object *tech_pvt = NULL;
|
||||
switch_channel_t *channel = NULL;
|
||||
char dtmf_digit[2] = { 0, 0 };
|
||||
|
||||
/* placeholder for string searching */
|
||||
char *signal_ptr;
|
||||
const char *rec_header;
|
||||
|
||||
/* Try and find signal information in the payload */
|
||||
signal_ptr = strstr(sip->sip_payload->pl_data, "Signal=");
|
||||
if (session) {
|
||||
/* Get the channel */
|
||||
channel = switch_core_session_get_channel(session);
|
||||
|
||||
/* unknown info type */
|
||||
if (!signal_ptr) {
|
||||
sip_from_t const *from = sip->sip_from;
|
||||
/* Barf if we didn't get it */
|
||||
switch_assert(channel != NULL);
|
||||
|
||||
/* make sure we have our privates */
|
||||
tech_pvt = switch_core_session_get_private(session);
|
||||
|
||||
/* Barf if we didn't get it */
|
||||
switch_assert(tech_pvt != NULL);
|
||||
|
||||
/* print in the logs if something comes through we don't understand */
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Unknown INFO Recieved: %s%s" URL_PRINT_FORMAT "[%s]\n",
|
||||
from->a_display ? from->a_display : "",
|
||||
from->a_display ? " " : "",
|
||||
URL_PRINT_ARGS(from->a_url),
|
||||
sip->sip_payload->pl_data);
|
||||
/* Send 415 Unsupported Media response */
|
||||
nua_respond(nh, SIP_415_UNSUPPORTED_MEDIA, NUTAG_WITH_THIS(nua), TAG_END());
|
||||
return;
|
||||
|
||||
if (sip && sip->sip_payload && sip->sip_payload->pl_data) {
|
||||
switch_dtmf_t dtmf = { 0, SWITCH_DEFAULT_DTMF_DURATION };
|
||||
|
||||
/* Try and find signal information in the payload */
|
||||
if ((signal_ptr = strstr(sip->sip_payload->pl_data, "Signal="))) {
|
||||
/* move signal_ptr where we need it (right past Signal=) */
|
||||
signal_ptr = signal_ptr + 7;
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Bad signal\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* unknown info type */
|
||||
if (!signal_ptr) {
|
||||
sip_from_t const *from = sip->sip_from;
|
||||
|
||||
/* print in the logs if something comes through we don't understand */
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Unknown INFO Recieved: %s%s" URL_PRINT_FORMAT "[%s]\n",
|
||||
from->a_display ? from->a_display : "",
|
||||
from->a_display ? " " : "",
|
||||
URL_PRINT_ARGS(from->a_url),
|
||||
sip->sip_payload->pl_data);
|
||||
/* Send 415 Unsupported Media response */
|
||||
nua_respond(nh, SIP_415_UNSUPPORTED_MEDIA, NUTAG_WITH_THIS(nua), TAG_END());
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
dtmf.digit = *signal_ptr;
|
||||
if ((signal_ptr = strstr(sip->sip_payload->pl_data, "Duration="))) {
|
||||
int tmp;
|
||||
signal_ptr += 8;
|
||||
if ((tmp = atoi(signal_ptr)) < 0) {
|
||||
tmp = SWITCH_DEFAULT_DTMF_DURATION;
|
||||
}
|
||||
dtmf.duration = tmp;
|
||||
}
|
||||
|
||||
/* queue it up */
|
||||
switch_channel_queue_dtmf(channel, &dtmf);
|
||||
|
||||
/* print debug info */
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "INFO DTMF(%c)\n", dtmf.digit);
|
||||
|
||||
/* Send 200 OK response */
|
||||
nua_respond(nh, SIP_200_OK, NUTAG_WITH_THIS(nua), TAG_END());
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if ((rec_header = sofia_glue_get_unknown_header(sip, "record"))) {
|
||||
if (switch_strlen_zero(profile->record_template)) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Record attempted but no template defined.\n");
|
||||
nua_respond(nh, 488, "Recording not enabled", NUTAG_WITH_THIS(nua), TAG_END());
|
||||
} else {
|
||||
if (!strcasecmp(rec_header, "on")) {
|
||||
char *file;
|
||||
|
||||
file = switch_channel_expand_variables(channel, profile->record_template);
|
||||
switch_ivr_record_session(session, file, 0, NULL);
|
||||
switch_channel_set_variable(channel, "sofia_record_file", file);
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Recording %s to %s\n", switch_channel_get_name(channel), file);
|
||||
nua_respond(nh, SIP_200_OK, NUTAG_WITH_THIS(nua), TAG_END());
|
||||
if (file != profile->record_template) {
|
||||
free(file);
|
||||
file = NULL;
|
||||
}
|
||||
} else {
|
||||
const char *file;
|
||||
|
||||
if ((file = switch_channel_get_variable(channel, "sofia_record_file"))) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Done recording %s to %s\n", switch_channel_get_name(channel), file);
|
||||
switch_ivr_stop_record_session(session, file);
|
||||
nua_respond(nh, SIP_200_OK, NUTAG_WITH_THIS(nua), TAG_END());
|
||||
} else {
|
||||
nua_respond(nh, 488, "Nothing to stop", NUTAG_WITH_THIS(nua), TAG_END());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Get the channel */
|
||||
channel = switch_core_session_get_channel(session);
|
||||
|
||||
/* Barf if we didn't get it */
|
||||
switch_assert(channel != NULL);
|
||||
|
||||
/* make sure we have our privates */
|
||||
tech_pvt = switch_core_session_get_private(session);
|
||||
|
||||
/* Barf if we didn't get it */
|
||||
switch_assert(tech_pvt != NULL);
|
||||
|
||||
/* move signal_ptr where we need it (right past Signal=) */
|
||||
signal_ptr = signal_ptr + 7;
|
||||
|
||||
/* put the digit somewhere we can muck with */
|
||||
strncpy(dtmf_digit, signal_ptr, 1);
|
||||
|
||||
/* queue it up */
|
||||
switch_channel_queue_dtmf(channel, dtmf_digit);
|
||||
|
||||
/* print debug info */
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "INFO DTMF(%s)\n", dtmf_digit);
|
||||
|
||||
/* Send 200 OK response */
|
||||
nua_respond(nh, SIP_200_OK, NUTAG_WITH_THIS(nua), TAG_END());
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -347,6 +347,10 @@ void sofia_glue_attach_private(switch_core_session_t *session, sofia_profile_t *
|
||||
tech_pvt->te = profile->te;
|
||||
}
|
||||
|
||||
|
||||
tech_pvt->dtmf_type = profile->dtmf_type;
|
||||
|
||||
|
||||
if (tech_pvt->bcng_pt) {
|
||||
tech_pvt->cng_pt = tech_pvt->bcng_pt;
|
||||
} else if (!tech_pvt->cng_pt) {
|
||||
@@ -387,6 +391,20 @@ switch_status_t sofia_glue_ext_address_lookup(char **ip, switch_port_t *port, ch
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
const char *sofia_glue_get_unknown_header(sip_t const *sip, const char *name)
|
||||
{
|
||||
sip_unknown_t *un;
|
||||
for (un = sip->sip_unknown; un; un = un->un_next) {
|
||||
if (!strcasecmp(un->un_name, name)) {
|
||||
if (!switch_strlen_zero(un->un_value)) {
|
||||
return un->un_value;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
switch_status_t sofia_glue_tech_choose_port(private_object_t *tech_pvt)
|
||||
{
|
||||
char *ip = tech_pvt->profile->rtpip;
|
||||
@@ -1097,6 +1115,16 @@ switch_status_t sofia_glue_activate_rtp(private_object_t *tech_pvt, switch_rtp_f
|
||||
flags |= SWITCH_RTP_FLAG_BUGGY_2833;
|
||||
}
|
||||
|
||||
if ((val = switch_channel_get_variable(tech_pvt->channel, "dtmf_type"))) {
|
||||
if (!strcasecmp(val, "rfc2833")) {
|
||||
tech_pvt->dtmf_type = DTMF_2833;
|
||||
} else if (!strcasecmp(val, "info")) {
|
||||
tech_pvt->dtmf_type = DTMF_INFO;
|
||||
} else {
|
||||
tech_pvt->dtmf_type = tech_pvt->profile->dtmf_type;
|
||||
}
|
||||
}
|
||||
|
||||
if ((tech_pvt->profile->pflags & PFLAG_PASS_RFC2833)
|
||||
|| ((val = switch_channel_get_variable(tech_pvt->channel, "pass_rfc2833")) && switch_true(val))) {
|
||||
flags |= SWITCH_RTP_FLAG_PASS_RFC2833;
|
||||
|
||||
Reference in New Issue
Block a user