root/src/include/private/ftdm_state.h

/* [<][>][^][v][top][bottom][index][help] */

INCLUDED FROM


DEFINITIONS

This source file includes following definitions.
  1. FTDM_STR2ENUM_P
  2. FT_DECLARE
  3. FTDM_STR2ENUM_P
  4. FT_DECLARE

   1 /*
   2  * Copyright (c) 2010, Sangoma Technologies
   3  * Moises Silva <moy@sangoma.com>
   4  * All rights reserved.
   5  * 
   6  * Redistribution and use in source and binary forms, with or without
   7  * modification, are permitted provided that the following conditions
   8  * are met:
   9  * 
  10  * * Redistributions of source code must retain the above copyright
  11  * notice, this list of conditions and the following disclaimer.
  12  * 
  13  * * Redistributions in binary form must reproduce the above copyright
  14  * notice, this list of conditions and the following disclaimer in the
  15  * documentation and/or other materials provided with the distribution.
  16  * 
  17  * * Neither the name of the original author; nor the names of any contributors
  18  * may be used to endorse or promote products derived from this software
  19  * without specific prior written permission.
  20  * 
  21  * 
  22  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  23  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  24  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  25  * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER
  26  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  27  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  28  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  29  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  30  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  31  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  32  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  33  */
  34 
  35 #ifndef __FTDM_STATE_H__
  36 #define __FTDM_STATE_H__
  37 
  38 /*! \file
  39  * \brief State handling definitions
  40  * \note Most, if not all of the state handling functions assume you have a lock acquired. Touching the channel
  41  *       state is a sensitive matter that requires checks and careful thought and is typically a process that
  42  *       is not encapsulated within a single function, therefore the lock must be explicitly acquired by the 
  43  *       caller (most of the time, signaling modules), process states, set a new state and process it, and 
  44  *       finally unlock the channel. See docs/locking.txt fore more info
  45  */
  46 
  47 #ifdef __cplusplus
  48 extern "C" {
  49 #endif
  50 
  51 typedef enum {
  52         FTDM_CHANNEL_STATE_DOWN,
  53         FTDM_CHANNEL_STATE_HOLD,
  54         FTDM_CHANNEL_STATE_SUSPENDED,
  55         FTDM_CHANNEL_STATE_DIALTONE,
  56         FTDM_CHANNEL_STATE_COLLECT,
  57         FTDM_CHANNEL_STATE_RING,
  58         FTDM_CHANNEL_STATE_RINGING,
  59         FTDM_CHANNEL_STATE_BUSY,
  60         FTDM_CHANNEL_STATE_ATTN,
  61         FTDM_CHANNEL_STATE_GENRING,
  62         FTDM_CHANNEL_STATE_DIALING,
  63         FTDM_CHANNEL_STATE_GET_CALLERID,
  64         FTDM_CHANNEL_STATE_CALLWAITING,
  65         FTDM_CHANNEL_STATE_RESTART,
  66         FTDM_CHANNEL_STATE_PROCEED,
  67         FTDM_CHANNEL_STATE_PROGRESS,
  68         FTDM_CHANNEL_STATE_PROGRESS_MEDIA,
  69         FTDM_CHANNEL_STATE_UP,
  70         FTDM_CHANNEL_STATE_IDLE,
  71         FTDM_CHANNEL_STATE_TERMINATING,
  72         FTDM_CHANNEL_STATE_CANCEL,
  73         FTDM_CHANNEL_STATE_HANGUP,
  74         FTDM_CHANNEL_STATE_HANGUP_COMPLETE,
  75         FTDM_CHANNEL_STATE_IN_LOOP,
  76         FTDM_CHANNEL_STATE_RESET,
  77         FTDM_CHANNEL_STATE_INVALID
  78 } ftdm_channel_state_t;
  79 #define CHANNEL_STATE_STRINGS "DOWN", "HOLD", "SUSPENDED", "DIALTONE", "COLLECT", \
  80                 "RING", "RINGING", "BUSY", "ATTN", "GENRING", "DIALING", "GET_CALLERID", "CALLWAITING", \
  81                 "RESTART", "PROCEED", "PROGRESS", "PROGRESS_MEDIA", "UP", "IDLE", "TERMINATING", "CANCEL", \
  82                 "HANGUP", "HANGUP_COMPLETE", "IN_LOOP", "RESET", "INVALID"
  83 FTDM_STR2ENUM_P(ftdm_str2ftdm_channel_state, ftdm_channel_state2str, ftdm_channel_state_t)
  84 
  85 typedef struct {
  86         const char *file;
  87         const char *func;
  88         int line;
  89         ftdm_channel_state_t state; /*!< Current state (processed or not) */
  90         ftdm_channel_state_t last_state; /*!< Previous state */
  91         ftdm_time_t time; /*!< Time the state was set */
  92         ftdm_time_t end_time; /*!< Time the state processing was completed */
  93 } ftdm_state_history_entry_t;
  94 
  95 typedef ftdm_status_t (*ftdm_channel_state_processor_t)(ftdm_channel_t *fchan);
  96 
  97 /*!
  98  * \brief Process channel states by invoking the channel state processing routine
  99  *        it will keep calling the processing routine while the state status
 100  *        is FTDM_STATE_STATUS_NEW, it will not do anything otherwise
 101  */
 102 FT_DECLARE(ftdm_status_t) ftdm_channel_advance_states(ftdm_channel_t *fchan);
 103 
 104 FT_DECLARE(ftdm_status_t) _ftdm_channel_complete_state(const char *file, const char *function, int line, ftdm_channel_t *fchan);
 105 #define ftdm_channel_complete_state(obj) _ftdm_channel_complete_state(__FILE__, __FUNCTION__, __LINE__, obj)
 106 FT_DECLARE(int) ftdm_check_state_all(ftdm_span_t *span, ftdm_channel_state_t state);
 107 
 108 /*!
 109  * \brief Status of the current channel state 
 110  * \note A given state goes thru several status (yes, states for the state!)
 111  * The order is always FTDM_STATE_STATUS_NEW -> FTDM_STATE_STATUS_PROCESSED -> FTDM_STATUS_COMPLETED
 112  * However, is possible to go from NEW -> COMPLETED directly when the signaling module explicitly changes 
 113  * the state of the channel in the middle of processing the current state by calling the ftdm_set_state() API
 114  *
 115  * FTDM_STATE_STATUS_NEW - 
 116  *   Someone just set the state of the channel, either the signaling module or the user (implicitly through a call API). 
 117  *   This is accomplished by calling ftdm_channel_set_state() which changes the 'state' and 'last_state' memebers of 
 118  *   the ftdm_channel_t structure.
 119  *
 120  * FTDM_STATE_STATUS_PROCESSED -
 121  *   The signaling module did something based on the new state.
 122  *
 123  *   This is accomplished via ftdm_channel_advance_states()
 124  *
 125  *   When ftdm_channel_advance_states(), at the very least, if the channel has its state in FTDM_STATE_STATUS_NEW, it
 126  *   will move to FTDM_STATE_STATUS_PROCESSED, depending on what the signaling module does during the processing
 127  *   the state may move to FTDM_STATE_STATUS_COMPLETED right after or wait for a signaling specific event to complete it.
 128  *   It is also possible that more state transitions occur during the execution of ftdm_channel_advance_states() if one
 129  *   state processing/completion leads to another state change, the function will not return until the chain of events
 130  *   lead to a state that is not in FTDM_STATE_STATUS_NEW
 131  *
 132  * FTDM_STATE_STATUS_COMPLETED - 
 133  *   The signaling module completed the processing of the state and there is nothing further to be done for this state.
 134  *
 135  *   This is accomplished either explicitly by the signaling module by calling ftdm_channel_complete_state() or by
 136  *   the signaling module implicitly by trying to set the state of the channel to a new state via ftdm_set_state()
 137  *
 138  *   When working with blocking channels (FTDM_CHANNEL_NONBLOCK flag not set), the user thread is signaled and unblocked 
 139  *   so it can continue.
 140  *
 141  *   When a state moves to this status is also possible for a signal FTDM_SIGEVENT_INDICATION_COMPLETED to be delivered 
 142  *   by the core if the state change was associated to an indication requested by the user, 
 143  */
 144 typedef enum {
 145         FTDM_STATE_STATUS_NEW,
 146         FTDM_STATE_STATUS_PROCESSED,
 147         FTDM_STATE_STATUS_COMPLETED,
 148         FTDM_STATE_STATUS_INVALID
 149 } ftdm_state_status_t;
 150 #define CHANNEL_STATE_STATUS_STRINGS "NEW", "PROCESSED", "COMPLETED", "INVALID"
 151 FTDM_STR2ENUM_P(ftdm_str2ftdm_state_status, ftdm_state_status2str, ftdm_state_status_t)
 152 
 153 typedef enum {
 154         ZSM_NONE,
 155         ZSM_UNACCEPTABLE,
 156         ZSM_ACCEPTABLE
 157 } ftdm_state_map_type_t;
 158 
 159 typedef enum {
 160         ZSD_INBOUND,
 161         ZSD_OUTBOUND,
 162 } ftdm_state_direction_t;
 163 
 164 #define FTDM_MAP_NODE_SIZE 512
 165 #define FTDM_MAP_MAX FTDM_CHANNEL_STATE_INVALID+2
 166 
 167 struct ftdm_state_map_node {
 168         ftdm_state_direction_t direction;
 169         ftdm_state_map_type_t type;
 170         ftdm_channel_state_t check_states[FTDM_MAP_MAX];
 171         ftdm_channel_state_t states[FTDM_MAP_MAX];
 172 };
 173 typedef struct ftdm_state_map_node ftdm_state_map_node_t;
 174 
 175 struct ftdm_state_map {
 176         ftdm_state_map_node_t nodes[FTDM_MAP_NODE_SIZE];
 177 };
 178 typedef struct ftdm_state_map ftdm_state_map_t;
 179 
 180 /*!\brief Cancel the state processing for a channel (the channel must be locked when calling this function)
 181  * \note Only the core should use this function
 182  */ 
 183 FT_DECLARE(ftdm_status_t) ftdm_channel_cancel_state(const char *file, const char *func, int line,
 184                 ftdm_channel_t *ftdmchan);
 185 
 186 /*!\brief Set the state for a channel (the channel must be locked when calling this function)
 187  * \note Signaling modules should use ftdm_set_state macro instead
 188  * \note If this function is called with the wait parameter set to a non-zero value, the recursivity
 189  *       of the channel lock must be == 1 because the channel will be unlocked/locked when waiting */
 190 FT_DECLARE(ftdm_status_t) ftdm_channel_set_state(const char *file, const char *func, int line,
 191                 ftdm_channel_t *ftdmchan, ftdm_channel_state_t state, int wait);
 192 
 193 /*!\brief Set the state of a channel immediately and implicitly complete the previous state if needed 
 194  * \note FTDM_SIGEVENT_INDICATION_COMPLETED will be sent if the state change 
 195  *       is associated to some indication (ie FTDM_CHANNEL_INDICATE_PROCEED)
 196  * \note The channel must be locked when calling this function
 197  * */
 198 FT_DECLARE(ftdm_status_t) _ftdm_set_state(const char *file, const char *func, int line,
 199                         ftdm_channel_t *fchan, ftdm_channel_state_t state);
 200 #define ftdm_set_state(obj, s) _ftdm_set_state(__FILE__, __FUNCTION__, __LINE__, obj, s);                                                                       \
 201 
 202 /*!\brief This macro is deprecated, signaling modules should always lock the channel themselves anyways since they must
 203  * process first the user pending state changes then set a new state before releasing the lock 
 204  * this macro is here for backwards compatibility, DO NOT USE IT in new code since it is *always* wrong to set
 205  * a state in a signaling module without checking and processing the current state first (and for that you must lock the channel)
 206  */
 207 #define ftdm_set_state_locked(obj, s) \
 208         do { \
 209                 ftdm_channel_lock(obj); \
 210                 ftdm_channel_set_state(__FILE__, __FUNCTION__, __LINE__, obj, s, 0);                                                                    \
 211                 ftdm_channel_unlock(obj); \
 212         } while(0);
 213 
 214 #define ftdm_set_state_r(obj, s, r) r = ftdm_channel_set_state(__FILE__, __FUNCTION__, __LINE__, obj, s, 0);
 215 
 216 #define ftdm_set_state_all(span, state) \
 217         do { \
 218                 uint32_t _j; \
 219                 ftdm_mutex_lock((span)->mutex); \
 220                 for(_j = 1; _j <= (span)->chan_count; _j++) { \
 221                         if (!FTDM_IS_DCHAN(span->channels[_j])) { \
 222                                 ftdm_set_state_locked((span->channels[_j]), state); \
 223                         } \
 224                 } \
 225                 ftdm_mutex_unlock((span)->mutex); \
 226         } while (0);
 227 
 228 #ifdef __cplusplus
 229 } 
 230 #endif
 231 
 232 #endif
 233 
 234 /* For Emacs:
 235  * Local Variables:
 236  * mode:c
 237  * indent-tabs-mode:t
 238  * tab-width:4
 239  * c-basic-offset:4
 240  * End:
 241  * For VIM:
 242  * vim:set softtabstop=4 shiftwidth=4 tabstop=4:
 243  */

/* [<][>][^][v][top][bottom][index][help] */