]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
freetdm: add asynchronous signal notification
authorMoises Silva <moy@sangoma.com>
Tue, 31 Aug 2010 22:13:56 +0000 (18:13 -0400)
committerMoises Silva <moy@sangoma.com>
Thu, 2 Sep 2010 16:43:44 +0000 (12:43 -0400)
libs/freetdm/src/ftdm_io.c
libs/freetdm/src/include/freetdm.h
libs/freetdm/src/include/private/ftdm_core.h
libs/freetdm/src/include/private/ftdm_types.h

index b087881e1dbd9b627d7a9b2efbbdfe13dc7e184a..7f27177024514901131686b829a7e3a6f25f4764 100644 (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
 
@@ -461,6 +462,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);
@@ -4160,6 +4164,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;
 }
 
@@ -4425,10 +4432,39 @@ FT_DECLARE(ftdm_status_t) ftdm_group_create(ftdm_group_t **group, const char *na
        return status;
 }
 
-FT_DECLARE(ftdm_status_t) ftdm_span_send_signal(ftdm_span_t *span, ftdm_sigmsg_t *sigmsg)
+static ftdm_status_t ftdm_span_trigger_signal(const ftdm_span_t *span, ftdm_sigmsg_t *sigmsg)
 {
-       ftdm_status_t status = FTDM_FAIL;
+       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)
+{
        if (sigmsg->channel) {
                ftdm_mutex_lock(sigmsg->channel->mutex);
        }
@@ -4463,10 +4499,12 @@ FT_DECLARE(ftdm_status_t) ftdm_span_send_signal(ftdm_span_t *span, ftdm_sigmsg_t
                break;  
 
        }
-
-       /* 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:
@@ -4474,7 +4512,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)
index 61d37c88781c6acdbfae9d3da73af408229eee81..7501bb4977d83873bdd731a484994649afef78ab 100644 (file)
@@ -331,23 +331,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
  */
@@ -366,6 +349,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,
index eb9a84a84ad85c66f3f94f5576837926ce86cddc..74bea8148cde246d6e52f3bd4debdf640e51ebfa 100644 (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,9 @@ 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
 */
index 572e63299b6521e050e4960ea559e6291e779206..d8e8b5c2e6e71661b2df63bbece74e8da122991a 100644 (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 */