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:
Anthony Minessale 2007-12-22 00:32:20 +00:00
parent 601f7b6e4a
commit 2931fc9109
33 changed files with 475 additions and 313 deletions

View File

@ -168,6 +168,7 @@ struct switch_runtime {
uint32_t flags;
switch_time_t timestamp;
switch_mutex_t *throttle_mutex;
switch_mutex_t *global_mutex;
uint32_t sps_total;
int32_t sps;
int32_t sps_last;

View File

@ -422,19 +422,20 @@ SWITCH_DECLARE(switch_size_t) switch_channel_has_dtmf(switch_channel_t *channel)
/*!
\brief Queue DTMF on a given channel
\param channel channel to queue DTMF to
\param dtmf string of digits to queue
\param dtmf digit
\return SWITCH_STATUS_SUCCESS if successful
*/
SWITCH_DECLARE(switch_status_t) switch_channel_queue_dtmf(switch_channel_t *channel, const char *dtmf);
SWITCH_DECLARE(switch_status_t) switch_channel_queue_dtmf(switch_channel_t *channel, const switch_dtmf_t *dtmf);
/*!
\brief Retrieve DTMF digits from a given channel
\param channel channel to retrieve digits from
\param dtmf buffer to write dtmf to
\param len max size in bytes of the buffer
\param dtmf digit
\return number of bytes read into the buffer
*/
SWITCH_DECLARE(switch_size_t) switch_channel_dequeue_dtmf(switch_channel_t *channel, char *dtmf, switch_size_t len);
SWITCH_DECLARE(switch_status_t) switch_channel_dequeue_dtmf(switch_channel_t *channel, switch_dtmf_t *dtmf);
SWITCH_DECLARE(void) switch_channel_flush_dtmf(switch_channel_t *channel);
SWITCH_DECLARE(switch_size_t) switch_channel_dequeue_dtmf_string(switch_channel_t *channel, char *dtmf_str, switch_size_t len);
/*!
\brief Render the name of the provided state enum

View File

@ -829,7 +829,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_waitfor_write(switch_core_se
\param dtmf string to send to the session
\return SWITCH_STATUS_SUCCESS if the dtmf was written
*/
SWITCH_DECLARE(switch_status_t) switch_core_session_send_dtmf(switch_core_session_t *session, const char *dtmf);
SWITCH_DECLARE(switch_status_t) switch_core_session_send_dtmf(switch_core_session_t *session, const switch_dtmf_t *dtmf);
/*!
\brief RECV DTMF on a session
@ -837,7 +837,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_send_dtmf(switch_core_sessio
\param dtmf string to recv from the session
\return SWITCH_STATUS_SUCCESS if the dtmf is ok to queue
*/
SWITCH_DECLARE(switch_status_t) switch_core_session_recv_dtmf(switch_core_session_t *session, const char *dtmf);
SWITCH_DECLARE(switch_status_t) switch_core_session_recv_dtmf(switch_core_session_t *session, const switch_dtmf_t *dtmf);
///\}

View File

@ -59,8 +59,8 @@ typedef switch_status_t (*switch_video_write_frame_hook_t) (switch_core_session_
typedef switch_status_t (*switch_kill_channel_hook_t) (switch_core_session_t *, int);
typedef switch_status_t (*switch_waitfor_read_hook_t) (switch_core_session_t *, int, int);
typedef switch_status_t (*switch_waitfor_write_hook_t) (switch_core_session_t *, int, int);
typedef switch_status_t (*switch_send_dtmf_hook_t) (switch_core_session_t *, const char *);
typedef switch_status_t (*switch_recv_dtmf_hook_t) (switch_core_session_t *, const char *);
typedef switch_status_t (*switch_send_dtmf_hook_t) (switch_core_session_t *, const switch_dtmf_t *);
typedef switch_status_t (*switch_recv_dtmf_hook_t) (switch_core_session_t *, const switch_dtmf_t *);
typedef switch_status_t (*switch_state_change_hook_t) (switch_core_session_t *);

View File

@ -105,7 +105,7 @@ typedef switch_status_t (*switch_io_write_frame_t) (switch_core_session_t *, swi
typedef switch_status_t (*switch_io_kill_channel_t) (switch_core_session_t *, int);
typedef switch_status_t (*switch_io_waitfor_read_t) (switch_core_session_t *, int, int);
typedef switch_status_t (*switch_io_waitfor_write_t) (switch_core_session_t *, int, int);
typedef switch_status_t (*switch_io_send_dtmf_t) (switch_core_session_t *, char *);
typedef switch_status_t (*switch_io_send_dtmf_t) (switch_core_session_t *, const switch_dtmf_t *);
typedef switch_status_t (*switch_io_receive_message_t) (switch_core_session_t *, switch_core_session_message_t *);
typedef switch_status_t (*switch_io_receive_event_t) (switch_core_session_t *, switch_event_t *);
typedef switch_status_t (*switch_io_state_change_t) (switch_core_session_t *);

View File

@ -261,7 +261,8 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_read(switch_rtp_t *rtp_session, void
\param digits the digit string to queue
\param duration the duration of the dtmf
*/
SWITCH_DECLARE(switch_status_t) switch_rtp_queue_rfc2833(switch_rtp_t *rtp_session, char *digits, uint32_t duration);
SWITCH_DECLARE(switch_status_t) switch_rtp_queue_rfc2833(switch_rtp_t *rtp_session, const switch_dtmf_t *dtmf);
SWITCH_DECLARE(switch_status_t) switch_rtp_queue_rfc2833_in(switch_rtp_t *rtp_session, const switch_dtmf_t *dtmf);
/*!
\brief Test for presence of DTMF on a given RTP session
@ -270,22 +271,13 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_queue_rfc2833(switch_rtp_t *rtp_sessi
*/
SWITCH_DECLARE(switch_size_t) switch_rtp_has_dtmf(switch_rtp_t *rtp_session);
/*!
\brief Queue DTMF on a given RTP session
\param rtp_session RTP session to queue DTMF to
\param dtmf string of digits to queue
\return SWITCH_STATUS_SUCCESS if successful
*/
SWITCH_DECLARE(switch_status_t) switch_rtp_queue_dtmf(switch_rtp_t *rtp_session, char *dtmf);
/*!
\brief Retrieve DTMF digits from a given RTP session
\param rtp_session RTP session to retrieve digits from
\param dtmf buffer to write dtmf to
\param len max size in bytes of the buffer
\param dtmf the dtmf
\return number of bytes read into the buffer
*/
SWITCH_DECLARE(switch_size_t) switch_rtp_dequeue_dtmf(switch_rtp_t *rtp_session, char *dtmf, switch_size_t len);
SWITCH_DECLARE(switch_size_t) switch_rtp_dequeue_dtmf(switch_rtp_t *rtp_session, switch_dtmf_t *dtmf);
/*!
\brief Read data from a given RTP session without copying

View File

@ -92,7 +92,7 @@ SWITCH_BEGIN_EXTERN_C
#define SWITCH_SEQ_CLEARLINEEND SWITCH_SEQ_ESC SWITCH_SEQ_CLEARLINEEND_CHAR
#define SWITCH_SEQ_CLEARSCR SWITCH_SEQ_ESC SWITCH_SEQ_CLEARSCR_CHAR SWITCH_SEQ_HOME
#define SWITCH_DEFAULT_DTMF_DURATION 250
#define SWITCH_DEFAULT_DIR_PERMS SWITCH_FPROT_UREAD | SWITCH_FPROT_UWRITE | SWITCH_FPROT_UEXECUTE | SWITCH_FPROT_GREAD | SWITCH_FPROT_GEXECUTE
#ifdef WIN32
@ -136,6 +136,11 @@ SWITCH_BEGIN_EXTERN_C
#define SWITCH_BITS_PER_BYTE 8
typedef uint8_t switch_byte_t;
typedef struct {
char digit;
uint32_t duration;
} switch_dtmf_t;
typedef enum {
SOF_NONE = 0,
SOF_NOBLOCK = (1 << 0),

View File

@ -1648,7 +1648,7 @@ static void conference_loop_output(conference_member_t * member)
/* if we have caller digits, feed them to the parser to find an action */
if (switch_channel_has_dtmf(channel)) {
switch_channel_dequeue_dtmf(channel, dtmf, sizeof(dtmf));
switch_channel_dequeue_dtmf_string(channel, dtmf, sizeof(dtmf));
if (member->conference->dtmf_parser != NULL) {
@ -2637,6 +2637,8 @@ static switch_status_t conf_api_sub_dtmf(conference_member_t * member, switch_st
{
switch_event_t *event;
char *dtmf = (char *) data;
char *p = dtmf;
switch_dtmf_t _dtmf = { 0, SWITCH_DEFAULT_DTMF_DURATION };
if (member == NULL) {
stream->write_function(stream, "Invalid member!\n");
@ -2651,9 +2653,15 @@ static switch_status_t conf_api_sub_dtmf(conference_member_t * member, switch_st
switch_mutex_lock(member->flag_mutex);
switch_core_session_kill_channel(member->session, SWITCH_SIG_BREAK);
switch_core_session_send_dtmf(member->session, dtmf);
switch_mutex_unlock(member->flag_mutex);
while(p && *p) {
_dtmf.digit = *p;
switch_core_session_send_dtmf(member->session, &_dtmf);
p++;
}
switch_mutex_unlock(member->flag_mutex);
if (stream != NULL) {
stream->write_function(stream, "OK sent %s to %u\n", (char *) data, member->id);

View File

@ -193,10 +193,17 @@ SWITCH_STANDARD_APP(break_function)
SWITCH_STANDARD_APP(queue_dtmf_function)
{
switch_channel_t *channel;
char *p;
switch_dtmf_t dtmf = {0, SWITCH_DEFAULT_DTMF_DURATION};
if (!switch_strlen_zero(data)) {
channel = switch_core_session_get_channel(session);
assert(channel != NULL);
switch_channel_queue_dtmf(channel, data);
for (p = (char *)data; p && *p; p++) {
dtmf.digit = *p;
switch_channel_queue_dtmf(channel, &dtmf);
p++;
}
}
}
@ -1048,7 +1055,7 @@ static switch_status_t on_dtmf(switch_core_session_t *session, void *input, swit
switch (itype) {
case SWITCH_INPUT_TYPE_DTMF:
{
char *dtmf = (char *) input;
switch_dtmf_t *dtmf = (switch_dtmf_t *) input;
const char *terminators;
switch_channel_t *channel = switch_core_session_get_channel(session);
const char *p;
@ -1061,14 +1068,11 @@ static switch_status_t on_dtmf(switch_core_session_t *session, void *input, swit
if (!strcasecmp(terminators, "none")) {
terminators = NULL;
}
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Digits %s\n", dtmf);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Digit %c\n", dtmf->digit);
for (p = terminators; p && *p; p++) {
char *d;
for (d = dtmf; d && *d; d++) {
if (*p == *d) {
return SWITCH_STATUS_BREAK;
}
if (*p == dtmf->digit) {
return SWITCH_STATUS_BREAK;
}
}
}

View File

@ -48,8 +48,9 @@ static switch_status_t on_dtmf(switch_core_session_t *session, void *input, swit
switch (itype) {
case SWITCH_INPUT_TYPE_DTMF:
{
char *dtmf = (char *) input;
if (*dtmf == '*') {
switch_dtmf_t *dtmf = (switch_dtmf_t *) input;
if (dtmf->digit == '*') {
channel = switch_core_session_get_channel(session);
if (switch_channel_test_flag(channel, CF_ORIGINATOR)) {
channel = switch_core_session_get_channel(bleg);

View File

@ -91,11 +91,11 @@ static switch_status_t on_dtmf(switch_core_session_t *session, void *input, swit
{
switch (itype) {
case SWITCH_INPUT_TYPE_DTMF:{
char *dtmf = (char *) input;
switch_dtmf_t *dtmf = (switch_dtmf_t *) input;
struct dtmf_buffer *dtb;
dtb = (struct dtmf_buffer *) buf;
switch (*dtmf) {
switch (dtmf->digit) {
case '#':
switch_set_flag(dtb, SFLAG_MAIN);
return SWITCH_STATUS_BREAK;

View File

@ -615,9 +615,11 @@ static switch_status_t cancel_on_dtmf(switch_core_session_t *session, void *inpu
switch (itype) {
case SWITCH_INPUT_TYPE_DTMF:
{
char *dtmf = (char *) input;
switch_dtmf_t *dtmf = (switch_dtmf_t *) input;
if (buf && buflen) {
switch_copy_string(buf, dtmf, buflen);
char *bp = (char *) buf;
bp[0] = dtmf->digit;
bp[1] = '\0';
}
return SWITCH_STATUS_BREAK;
}
@ -643,13 +645,13 @@ static switch_status_t control_playback(switch_core_session_t *session, void *in
switch (itype) {
case SWITCH_INPUT_TYPE_DTMF:
{
char *dtmf = (char *) input;
switch_dtmf_t *dtmf = (switch_dtmf_t *) input;
cc_t *cc = (cc_t *) buf;
switch_file_handle_t *fh = cc->fh;
uint32_t pos = 0;
if (!cc->noexit && (*dtmf == *cc->profile->delete_file_key || *dtmf == *cc->profile->save_file_key || *dtmf == *cc->profile->terminator_key)) {
*cc->buf = *dtmf;
if (!cc->noexit && (dtmf->digit == *cc->profile->delete_file_key || dtmf->digit == *cc->profile->save_file_key || dtmf->digit == *cc->profile->terminator_key)) {
*cc->buf = dtmf->digit;
return SWITCH_STATUS_BREAK;
}
@ -657,7 +659,7 @@ static switch_status_t control_playback(switch_core_session_t *session, void *in
return SWITCH_STATUS_SUCCESS;
}
if (*dtmf == *cc->profile->pause_key) {
if (dtmf->digit == *cc->profile->pause_key) {
if (switch_test_flag(fh, SWITCH_FILE_PAUSE)) {
switch_clear_flag(fh, SWITCH_FILE_PAUSE);
} else {
@ -666,20 +668,20 @@ static switch_status_t control_playback(switch_core_session_t *session, void *in
return SWITCH_STATUS_SUCCESS;
}
if (*dtmf == *cc->profile->restart_key) {
if (dtmf->digit == *cc->profile->restart_key) {
unsigned int seekpos = 0;
fh->speed = 0;
switch_core_file_seek(fh, &seekpos, 0, SEEK_SET);
return SWITCH_STATUS_SUCCESS;
}
if (*dtmf == *cc->profile->ff_key) {
if (dtmf->digit == *cc->profile->ff_key) {
int samps = 24000;
switch_core_file_seek(fh, &pos, samps, SEEK_CUR);
return SWITCH_STATUS_SUCCESS;
}
if (*dtmf == *cc->profile->rew_key) {
if (dtmf->digit == *cc->profile->rew_key) {
int samps = 24000;
switch_core_file_seek(fh, &pos, fh->pos - samps, SEEK_SET);
return SWITCH_STATUS_SUCCESS;

View File

@ -522,14 +522,14 @@ static switch_status_t channel_waitfor_write(switch_core_session_t *session, int
}
static switch_status_t channel_send_dtmf(switch_core_session_t *session, char *dtmf)
static switch_status_t channel_send_dtmf(switch_core_session_t *session, const switch_dtmf_t *dtmf)
{
private_t *tech_pvt = NULL;
tech_pvt = switch_core_session_get_private(session);
assert(tech_pvt != NULL);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "DTMF ON CALL %s [%s]\n", tech_pvt->call_id, dtmf);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "DTMF ON CALL %s [%c]\n", tech_pvt->call_id, dtmf->digit);
return SWITCH_STATUS_SUCCESS;
}
@ -1205,15 +1205,21 @@ static switch_status_t engage_device(unsigned int sample_rate, int codec_ms)
static switch_status_t dtmf_call(char **argv, int argc, switch_stream_handle_t *stream)
{
char *dtmf = argv[0];
if (switch_strlen_zero(dtmf)) {
char *dtmf_str = argv[0];
switch_dtmf_t dtmf = {0, SWITCH_DEFAULT_DTMF_DURATION};
if (switch_strlen_zero(dtmf_str)) {
stream->write_function(stream, "No DTMF Supplied!\n");
} else {
switch_mutex_lock(globals.pvt_lock);
if (globals.call_list) {
switch_channel_t *channel = switch_core_session_get_channel(globals.call_list->session);
switch_channel_queue_dtmf(channel, dtmf);
char *p = dtmf_str;
while(p && *p) {
dtmf.digit = *p;
switch_channel_queue_dtmf(channel, &dtmf);
p++;
}
}
switch_mutex_unlock(globals.pvt_lock);
}

View File

@ -1344,7 +1344,7 @@ static switch_status_t channel_send_dtmf(switch_core_session_t *session, char *d
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "DTMF [%s]\n", dtmf);
return switch_rtp_queue_rfc2833(tech_pvt->rtp_session, dtmf, 100 * (tech_pvt->read_codec.implementation->samples_per_second / 1000));
return switch_rtp_queue_rfc2833(tech_pvt->rtp_session, dtmf);
}
@ -1416,9 +1416,9 @@ static switch_status_t channel_read_frame(switch_core_session_t *session, switch
}
#endif
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);
}
@ -2722,7 +2722,13 @@ static ldl_status handle_signalling(ldl_handle_t * handle, ldl_session_t * dlses
case LDL_SIGNAL_MSG:
if (msg) {
if (*msg == '+') {
switch_channel_queue_dtmf(channel, msg + 1);
char *p = msg + 1;
switch_dtmf_t dtmf = { 0, SWITCH_DEFAULT_DTMF_DURATION };
while (p && *p) {
dtmf.digit = *p;
switch_channel_queue_dtmf(channel, &dtmf);
p++;
}
switch_set_flag_locked(tech_pvt, TFLAG_DTMF);
if (switch_rtp_ready(tech_pvt->rtp_session)) {
switch_rtp_set_flag(tech_pvt->rtp_session, SWITCH_RTP_FLAG_BREAK);

View File

@ -620,17 +620,14 @@ static switch_status_t channel_waitfor_write(switch_core_session_t *session, int
}
static switch_status_t channel_send_dtmf(switch_core_session_t *session, char *dtmf)
static switch_status_t channel_send_dtmf(switch_core_session_t *session, const switch_dtmf_t *dtmf)
{
private_t *tech_pvt = NULL;
char *digit;
tech_pvt = switch_core_session_get_private(session);
switch_assert(tech_pvt != NULL);
if (tech_pvt->iax_session) {
for (digit = dtmf; *digit; digit++) {
iax_send_dtmf(tech_pvt->iax_session, *digit);
}
iax_send_dtmf(tech_pvt->iax_session, dtmf->digit);
}
return SWITCH_STATUS_SUCCESS;
@ -1206,11 +1203,12 @@ SWITCH_MODULE_RUNTIME_FUNCTION(mod_iax_runtime)
break;
case IAX_EVENT_DTMF:
if (channel) {
char str[2] = { (char) iaxevent->subclass };
switch_dtmf_t dtmf = { (char) iaxevent->subclass , SWITCH_DEFAULT_DTMF_DURATION };
if (globals.debug) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "%s DTMF %s\n", str, switch_channel_get_name(channel));
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "%c DTMF %s\n", dtmf.digit, switch_channel_get_name(channel));
}
switch_channel_queue_dtmf(channel, str);
switch_channel_queue_dtmf(channel, &dtmf);
}
break;

View File

@ -524,14 +524,14 @@ static switch_status_t channel_waitfor_write(switch_core_session_t *session, int
}
static switch_status_t channel_send_dtmf(switch_core_session_t *session, char *dtmf)
static switch_status_t channel_send_dtmf(switch_core_session_t *session, const switch_dtmf_t *dtmf)
{
private_t *tech_pvt = NULL;
tech_pvt = switch_core_session_get_private(session);
switch_assert(tech_pvt != NULL);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "DTMF ON CALL %s [%s]\n", tech_pvt->call_id, dtmf);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "DTMF ON CALL %s [%c]\n", tech_pvt->call_id, dtmf->digit);
return SWITCH_STATUS_SUCCESS;
}
@ -1314,18 +1314,23 @@ static switch_status_t engage_ring_device(int sample_rate, int channels)
static switch_status_t dtmf_call(char **argv, int argc, switch_stream_handle_t *stream)
{
char *dtmf = argv[0];
if (switch_strlen_zero(dtmf)) {
char *dtmf_str = argv[0];
switch_dtmf_t dtmf = {0, SWITCH_DEFAULT_DTMF_DURATION};
if (switch_strlen_zero(dtmf_str)) {
stream->write_function(stream, "No DTMF Supplied!\n");
} else {
switch_mutex_lock(globals.pvt_lock);
if (globals.call_list) {
switch_channel_t *channel = switch_core_session_get_channel(globals.call_list->session);
switch_channel_queue_dtmf(channel, dtmf);
char *p = dtmf_str;
while(p && *p) {
dtmf.digit = *p;
switch_channel_queue_dtmf(channel, &dtmf);
p++;
}
}
switch_mutex_unlock(globals.pvt_lock);
}

View File

@ -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)

View File

@ -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);

View File

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

View File

@ -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;

View File

@ -810,7 +810,13 @@ static switch_status_t wanpipe_read_frame(switch_core_session_t *session, switch
teletone_dtmf_get(&tech_pvt->dtmf_detect, digit_str, sizeof(digit_str));
if(digit_str[0]) {
switch_channel_queue_dtmf(channel, digit_str);
char *p = digit_str;
switch_dtmf_t dtmf = {0, globals.dtmf_on};
while(p && *p) {
dtmf.digit = *p;
switch_channel_queue_dtmf(channel, &dtmf);
p++;
}
if (globals.debug) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "DTMF DETECTED: [%s]\n", digit_str);
}
@ -876,13 +882,12 @@ static switch_status_t wanpipe_write_frame(switch_core_session_t *session, switc
return SWITCH_STATUS_SUCCESS;
}
static switch_status_t wanpipe_send_dtmf(switch_core_session_t *session, char *digits)
static switch_status_t wanpipe_send_dtmf(switch_core_session_t *session, const switch_dtmf_t *dtmf)
{
private_object_t *tech_pvt;
switch_channel_t *channel = NULL;
switch_status_t status = SWITCH_STATUS_SUCCESS;
int wrote = 0;
char *cur = NULL;
channel = switch_core_session_get_channel(session);
assert(channel != NULL);
@ -903,12 +908,13 @@ static switch_status_t wanpipe_send_dtmf(switch_core_session_t *session, char *d
switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "SUCCESS!\n");
}
}
for (cur = digits; *cur; cur++) {
if ((wrote = teletone_mux_tones(&tech_pvt->tone_session, &tech_pvt->tone_session.TONES[(int)*cur]))) {
switch_buffer_write(tech_pvt->dtmf_buffer, tech_pvt->tone_session.buffer, wrote * 2);
}
tech_pvt->tone_session.duration = dtmf.duration * (tech_pvt->tone_session.rate / 1000);
if ((wrote = teletone_mux_tones(&tech_pvt->tone_session, &tech_pvt->tone_session.TONES[(int)dtmf->digit]))) {
switch_buffer_write(tech_pvt->dtmf_buffer, tech_pvt->tone_session.buffer, wrote * 2);
}
tech_pvt->skip_read_frames = 200;
return status;

View File

@ -1010,10 +1010,14 @@ static switch_status_t js_common_callback(switch_core_session_t *session, void *
return SWITCH_STATUS_FALSE;
}
break;
case SWITCH_INPUT_TYPE_DTMF:
dtmf = (char *) input;
argv[argc++] = STRING_TO_JSVAL(JS_NewStringCopyZ(cb_state->cx, "dtmf"));
argv[argc++] = STRING_TO_JSVAL(JS_NewStringCopyZ(cb_state->cx, dtmf));
case SWITCH_INPUT_TYPE_DTMF:
{
switch_dtmf_t *_dtmf = (switch_dtmf_t *) input;
dtmf[0] = _dtmf->digit;
dtmf[1] = '\0';
argv[argc++] = STRING_TO_JSVAL(JS_NewStringCopyZ(cb_state->cx, "dtmf"));
argv[argc++] = STRING_TO_JSVAL(JS_NewStringCopyZ(cb_state->cx, dtmf));
}
break;
}
@ -1208,8 +1212,6 @@ static switch_status_t js_collect_input_callback(switch_core_session_t *session,
static JSBool session_flush_digits(JSContext * cx, JSObject * obj, uintN argc, jsval * argv, jsval * rval)
{
struct js_session *jss = JS_GetPrivate(cx, obj);
char buf[256];
switch_size_t has;
switch_channel_t *channel;
METHOD_SANITY_CHECK();
@ -1217,9 +1219,7 @@ static JSBool session_flush_digits(JSContext * cx, JSObject * obj, uintN argc, j
channel = switch_core_session_get_channel(jss->session);
switch_assert(channel != NULL);
while ((has = switch_channel_has_dtmf(channel))) {
switch_channel_dequeue_dtmf(channel, buf, sizeof(buf));
}
switch_channel_flush_dtmf(channel);
*rval = BOOLEAN_TO_JSVAL(JS_TRUE);
return JS_TRUE;

View File

@ -257,7 +257,7 @@ static JSBool teletone_generate(JSContext * cx, JSObject * obj, uintN argc, jsva
uintN aargc = 0;
jsval aargv[4];
switch_channel_dequeue_dtmf(channel, dtmf, sizeof(dtmf));
switch_channel_dequeue_dtmf_string(channel, dtmf, sizeof(dtmf));
aargv[aargc++] = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, dtmf));
JS_CallFunction(cx, obj, tto->function, aargc, aargv, &tto->ret);
ret = JS_GetStringBytes(JS_ValueToString(cx, tto->ret));

View File

@ -104,7 +104,7 @@ static struct switch_cause_table CAUSE_CHART[] = {
struct switch_channel {
char *name;
switch_buffer_t *dtmf_buffer;
switch_queue_t *dtmf_queue;
switch_mutex_t *dtmf_mutex;
switch_mutex_t *flag_mutex;
switch_mutex_t *profile_mutex;
@ -186,7 +186,7 @@ SWITCH_DECLARE(switch_status_t) switch_channel_alloc(switch_channel_t **channel,
switch_event_create(&(*channel)->variables, SWITCH_EVENT_MESSAGE);
switch_core_hash_init(&(*channel)->private_hash, pool);
switch_buffer_create_dynamic(&(*channel)->dtmf_buffer, 128, 128, 0);
switch_queue_create(&(*channel)->dtmf_queue, 128, pool);
switch_mutex_init(&(*channel)->dtmf_mutex, SWITCH_MUTEX_NESTED, pool);
switch_mutex_init(&(*channel)->flag_mutex, SWITCH_MUTEX_NESTED, pool);
@ -203,18 +203,16 @@ SWITCH_DECLARE(switch_size_t) switch_channel_has_dtmf(switch_channel_t *channel)
switch_assert(channel != NULL);
switch_mutex_lock(channel->dtmf_mutex);
has = switch_buffer_inuse(channel->dtmf_buffer);
has = switch_queue_size(channel->dtmf_queue);
switch_mutex_unlock(channel->dtmf_mutex);
return has;
}
SWITCH_DECLARE(switch_status_t) switch_channel_queue_dtmf(switch_channel_t *channel, const char *dtmf)
SWITCH_DECLARE(switch_status_t) switch_channel_queue_dtmf(switch_channel_t *channel, const switch_dtmf_t *dtmf)
{
switch_status_t status;
register switch_size_t len, inuse;
switch_size_t wr = 0;
const char *p;
void *pop;
switch_assert(channel != NULL);
@ -224,23 +222,24 @@ SWITCH_DECLARE(switch_status_t) switch_channel_queue_dtmf(switch_channel_t *chan
goto done;
}
inuse = switch_buffer_inuse(channel->dtmf_buffer);
len = strlen(dtmf);
if (is_dtmf(dtmf->digit)) {
switch_dtmf_t *dt;
int x = 0;
if (len + inuse > switch_buffer_len(channel->dtmf_buffer)) {
switch_buffer_toss(channel->dtmf_buffer, strlen(dtmf));
}
p = dtmf;
while (wr < len && p) {
if (is_dtmf(*p)) {
wr++;
} else {
break;
switch_zmalloc(dt, sizeof(*dt));
*dt = *dtmf;
while (switch_queue_trypush(channel->dtmf_queue, dt) != SWITCH_STATUS_SUCCESS) {
switch_queue_trypop(channel->dtmf_queue, &pop);
if (++x > 100) {
status = SWITCH_STATUS_FALSE;
free(dt);
goto done;
}
}
p++;
}
status = switch_buffer_write(channel->dtmf_buffer, dtmf, wr) ? SWITCH_STATUS_SUCCESS : SWITCH_STATUS_MEMERR;
status = SWITCH_STATUS_SUCCESS;
done:
@ -250,33 +249,64 @@ SWITCH_DECLARE(switch_status_t) switch_channel_queue_dtmf(switch_channel_t *chan
}
SWITCH_DECLARE(switch_size_t) switch_channel_dequeue_dtmf(switch_channel_t *channel, char *dtmf, switch_size_t len)
SWITCH_DECLARE(switch_status_t) switch_channel_dequeue_dtmf(switch_channel_t *channel, switch_dtmf_t *dtmf)
{
switch_size_t bytes;
switch_event_t *event;
void *pop;
switch_dtmf_t *dt;
switch_status_t status = SWITCH_STATUS_FALSE;
switch_assert(channel != NULL);
switch_mutex_lock(channel->dtmf_mutex);
if ((bytes = switch_buffer_read(channel->dtmf_buffer, dtmf, len)) > 0) {
*(dtmf + bytes) = '\0';
if (switch_queue_trypop(channel->dtmf_queue, &pop) == SWITCH_STATUS_SUCCESS) {
dt = (switch_dtmf_t *) pop;
*dtmf = *dt;
free(dt);
status = SWITCH_STATUS_SUCCESS;
}
switch_mutex_unlock(channel->dtmf_mutex);
if (bytes && switch_event_create(&event, SWITCH_EVENT_DTMF) == SWITCH_STATUS_SUCCESS) {
if (status == SWITCH_STATUS_SUCCESS && switch_event_create(&event, SWITCH_EVENT_DTMF) == SWITCH_STATUS_SUCCESS) {
switch_channel_event_set_data(channel, event);
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "DTMF-String", "%s", dtmf);
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "DTMF-Digit", "%c", dtmf->digit);
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "DTMF-Duration", "%u", dtmf->duration);
switch_event_fire(&event);
}
return bytes;
return status;
}
SWITCH_DECLARE(switch_size_t) switch_channel_dequeue_dtmf_string(switch_channel_t *channel, char *dtmf_str, switch_size_t len)
{
switch_size_t x = 0;
switch_dtmf_t dtmf = {0};
memset(dtmf_str, 0, len);
while(x < len - 1 && switch_channel_dequeue_dtmf(channel, &dtmf) == SWITCH_STATUS_SUCCESS) {
dtmf_str[x++] = dtmf.digit;
}
return x;
}
SWITCH_DECLARE(void) switch_channel_flush_dtmf(switch_channel_t *channel)
{
void *pop;
switch_mutex_lock(channel->dtmf_mutex);
while(switch_queue_trypop(channel->dtmf_queue, &pop) == SWITCH_STATUS_SUCCESS) {
free(pop);
}
switch_mutex_unlock(channel->dtmf_mutex);
}
SWITCH_DECLARE(void) switch_channel_uninit(switch_channel_t *channel)
{
switch_buffer_destroy(&channel->dtmf_buffer);
switch_core_hash_destroy(&channel->private_hash);
switch_event_destroy(&channel->variables);
}

View File

@ -145,9 +145,9 @@ SWITCH_DECLARE(const switch_state_handler_table_t *) switch_core_get_state_handl
SWITCH_DECLARE(char *) switch_core_get_variable(const char *varname)
{
char *val;
switch_mutex_lock(runtime.throttle_mutex);
switch_mutex_lock(runtime.global_mutex);
val = (char *) switch_core_hash_find(runtime.global_vars, varname);
switch_mutex_unlock(runtime.throttle_mutex);
switch_mutex_unlock(runtime.global_mutex);
return val;
}
@ -156,7 +156,7 @@ SWITCH_DECLARE(void) switch_core_set_variable(const char *varname, const char *v
char *val;
if (varname) {
switch_mutex_lock(runtime.throttle_mutex);
switch_mutex_lock(runtime.global_mutex);
val = (char *) switch_core_hash_find(runtime.global_vars, varname);
if (val) {
free(val);
@ -166,7 +166,7 @@ SWITCH_DECLARE(void) switch_core_set_variable(const char *varname, const char *v
} else {
switch_core_hash_delete(runtime.global_vars, varname);
}
switch_mutex_unlock(runtime.throttle_mutex);
switch_mutex_unlock(runtime.global_mutex);
}
}
@ -671,6 +671,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_init(switch_core_flag_t flags, switc
}
switch_assert(runtime.memory_pool != NULL);
switch_mutex_init(&runtime.throttle_mutex, SWITCH_MUTEX_NESTED, runtime.memory_pool);
switch_mutex_init(&runtime.global_mutex, SWITCH_MUTEX_NESTED, runtime.memory_pool);
switch_core_set_globals();
switch_core_session_init(runtime.memory_pool);
switch_core_hash_init(&runtime.global_vars, runtime.memory_pool);

View File

@ -881,7 +881,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_waitfor_write(switch_core_se
}
SWITCH_DECLARE(switch_status_t) switch_core_session_recv_dtmf(switch_core_session_t *session, const char *dtmf)
SWITCH_DECLARE(switch_status_t) switch_core_session_recv_dtmf(switch_core_session_t *session, const switch_dtmf_t *dtmf)
{
switch_io_event_hook_recv_dtmf_t *ptr;
switch_status_t status;
@ -894,7 +894,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_recv_dtmf(switch_core_sessio
return SWITCH_STATUS_SUCCESS;
}
SWITCH_DECLARE(switch_status_t) switch_core_session_send_dtmf(switch_core_session_t *session, const char *dtmf)
SWITCH_DECLARE(switch_status_t) switch_core_session_send_dtmf(switch_core_session_t *session, const switch_dtmf_t *dtmf)
{
switch_io_event_hook_send_dtmf_t *ptr;
switch_status_t status = SWITCH_STATUS_FALSE;
@ -907,28 +907,13 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_send_dtmf(switch_core_sessio
}
if (session->endpoint_interface->io_routines->send_dtmf) {
if (strchr(dtmf, 'w') || strchr(dtmf, 'W')) {
const char *d;
for (d = dtmf; d && *d; d++) {
char digit[2] = { 0 };
if (*d == 'w') {
switch_yield(500000);
continue;
} else if (*d == 'W') {
switch_yield(1000000);
continue;
}
digit[0] = *d;
if ((status = session->endpoint_interface->io_routines->send_dtmf(session, digit)) != SWITCH_STATUS_SUCCESS) {
return status;
}
}
if (dtmf->digit == 'w') {
switch_yield(500000);
} else if (dtmf->digit == 'W') {
switch_yield(1000000);
} else {
status = session->endpoint_interface->io_routines->send_dtmf(session, (char *)dtmf);
status = session->endpoint_interface->io_routines->send_dtmf(session, dtmf);
}
}
return status;

View File

@ -565,7 +565,6 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_dequeue_private_event(switch
SWITCH_DECLARE(void) switch_core_session_reset(switch_core_session_t *session)
{
switch_channel_t *channel;
char buf[256];
switch_size_t has;
/* clear resamplers*/
@ -583,7 +582,7 @@ SWITCH_DECLARE(void) switch_core_session_reset(switch_core_session_t *session)
channel = switch_core_session_get_channel(session);
while ((has = switch_channel_has_dtmf(channel))) {
switch_channel_dequeue_dtmf(channel, buf, sizeof(buf));
switch_channel_flush_dtmf(channel);
}
switch_ivr_deactivate_unicast(session);

View File

@ -398,9 +398,8 @@ int CoreSession::flushDigits()
channel = switch_core_session_get_channel(session);
assert(channel != NULL);
while ((has = switch_channel_has_dtmf(channel))) {
switch_channel_dequeue_dtmf(channel, buf, sizeof(buf));
}
switch_channel_flush_dtmf(channel);
return SWITCH_STATUS_SUCCESS;
}

View File

@ -495,10 +495,10 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_park(switch_core_session_t *session,
}
if (switch_channel_has_dtmf(channel)) {
char dtmf[128];
switch_channel_dequeue_dtmf(channel, dtmf, sizeof(dtmf));
switch_dtmf_t dtmf = {0};
switch_channel_dequeue_dtmf(channel, &dtmf);
if (args && args->input_callback) {
if ((status = args->input_callback(session, dtmf, SWITCH_INPUT_TYPE_DTMF, args->buf, args->buflen)) != SWITCH_STATUS_SUCCESS) {
if ((status = args->input_callback(session, (void *) &dtmf, SWITCH_INPUT_TYPE_DTMF, args->buf, args->buflen)) != SWITCH_STATUS_SUCCESS) {
break;
}
}
@ -552,7 +552,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_collect_digits_callback(switch_core_s
while (switch_channel_ready(channel)) {
switch_frame_t *read_frame;
switch_event_t *event;
char dtmf[128];
switch_dtmf_t dtmf = {0};
if (timeout) {
elapsed = (uint32_t) ((switch_time_now() - started) / 1000);
@ -566,8 +566,8 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_collect_digits_callback(switch_core_s
}
if (switch_channel_has_dtmf(channel)) {
switch_channel_dequeue_dtmf(channel, dtmf, sizeof(dtmf));
status = args->input_callback(session, dtmf, SWITCH_INPUT_TYPE_DTMF, args->buf, args->buflen);
switch_channel_dequeue_dtmf(channel, &dtmf);
status = args->input_callback(session, (void *)&dtmf, SWITCH_INPUT_TYPE_DTMF, args->buf, args->buflen);
}
if (switch_core_session_dequeue_event(session, &event) == SWITCH_STATUS_SUCCESS) {
@ -639,17 +639,20 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_collect_digits_count(switch_core_sess
}
if (switch_channel_has_dtmf(channel)) {
char dtmf[128];
switch_dtmf_t dtmf = {0};
int y;
for (y = 0; y < maxdigits; y++) {
if (switch_channel_dequeue_dtmf(channel, &dtmf) != SWITCH_STATUS_SUCCESS) {
break;
}
switch_channel_dequeue_dtmf(channel, dtmf, maxdigits);
for (i = 0; i < strlen(dtmf); i++) {
if (!switch_strlen_zero(terminators) && strchr(terminators, dtmf[i]) && terminator != NULL) {
*terminator = dtmf[i];
if (!switch_strlen_zero(terminators) && strchr(terminators, dtmf.digit) && terminator != NULL) {
*terminator = dtmf.digit;
return SWITCH_STATUS_SUCCESS;
}
buf[x++] = dtmf[i];
buf[x++] = dtmf.digit;
buf[x] = '\0';
if (x >= buflen || x >= maxdigits) {
return SWITCH_STATUS_SUCCESS;

View File

@ -481,9 +481,9 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_eavesdrop_session(switch_core_session
}
if ((flags & ED_DTMF) && switch_channel_has_dtmf(channel)) {
char dtmf[128] = "";
switch_channel_dequeue_dtmf(channel, dtmf, sizeof(dtmf));
fcommand = dtmf;
switch_dtmf_t dtmf = {0};
switch_channel_dequeue_dtmf(channel, &dtmf);
*fcommand = dtmf.digit;
}
if (fcommand) {
@ -717,7 +717,14 @@ static switch_bool_t inband_dtmf_callback(switch_media_bug_t *bug, void *user_da
teletone_dtmf_detect(&pvt->dtmf_detect, frame.data, frame.samples);
teletone_dtmf_get(&pvt->dtmf_detect, digit_str, sizeof(digit_str));
if (digit_str[0]) {
switch_channel_queue_dtmf(channel, digit_str);
char *p = digit_str;
while(p && *p) {
switch_dtmf_t dtmf;
dtmf.digit = *p;
dtmf.duration = SWITCH_DEFAULT_DTMF_DURATION;
switch_channel_queue_dtmf(channel, &dtmf);
p++;
}
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "DTMF DETECTED: [%s]\n", digit_str);
}
}
@ -804,7 +811,7 @@ static int teletone_dtmf_generate_handler(teletone_generation_session_t * ts, te
}
static switch_status_t generate_on_dtmf(switch_core_session_t *session, const char *dtmf)
static switch_status_t generate_on_dtmf(switch_core_session_t *session, const switch_dtmf_t *dtmf)
{
switch_media_bug_t *bug;
@ -815,7 +822,9 @@ static switch_status_t generate_on_dtmf(switch_core_session_t *session, const ch
if (pvt) {
switch_mutex_lock(pvt->mutex);
teletone_run(&pvt->ts, (char *)dtmf);
char buf[2] = "";
buf[0] = dtmf->digit;
teletone_run(&pvt->ts, buf);
switch_mutex_unlock(pvt->mutex);
return SWITCH_STATUS_FALSE;
}

View File

@ -116,17 +116,20 @@ static void *audio_bridge_thread(switch_thread_t * thread, void *obj)
}
/* if 1 channel has DTMF pass it to the other */
if (switch_channel_has_dtmf(chan_a)) {
char dtmf[128];
switch_channel_dequeue_dtmf(chan_a, dtmf, sizeof(dtmf));
if (input_callback) {
if (input_callback(session_a, dtmf, SWITCH_INPUT_TYPE_DTMF, user_data, 0) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s ended call via DTMF\n", switch_channel_get_name(chan_a));
switch_core_session_kill_channel(session_b, SWITCH_SIG_BREAK);
break;
while (switch_channel_has_dtmf(chan_a)) {
switch_dtmf_t dtmf = { 0, 0 };
if (switch_channel_dequeue_dtmf(chan_a, &dtmf) == SWITCH_STATUS_SUCCESS) {
if (input_callback) {
if (input_callback(session_a, (void *)&dtmf, SWITCH_INPUT_TYPE_DTMF, user_data, 0) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s ended call via DTMF\n", switch_channel_get_name(chan_a));
switch_core_session_kill_channel(session_b, SWITCH_SIG_BREAK);
break;
}
}
switch_core_session_send_dtmf(session_b, &dtmf);
}
switch_core_session_send_dtmf(session_b, dtmf);
}
if (switch_core_session_dequeue_event(session_a, &event) == SWITCH_STATUS_SUCCESS) {

View File

@ -338,7 +338,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_record_file(switch_core_session_t *se
switch_file_handle_t *fh, char *file, switch_input_args_t *args, uint32_t limit)
{
switch_channel_t *channel;
char dtmf[128];
switch_dtmf_t dtmf = {0};
switch_file_handle_t lfh = { 0 };
switch_frame_t *read_frame;
switch_codec_t codec, *read_codec;
@ -476,11 +476,11 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_record_file(switch_core_session_t *se
status = SWITCH_STATUS_BREAK;
break;
}
switch_channel_dequeue_dtmf(channel, dtmf, sizeof(dtmf));
switch_channel_dequeue_dtmf(channel, &dtmf);
if (args->input_callback) {
status = args->input_callback(session, dtmf, SWITCH_INPUT_TYPE_DTMF, args->buf, args->buflen);
status = args->input_callback(session, (void *)&dtmf, SWITCH_INPUT_TYPE_DTMF, args->buf, args->buflen);
} else {
switch_copy_string((char *) args->buf, dtmf, args->buflen);
switch_copy_string((char *) args->buf, (void *)&dtmf, args->buflen);
status = SWITCH_STATUS_BREAK;
}
}
@ -664,7 +664,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_play_file(switch_core_session_t *sess
{
switch_channel_t *channel;
int16_t *abuf;
char dtmf[128];
switch_dtmf_t dtmf = {0};
uint32_t interval = 0, samples = 0, framelen, sample_start = 0;
uint32_t ilen = 0;
switch_size_t olen = 0, llen = 0;
@ -900,11 +900,11 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_play_file(switch_core_session_t *sess
done = 1;
break;
}
switch_channel_dequeue_dtmf(channel, dtmf, sizeof(dtmf));
switch_channel_dequeue_dtmf(channel, &dtmf);
if (args->input_callback) {
status = args->input_callback(session, dtmf, SWITCH_INPUT_TYPE_DTMF, args->buf, args->buflen);
status = args->input_callback(session, (void *)&dtmf, SWITCH_INPUT_TYPE_DTMF, args->buf, args->buflen);
} else {
switch_copy_string((char *) args->buf, dtmf, args->buflen);
switch_copy_string((char *) args->buf, (void *)&dtmf, args->buflen);
status = SWITCH_STATUS_BREAK;
}
}
@ -1227,7 +1227,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_speak_text_handle(switch_core_session
{
switch_channel_t *channel;
short abuf[960];
char dtmf[128];
switch_dtmf_t dtmf = {0};
uint32_t len = 0;
switch_size_t ilen = 0;
switch_frame_t write_frame = { 0 };
@ -1357,11 +1357,11 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_speak_text_handle(switch_core_session
if (args->buf && !strcasecmp(args->buf, "_break_")) {
status = SWITCH_STATUS_BREAK;
} else {
switch_channel_dequeue_dtmf(channel, dtmf, sizeof(dtmf));
switch_channel_dequeue_dtmf(channel, &dtmf);
if (args->input_callback) {
status = args->input_callback(session, dtmf, SWITCH_INPUT_TYPE_DTMF, args->buf, args->buflen);
status = args->input_callback(session, (void *) &dtmf, SWITCH_INPUT_TYPE_DTMF, args->buf, args->buflen);
} else {
switch_copy_string((char *) args->buf, dtmf, args->buflen);
switch_copy_string((char *) args->buf, (void *) &dtmf, args->buflen);
status = SWITCH_STATUS_BREAK;
}
}

View File

@ -75,11 +75,6 @@ typedef struct {
} rtp_msg_t;
struct rfc2833_digit {
char digit;
int duration;
};
struct switch_rtp_vad_data {
switch_core_session_t *session;
switch_codec_t vad_codec;
@ -115,7 +110,7 @@ struct switch_rtp_rfc2833_data {
char last_digit;
unsigned int dc;
time_t last_digit_time;
switch_buffer_t *dtmf_buffer;
switch_queue_t *dtmf_inqueue;
switch_mutex_t *dtmf_mutex;
};
@ -497,7 +492,9 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_create(switch_rtp_t **new_rtp_session
switch_mutex_init(&rtp_session->flag_mutex, SWITCH_MUTEX_NESTED, pool);
switch_mutex_init(&rtp_session->dtmf_data.dtmf_mutex, SWITCH_MUTEX_NESTED, pool);
switch_buffer_create_dynamic(&rtp_session->dtmf_data.dtmf_buffer, 128, 128, 0);
switch_queue_create(&rtp_session->dtmf_data.dtmf_queue, 100, rtp_session->pool);
switch_queue_create(&rtp_session->dtmf_data.dtmf_inqueue, 100, rtp_session->pool);
switch_rtp_set_flag(rtp_session, flags);
/* for from address on recvfrom calls */
@ -696,11 +693,20 @@ SWITCH_DECLARE(uint8_t) switch_rtp_ready(switch_rtp_t *rtp_session)
SWITCH_DECLARE(void) switch_rtp_destroy(switch_rtp_t **rtp_session)
{
void *pop;
if (!switch_rtp_ready(*rtp_session)) {
return;
}
while(switch_queue_trypop((*rtp_session)->dtmf_data.dtmf_inqueue, &pop) == SWITCH_STATUS_SUCCESS) {
free(pop);
}
while(switch_queue_trypop((*rtp_session)->dtmf_data.dtmf_queue, &pop) == SWITCH_STATUS_SUCCESS) {
free(pop);
}
(*rtp_session)->ready = 0;
switch_mutex_lock((*rtp_session)->flag_mutex);
@ -709,10 +715,6 @@ SWITCH_DECLARE(void) switch_rtp_destroy(switch_rtp_t **rtp_session)
stfu_n_destroy(&(*rtp_session)->jb);
}
if ((*rtp_session)->dtmf_data.dtmf_buffer) {
switch_buffer_destroy(&(*rtp_session)->dtmf_data.dtmf_buffer);
}
switch_rtp_kill_socket(*rtp_session);
switch_socket_close((*rtp_session)->sock);
(*rtp_session)->sock = NULL;
@ -834,7 +836,7 @@ static void do_2833(switch_rtp_t *rtp_session)
if (switch_queue_trypop(rtp_session->dtmf_data.dtmf_queue, &pop) == SWITCH_STATUS_SUCCESS) {
int x;
struct rfc2833_digit *rdigit = pop;
switch_dtmf_t *rdigit = pop;
memset(rtp_session->dtmf_data.out_digit_packet, 0, 4);
rtp_session->dtmf_data.out_digit_sofar = 0;
@ -1078,9 +1080,9 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_
rtp_session->dtmf_data.in_digit_seq = in_digit_seq;
if (duration && end) {
if (key != rtp_session->dtmf_data.last_digit) {
char digit_str[] = { key, 0 };
switch_dtmf_t dtmf = { key, duration };
time(&rtp_session->dtmf_data.last_digit_time);
switch_rtp_queue_dtmf(rtp_session, digit_str);
switch_rtp_queue_rfc2833_in(rtp_session, &dtmf);
switch_set_flag_locked(rtp_session, SWITCH_RTP_FLAG_BREAK);
}
if (++rtp_session->dtmf_data.dc >= 3) {
@ -1126,61 +1128,29 @@ SWITCH_DECLARE(switch_size_t) switch_rtp_has_dtmf(switch_rtp_t *rtp_session)
if (switch_rtp_ready(rtp_session)) {
switch_mutex_lock(rtp_session->dtmf_data.dtmf_mutex);
has = switch_buffer_inuse(rtp_session->dtmf_data.dtmf_buffer);
has = switch_queue_size(rtp_session->dtmf_data.dtmf_inqueue);
switch_mutex_unlock(rtp_session->dtmf_data.dtmf_mutex);
}
return has;
}
SWITCH_DECLARE(switch_status_t) switch_rtp_queue_dtmf(switch_rtp_t *rtp_session, char *dtmf)
{
switch_status_t status;
register switch_size_t len, inuse;
switch_size_t wr = 0;
char *p;
if (!switch_rtp_ready(rtp_session)) {
return SWITCH_STATUS_FALSE;
}
switch_mutex_lock(rtp_session->dtmf_data.dtmf_mutex);
inuse = switch_buffer_inuse(rtp_session->dtmf_data.dtmf_buffer);
len = strlen(dtmf);
if (len + inuse > switch_buffer_len(rtp_session->dtmf_data.dtmf_buffer)) {
switch_buffer_toss(rtp_session->dtmf_data.dtmf_buffer, strlen(dtmf));
}
p = dtmf;
while (wr < len && p) {
if (is_dtmf(*p)) {
wr++;
} else {
break;
}
p++;
}
status = switch_buffer_write(rtp_session->dtmf_data.dtmf_buffer, dtmf, wr) ? SWITCH_STATUS_SUCCESS : SWITCH_STATUS_MEMERR;
switch_mutex_unlock(rtp_session->dtmf_data.dtmf_mutex);
return status;
}
SWITCH_DECLARE(switch_size_t) switch_rtp_dequeue_dtmf(switch_rtp_t *rtp_session, char *dtmf, switch_size_t len)
SWITCH_DECLARE(switch_size_t) switch_rtp_dequeue_dtmf(switch_rtp_t *rtp_session, switch_dtmf_t *dtmf)
{
switch_size_t bytes = 0;
switch_dtmf_t *_dtmf = NULL;
void *pop;
if (!switch_rtp_ready(rtp_session)) {
return bytes;
}
switch_mutex_lock(rtp_session->dtmf_data.dtmf_mutex);
if ((bytes = switch_buffer_read(rtp_session->dtmf_data.dtmf_buffer, dtmf, len)) > 0) {
*(dtmf + bytes) = '\0';
if (switch_queue_trypop(rtp_session->dtmf_data.dtmf_inqueue, &pop) == SWITCH_STATUS_SUCCESS) {
_dtmf = (switch_dtmf_t *) pop;
*dtmf = *_dtmf;
bytes++;
}
switch_mutex_unlock(rtp_session->dtmf_data.dtmf_mutex);
@ -1188,30 +1158,42 @@ SWITCH_DECLARE(switch_size_t) switch_rtp_dequeue_dtmf(switch_rtp_t *rtp_session,
}
SWITCH_DECLARE(switch_status_t) switch_rtp_queue_rfc2833(switch_rtp_t *rtp_session, char *digits, uint32_t duration)
SWITCH_DECLARE(switch_status_t) switch_rtp_queue_rfc2833(switch_rtp_t *rtp_session, const switch_dtmf_t *dtmf)
{
char *c;
switch_dtmf_t *rdigit;
if (!switch_rtp_ready(rtp_session)) {
return SWITCH_STATUS_FALSE;
}
if (!rtp_session->dtmf_data.dtmf_queue) {
switch_queue_create(&rtp_session->dtmf_data.dtmf_queue, 100, rtp_session->pool);
if ((rdigit = malloc(sizeof(*rdigit))) != 0) {
*rdigit = *dtmf;
switch_queue_push(rtp_session->dtmf_data.dtmf_queue, rdigit);
} else {
abort();
}
return SWITCH_STATUS_SUCCESS;
}
SWITCH_DECLARE(switch_status_t) switch_rtp_queue_rfc2833_in(switch_rtp_t *rtp_session, const switch_dtmf_t *dtmf)
{
switch_dtmf_t *rdigit;
if (!switch_rtp_ready(rtp_session)) {
return SWITCH_STATUS_FALSE;
}
for (c = digits; *c; c++) {
struct rfc2833_digit *rdigit;
if ((rdigit = malloc(sizeof(*rdigit))) != 0) {
memset(rdigit, 0, sizeof(*rdigit));
rdigit->digit = *c;
rdigit->duration = duration;
switch_queue_push(rtp_session->dtmf_data.dtmf_queue, rdigit);
} else {
return SWITCH_STATUS_MEMERR;
}
if ((rdigit = malloc(sizeof(*rdigit))) != 0) {
*rdigit = *dtmf;
switch_queue_push(rtp_session->dtmf_data.dtmf_inqueue, rdigit);
} else {
abort();
}
return SWITCH_STATUS_SUCCESS;
}