freetdm: add asynchronous signal notification

This commit is contained in:
Moises Silva 2010-08-31 18:13:56 -04:00
parent f7669283a6
commit 3a35139a32
4 changed files with 70 additions and 24 deletions

View File

@ -51,6 +51,7 @@
#include "ftdm_cpu_monitor.h"
#define SPAN_PENDING_CHANS_QUEUE_SIZE 1000
#define SPAN_PENDING_SIGNALS_QUEUE_SIZE 1000
#define FTDM_READ_TRACE_INDEX 0
#define FTDM_WRITE_TRACE_INDEX 1
@ -463,6 +464,9 @@ static ftdm_status_t ftdm_span_destroy(ftdm_span_t *span)
if (span->pendingchans) {
ftdm_queue_destroy(&span->pendingchans);
}
if (span->pendingsignals) {
ftdm_queue_destroy(&span->pendingsignals);
}
ftdm_mutex_unlock(span->mutex);
ftdm_mutex_destroy(&span->mutex);
ftdm_safe_free(span->signal_data);
@ -4097,6 +4101,9 @@ static ftdm_status_t post_configure_span_channels(ftdm_span_t *span)
if (ftdm_test_flag(span, FTDM_SPAN_USE_CHAN_QUEUE)) {
status = ftdm_queue_create(&span->pendingchans, SPAN_PENDING_CHANS_QUEUE_SIZE);
}
if (status == FTDM_SUCCESS && ftdm_test_flag(span, FTDM_SPAN_USE_SIGNALS_QUEUE)) {
status = ftdm_queue_create(&span->pendingsignals, SPAN_PENDING_SIGNALS_QUEUE_SIZE);
}
return status;
}
@ -4362,10 +4369,39 @@ FT_DECLARE(ftdm_status_t) ftdm_group_create(ftdm_group_t **group, const char *na
return status;
}
static ftdm_status_t ftdm_span_trigger_signal(const ftdm_span_t *span, ftdm_sigmsg_t *sigmsg)
{
return span->signal_cb(sigmsg);
}
static ftdm_status_t ftdm_span_queue_signal(const ftdm_span_t *span, ftdm_sigmsg_t *sigmsg)
{
ftdm_sigmsg_t *new_sigmsg = NULL;
ftdm_assert_return((sigmsg->raw_data == NULL), FTDM_FAIL, "No raw data should be used with asynchronous notification\n");
new_sigmsg = ftdm_calloc(1, sizeof(*sigmsg));
if (!new_sigmsg) {
return FTDM_FAIL;
}
memcpy(new_sigmsg, sigmsg, sizeof(*sigmsg));
ftdm_queue_enqueue(span->pendingsignals, new_sigmsg);
return FTDM_SUCCESS;
}
FT_DECLARE(ftdm_status_t) ftdm_span_trigger_signals(const ftdm_span_t *span)
{
ftdm_sigmsg_t *sigmsg = NULL;
while ((sigmsg = ftdm_queue_dequeue(span->pendingsignals))) {
ftdm_span_trigger_signal(span, sigmsg);
ftdm_safe_free(sigmsg);
}
return FTDM_SUCCESS;
}
FT_DECLARE(ftdm_status_t) ftdm_span_send_signal(ftdm_span_t *span, ftdm_sigmsg_t *sigmsg)
{
ftdm_status_t status = FTDM_FAIL;
if (sigmsg->channel) {
ftdm_mutex_lock(sigmsg->channel->mutex);
}
@ -4401,9 +4437,11 @@ FT_DECLARE(ftdm_status_t) ftdm_span_send_signal(ftdm_span_t *span, ftdm_sigmsg_t
}
/* call the user callback only if set */
if (span->signal_cb) {
status = span->signal_cb(sigmsg);
/* if the signaling module uses a queue for signaling notifications, then enqueue it */
if (ftdm_test_flag(span, FTDM_SPAN_USE_SIGNALS_QUEUE)) {
ftdm_span_queue_signal(span, sigmsg);
} else {
ftdm_span_trigger_signal(span, sigmsg);
}
done:
@ -4411,7 +4449,7 @@ done:
ftdm_mutex_unlock(sigmsg->channel->mutex);
}
return status;
return FTDM_SUCCESS;
}
static void *ftdm_cpu_monitor_run(ftdm_thread_t *me, void *obj)

View File

@ -317,23 +317,6 @@ typedef struct ftdm_channel_config {
float txgain;
} ftdm_channel_config_t;
/*! \brief Generic signaling message */
struct ftdm_sigmsg {
ftdm_signal_event_t event_id; /*!< The type of message */
ftdm_channel_t *channel; /*!< Related channel */
uint32_t chan_id; /*!< easy access to chan id */
uint32_t span_id; /*!< easy access to span_id */
void *raw_data; /*!< Message specific data if any */
uint32_t raw_data_len; /*!< Data len in case is needed */
};
/*! \brief Crash policy
* Useful for debugging only, default policy is never, if you wish to crash on asserts then use ftdm_global_set_crash_policy */
typedef enum {
FTDM_CRASH_NEVER = 0,
FTDM_CRASH_ON_ASSERT
} ftdm_crash_policy_t;
/*!
\brief Signaling status on a given span or specific channel on protocols that support it
*/
@ -352,6 +335,24 @@ typedef enum {
/*! \brief Move from string to ftdm_signaling_status_t and viceversa */
FTDM_STR2ENUM_P(ftdm_str2ftdm_signaling_status, ftdm_signaling_status2str, ftdm_signaling_status_t)
/*! \brief Generic signaling message */
struct ftdm_sigmsg {
ftdm_signal_event_t event_id; /*!< The type of message */
ftdm_channel_t *channel; /*!< Related channel */
uint32_t chan_id; /*!< easy access to chan id */
uint32_t span_id; /*!< easy access to span_id */
ftdm_signaling_status_t sigstatus; /*!< Signaling status (valid if event_id is FTDM_SIGEVENT_SIGSTATUS_CHANGED) */
void *raw_data; /*!< Message specific data if any */
uint32_t raw_data_len; /*!< Data len in case is needed */
};
/*! \brief Crash policy
* Useful for debugging only, default policy is never, if you wish to crash on asserts then use ftdm_global_set_crash_policy */
typedef enum {
FTDM_CRASH_NEVER = 0,
FTDM_CRASH_ON_ASSERT
} ftdm_crash_policy_t;
/*! \brief I/O waiting flags */
typedef enum {
FTDM_NO_FLAGS = 0,

View File

@ -466,6 +466,7 @@ struct ftdm_span {
ftdm_state_map_t *state_map;
ftdm_caller_data_t default_caller_data;
ftdm_queue_t *pendingchans;
ftdm_queue_t *pendingsignals;
struct ftdm_span *next;
};
@ -579,6 +580,8 @@ FT_DECLARE(ftdm_status_t) ftdm_span_next_event(ftdm_span_t *span, ftdm_event_t *
*/
FT_DECLARE(ftdm_status_t) ftdm_channel_queue_dtmf(ftdm_channel_t *ftdmchan, const char *dtmf);
/* dequeue pending signals and notify the user via the span signal callback */
FT_DECLARE(ftdm_status_t) ftdm_span_trigger_signals(const ftdm_span_t *span);
/*!
\brief Assert condition

View File

@ -176,6 +176,10 @@ typedef enum {
FTDM_SPAN_USE_CHAN_QUEUE = (1 << 6),
FTDM_SPAN_SUGGEST_CHAN_ID = (1 << 7),
FTDM_SPAN_USE_AV_RATE = (1 << 8),
/* If you use this flag, you MUST call ftdm_span_trigger_signals to deliver the user signals
* after having called ftdm_send_span_signal(), which with this flag it will just enqueue the signal
* for later delivery */
FTDM_SPAN_USE_SIGNALS_QUEUE = (1 << 9),
} ftdm_span_flag_t;
/*! \brief Channel supported features */