Asterisk - The Open Source Telephony Project GIT-master-8f1982c
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Macros Modules Pages
Data Structures | Macros | Enumerations | Functions | Variables
app_sla.c File Reference

Shared Line Appearances. More...

#include "asterisk.h"
#include "asterisk/lock.h"
#include "asterisk/file.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/config.h"
#include "asterisk/app.h"
#include "asterisk/cli.h"
#include "asterisk/utils.h"
#include "asterisk/astobj2.h"
#include "asterisk/devicestate.h"
#include "asterisk/dial.h"
#include "asterisk/causes.h"
#include "asterisk/format_compatibility.h"
Include dependency graph for app_sla.c:

Go to the source code of this file.

Data Structures

struct  dial_trunk_args
 
struct  run_station_args
 
struct  sla_event
 
struct  sla_failed_station
 A station that failed to be dialed. More...
 
struct  sla_framehook_data
 Framehook to support HOLD within the conference. More...
 
struct  sla_ringing_station
 A station that is ringing. More...
 
struct  sla_ringing_trunk
 A trunk that is ringing. More...
 
struct  sla_station
 
struct  sla_station_ref
 A reference to a station. More...
 
struct  sla_trunk
 
struct  sla_trunk_ref
 A station's reference to a trunk. More...
 

Macros

#define MAX_CONFNUM   80
 
#define S(e)   case e: return # e;
 
#define SLA_CONFIG_FILE   "sla.conf"
 

Enumerations

enum  {
  CONFFLAG_QUIET = (1 << 0) , CONFFLAG_MOH = (1 << 1) , CONFFLAG_MARKEDEXIT = (1 << 2) , CONFFLAG_MARKEDUSER = (1 << 3) ,
  CONFFLAG_PASS_DTMF = (1 << 4) , CONFFLAG_SLA_STATION = (1 << 5) , CONFFLAG_SLA_TRUNK = (1 << 6)
}
 
enum  { SLA_TRUNK_OPT_MOH = (1 << 0) }
 
enum  { SLA_TRUNK_OPT_ARG_MOH_CLASS = 0 , SLA_TRUNK_OPT_ARG_ARRAY_SIZE = 1 }
 
enum  sla_event_type { SLA_EVENT_HOLD , SLA_EVENT_DIAL_STATE , SLA_EVENT_RINGING_TRUNK }
 Event types that can be queued up for the SLA thread. More...
 
enum  sla_hold_access { SLA_HOLD_OPEN , SLA_HOLD_PRIVATE }
 
enum  sla_station_hangup { SLA_STATION_HANGUP_NORMAL , SLA_STATION_HANGUP_TIMEOUT }
 
enum  sla_trunk_state {
  SLA_TRUNK_STATE_IDLE , SLA_TRUNK_STATE_RINGING , SLA_TRUNK_STATE_UP , SLA_TRUNK_STATE_ONHOLD ,
  SLA_TRUNK_STATE_ONHOLD_BYME
}
 
enum  sla_which_trunk_refs { ALL_TRUNK_REFS , INACTIVE_TRUNK_REFS }
 

Functions

static void __reg_module (void)
 
static void __unreg_module (void)
 
static void answer_trunk_chan (struct ast_channel *chan)
 
struct ast_moduleAST_MODULE_SELF_SYM (void)
 
static int attach_framehook (struct ast_channel *chan, const char *confname)
 
static int conf_kick_all (struct ast_channel *chan, const char *confname)
 
static int conf_run (struct ast_channel *chan, const char *confname, struct ast_flags *confflags, char *optargs[])
 
static struct sla_trunk_refcreate_trunk_ref (struct sla_trunk *trunk)
 
static void * dial_trunk (void *data)
 
static int load_config (int reload)
 
static int load_module (void)
 Load the module. More...
 
static struct sla_ringing_trunkqueue_ringing_trunk (struct sla_trunk *trunk)
 
static int reload (void)
 
static int remove_framehook (struct ast_channel *chan)
 
static void * run_station (void *data)
 
static void sla_add_trunk_to_station (struct sla_station *station, struct ast_variable *var)
 
static int sla_build_station (struct ast_config *cfg, const char *cat)
 
static int sla_build_trunk (struct ast_config *cfg, const char *cat)
 
static int sla_calc_station_delays (unsigned int *timeout)
 Calculate the ring delay for a station. More...
 
static int sla_calc_station_timeouts (unsigned int *timeout)
 Process station ring timeouts. More...
 
static int sla_calc_trunk_timeouts (unsigned int *timeout)
 Process trunk ring timeouts. More...
 
static void sla_change_trunk_state (const struct sla_trunk *trunk, enum sla_trunk_state state, enum sla_which_trunk_refs inactive_only, const struct sla_trunk_ref *exclude)
 
static int sla_check_device (const char *device)
 
static int sla_check_failed_station (const struct sla_station *station)
 Check to see if this station has failed to be dialed in the past minute. More...
 
static int sla_check_inuse_station (const struct sla_station *station)
 Check to see if a station is in use. More...
 
static int sla_check_ringing_station (const struct sla_station *station)
 Check to see if this station is already ringing. More...
 
static int sla_check_station_delay (struct sla_station *station, struct sla_ringing_trunk *ringing_trunk)
 Calculate the ring delay for a given ringing trunk on a station. More...
 
static int sla_check_station_hold_access (const struct sla_trunk *trunk, const struct sla_station *station)
 
static int sla_check_timed_out_station (const struct sla_ringing_trunk *ringing_trunk, const struct sla_station *station)
 Check to see if dialing this station already timed out for this ringing trunk. More...
 
static struct sla_trunk_refsla_choose_idle_trunk (const struct sla_station *station)
 For a given station, choose the highest priority idle trunk. More...
 
static struct sla_ringing_trunksla_choose_ringing_trunk (struct sla_station *station, struct sla_trunk_ref **trunk_ref, int rm)
 Choose the highest priority ringing trunk for a station. More...
 
static struct sla_failed_stationsla_create_failed_station (struct sla_station *station)
 
static struct sla_ringing_stationsla_create_ringing_station (struct sla_station *station)
 
static struct sla_station_refsla_create_station_ref (struct sla_station *station)
 
static void sla_destroy (void)
 
static void sla_dial_state_callback (struct ast_dial *dial)
 
static void sla_event_destroy (struct sla_event *event)
 
static void sla_failed_station_destroy (struct sla_failed_station *failed_station)
 
static struct sla_stationsla_find_station (const char *name)
 
static struct sla_trunksla_find_trunk (const char *name)
 
static struct sla_trunk_refsla_find_trunk_ref (const struct sla_station *station, const struct sla_trunk *trunk)
 
static struct sla_trunk_refsla_find_trunk_ref_byname (const struct sla_station *station, const char *name)
 Find a trunk reference on a station by name. More...
 
static struct ast_framesla_framehook (struct ast_channel *chan, struct ast_frame *f, enum ast_framehook_event event, void *data)
 
static int sla_framehook_consume (void *data, enum ast_frame_type type)
 Callback function which informs upstream if we are consuming a frame of a specific type. More...
 
static void sla_handle_dial_state_event (void)
 
static void sla_handle_hold_event (struct sla_event *event)
 
static void sla_handle_ringing_trunk_event (void)
 
static void sla_hangup_stations (void)
 
static const char * sla_hold_str (unsigned int hold_access)
 
static int sla_in_use (void)
 
static int sla_load_config (int reload)
 
static int sla_process_timers (struct timespec *ts)
 Calculate the time until the next known event. More...
 
static void sla_queue_event (enum sla_event_type type)
 
static void sla_queue_event_conf (enum sla_event_type type, struct ast_channel *chan, const char *confname)
 Queue a SLA event from the conference. More...
 
static void sla_queue_event_full (enum sla_event_type type, struct sla_trunk_ref *trunk_ref, struct sla_station *station, int lock)
 
static void sla_queue_event_nolock (enum sla_event_type type)
 
static int sla_ring_station (struct sla_ringing_trunk *ringing_trunk, struct sla_station *station)
 Ring a station. More...
 
static void sla_ring_stations (void)
 Ring stations based on current set of ringing trunks. More...
 
static void sla_ringing_station_destroy (struct sla_ringing_station *ringing_station)
 
static void sla_ringing_trunk_destroy (struct sla_ringing_trunk *ringing_trunk)
 
static char * sla_show_stations (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * sla_show_trunks (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static enum ast_device_state sla_state (const char *data)
 
static enum ast_device_state sla_state_to_devstate (enum sla_trunk_state state)
 
static int sla_station_cmp (void *obj, void *arg, int flags)
 
static void sla_station_destructor (void *obj)
 
static int sla_station_exec (struct ast_channel *chan, const char *data)
 
static int sla_station_is_marked (void *obj, void *arg, int flags)
 
static int sla_station_mark (void *obj, void *arg, int flags)
 
static void sla_station_ref_destructor (void *obj)
 
static int sla_station_release_refs (void *obj, void *arg, int flags)
 
static void sla_stop_ringing_station (struct sla_ringing_station *ringing_station, enum sla_station_hangup hangup)
 
static void sla_stop_ringing_trunk (struct sla_ringing_trunk *ringing_trunk)
 
static void * sla_thread (void *data)
 
static int sla_trunk_cmp (void *obj, void *arg, int flags)
 
static void sla_trunk_destructor (void *obj)
 
static int sla_trunk_exec (struct ast_channel *chan, const char *data)
 
static int sla_trunk_is_marked (void *obj, void *arg, int flags)
 
static int sla_trunk_mark (void *obj, void *arg, int flags)
 
static void sla_trunk_ref_destructor (void *obj)
 
static int sla_trunk_release_refs (void *obj, void *arg, int flags)
 
static const char * trunkstate2str (enum sla_trunk_state state)
 
static int unload_module (void)
 

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Shared Line Appearances" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .support_level = AST_MODULE_SUPPORT_EXTENDED, .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_DEVSTATE_PROVIDER, }
 
static const struct ast_module_infoast_module_info = &__mod_info
 
static struct ast_cli_entry cli_sla []
 
struct {
   unsigned int   attempt_callerid:1
 
   ast_cond_t   cond
 
   struct {
      struct sla_event *   first
 
      struct sla_event *   last
 
   }   event_q
 
   struct {
      struct sla_failed_station *   first
 
      struct sla_failed_station *   last
 
   }   failed_stations
 
   ast_mutex_t   lock
 
   struct {
      struct sla_ringing_station *   first
 
      struct sla_ringing_station *   last
 
   }   ringing_stations
 
   struct {
      struct sla_ringing_trunk *   first
 
      struct sla_ringing_trunk *   last
 
   }   ringing_trunks
 
   unsigned int   stop:1
 
   pthread_t   thread
 
sla
 A structure for data used by the sla thread. More...
 
static const struct ast_datastore_info sla_framehook_datastore
 
static const char sla_registrar [] = "SLA"
 
static struct ao2_containersla_stations
 
static const struct ast_app_option sla_trunk_opts [128] = { [ 'M' ] = { .flag = SLA_TRUNK_OPT_MOH , .arg_index = SLA_TRUNK_OPT_ARG_MOH_CLASS + 1 }, }
 
static struct ao2_containersla_trunks
 
static const char *const slastation_app = "SLAStation"
 
static const char *const slatrunk_app = "SLATrunk"
 

Detailed Description

Shared Line Appearances.

Author
Naveen Albert aster.nosp@m.isk@.nosp@m.phrea.nosp@m.knet.nosp@m..org

Definition in file app_sla.c.

Macro Definition Documentation

◆ MAX_CONFNUM

#define MAX_CONFNUM   80

Definition at line 131 of file app_sla.c.

◆ S

#define S (   e)    case e: return # e;

◆ SLA_CONFIG_FILE

#define SLA_CONFIG_FILE   "sla.conf"

Definition at line 130 of file app_sla.c.

Enumeration Type Documentation

◆ anonymous enum

anonymous enum
Enumerator
CONFFLAG_QUIET 

If set there will be no enter or leave sounds

CONFFLAG_MOH 

Set to have music on hold when user is alone in conference

CONFFLAG_MARKEDEXIT 

If set, the channel will leave the conference if all marked users leave

CONFFLAG_MARKEDUSER 

If set, the user will be marked

CONFFLAG_PASS_DTMF 

Pass DTMF through the conference

CONFFLAG_SLA_STATION 
CONFFLAG_SLA_TRUNK 

Definition at line 136 of file app_sla.c.

136 {
137 /*! If set there will be no enter or leave sounds */
138 CONFFLAG_QUIET = (1 << 0),
139 /*! Set to have music on hold when user is alone in conference */
140 CONFFLAG_MOH = (1 << 1),
141 /*! If set, the channel will leave the conference if all marked users leave */
142 CONFFLAG_MARKEDEXIT = (1 << 2),
143 /*! If set, the user will be marked */
144 CONFFLAG_MARKEDUSER = (1 << 3),
145 /*! Pass DTMF through the conference */
146 CONFFLAG_PASS_DTMF = (1 << 4),
147 CONFFLAG_SLA_STATION = (1 << 5),
148 CONFFLAG_SLA_TRUNK = (1 << 6),
149};
@ CONFFLAG_QUIET
Definition: app_sla.c:138
@ CONFFLAG_MARKEDUSER
Definition: app_sla.c:144
@ CONFFLAG_MARKEDEXIT
Definition: app_sla.c:142
@ CONFFLAG_PASS_DTMF
Definition: app_sla.c:146
@ CONFFLAG_MOH
Definition: app_sla.c:140
@ CONFFLAG_SLA_TRUNK
Definition: app_sla.c:148
@ CONFFLAG_SLA_STATION
Definition: app_sla.c:147

◆ anonymous enum

anonymous enum
Enumerator
SLA_TRUNK_OPT_MOH 

Definition at line 151 of file app_sla.c.

151 {
152 SLA_TRUNK_OPT_MOH = (1 << 0),
153};
@ SLA_TRUNK_OPT_MOH
Definition: app_sla.c:152

◆ anonymous enum

anonymous enum
Enumerator
SLA_TRUNK_OPT_ARG_MOH_CLASS 
SLA_TRUNK_OPT_ARG_ARRAY_SIZE 

Definition at line 155 of file app_sla.c.

155 {
158};
@ SLA_TRUNK_OPT_ARG_MOH_CLASS
Definition: app_sla.c:156
@ SLA_TRUNK_OPT_ARG_ARRAY_SIZE
Definition: app_sla.c:157

◆ sla_event_type

Event types that can be queued up for the SLA thread.

Enumerator
SLA_EVENT_HOLD 

A station has put the call on hold

SLA_EVENT_DIAL_STATE 

The state of a dial has changed

SLA_EVENT_RINGING_TRUNK 

The state of a ringing trunk has changed

Definition at line 284 of file app_sla.c.

284 {
285 /*! A station has put the call on hold */
287 /*! The state of a dial has changed */
289 /*! The state of a ringing trunk has changed */
291};
@ SLA_EVENT_RINGING_TRUNK
Definition: app_sla.c:290
@ SLA_EVENT_HOLD
Definition: app_sla.c:286
@ SLA_EVENT_DIAL_STATE
Definition: app_sla.c:288

◆ sla_hold_access

Enumerator
SLA_HOLD_OPEN 

This means that any station can put it on hold, and any station can retrieve the call from hold.

SLA_HOLD_PRIVATE 

This means that only the station that put the call on hold may retrieve it from hold.

Definition at line 177 of file app_sla.c.

177 {
178 /*! This means that any station can put it on hold, and any station
179 * can retrieve the call from hold. */
181 /*! This means that only the station that put the call on hold may
182 * retrieve it from hold. */
184};
@ SLA_HOLD_OPEN
Definition: app_sla.c:180
@ SLA_HOLD_PRIVATE
Definition: app_sla.c:183

◆ sla_station_hangup

Enumerator
SLA_STATION_HANGUP_NORMAL 
SLA_STATION_HANGUP_TIMEOUT 

Definition at line 317 of file app_sla.c.

317 {
320};
@ SLA_STATION_HANGUP_NORMAL
Definition: app_sla.c:318
@ SLA_STATION_HANGUP_TIMEOUT
Definition: app_sla.c:319

◆ sla_trunk_state

Enumerator
SLA_TRUNK_STATE_IDLE 
SLA_TRUNK_STATE_RINGING 
SLA_TRUNK_STATE_UP 
SLA_TRUNK_STATE_ONHOLD 
SLA_TRUNK_STATE_ONHOLD_BYME 

Definition at line 169 of file app_sla.c.

169 {
175};
@ SLA_TRUNK_STATE_ONHOLD
Definition: app_sla.c:173
@ SLA_TRUNK_STATE_RINGING
Definition: app_sla.c:171
@ SLA_TRUNK_STATE_UP
Definition: app_sla.c:172
@ SLA_TRUNK_STATE_ONHOLD_BYME
Definition: app_sla.c:174
@ SLA_TRUNK_STATE_IDLE
Definition: app_sla.c:170

◆ sla_which_trunk_refs

Enumerator
ALL_TRUNK_REFS 
INACTIVE_TRUNK_REFS 

Definition at line 164 of file app_sla.c.

164 {
167};
@ INACTIVE_TRUNK_REFS
Definition: app_sla.c:166
@ ALL_TRUNK_REFS
Definition: app_sla.c:165

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 2881 of file app_sla.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 2881 of file app_sla.c.

◆ answer_trunk_chan()

static void answer_trunk_chan ( struct ast_channel chan)
static

Definition at line 917 of file app_sla.c.

918{
919 ast_raw_answer(chan); /* Do NOT use ast_answer since that waits for media using ast_waitfor_nandfds. */
920 ast_indicate(chan, -1);
921}
int ast_indicate(struct ast_channel *chan, int condition)
Indicates condition of channel.
Definition: channel.c:4234
int ast_raw_answer(struct ast_channel *chan)
Answer a channel.
Definition: channel.c:2659

References ast_indicate(), ast_raw_answer(), and sla_trunk_ref::chan.

Referenced by run_station(), sla_handle_dial_state_event(), and sla_station_exec().

◆ AST_MODULE_SELF_SYM()

struct ast_module * AST_MODULE_SELF_SYM ( void  )

Definition at line 2881 of file app_sla.c.

◆ attach_framehook()

static int attach_framehook ( struct ast_channel chan,
const char *  confname 
)
static

Definition at line 666 of file app_sla.c.

667{
668 struct ast_datastore *datastore;
669 struct sla_framehook_data *data;
670 static struct ast_framehook_interface sla_framehook_interface = {
672 .event_cb = sla_framehook,
673 .consume_cb = sla_framehook_consume,
674 .disable_inheritance = 1,
675 };
676 SCOPED_CHANNELLOCK(chan_lock, chan);
677
679 if (datastore) {
680 ast_log(AST_LOG_WARNING, "SLA framehook already set on '%s'\n", ast_channel_name(chan));
681 return 0;
682 }
683
685 if (!datastore) {
686 return -1;
687 }
688
689 data = ast_calloc(1, sizeof(*data));
690 if (!data) {
691 ast_datastore_free(datastore);
692 return -1;
693 }
694
695 data->framehook_id = ast_framehook_attach(chan, &sla_framehook_interface);
696 data->confname = ast_strdup(confname);
697 if (!data->confname || data->framehook_id < 0) {
698 ast_log(AST_LOG_WARNING, "Failed to attach SLA framehook to '%s'\n", ast_channel_name(chan));
699 ast_datastore_free(datastore);
700 ast_free(data);
701 return -1;
702 }
703 datastore->data = data;
704
705 ast_channel_datastore_add(chan, datastore);
706 return 0;
707}
static int sla_framehook_consume(void *data, enum ast_frame_type type)
Callback function which informs upstream if we are consuming a frame of a specific type.
Definition: app_sla.c:661
static struct ast_frame * sla_framehook(struct ast_channel *chan, struct ast_frame *f, enum ast_framehook_event event, void *data)
Definition: app_sla.c:648
static const struct ast_datastore_info sla_framehook_datastore
Definition: app_sla.c:616
#define ast_free(a)
Definition: astmm.h:180
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:241
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:202
#define ast_log
Definition: astobj2.c:42
const char * ast_channel_name(const struct ast_channel *chan)
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
Definition: channel.c:2354
struct ast_datastore * ast_channel_datastore_find(struct ast_channel *chan, const struct ast_datastore_info *info, const char *uid)
Find a datastore on a channel.
Definition: channel.c:2368
#define ast_datastore_alloc(info, uid)
Definition: datastore.h:85
int ast_datastore_free(struct ast_datastore *datastore)
Free a data store object.
Definition: datastore.c:68
int ast_framehook_attach(struct ast_channel *chan, struct ast_framehook_interface *i)
Attach an framehook onto a channel for frame interception.
Definition: framehook.c:132
#define AST_FRAMEHOOK_INTERFACE_VERSION
Definition: framehook.h:227
#define AST_LOG_WARNING
#define SCOPED_CHANNELLOCK(varname, chan)
scoped lock specialization for channels.
Definition: lock.h:626
#define NULL
Definition: resample.c:96
Structure for a data store object.
Definition: datastore.h:64
void * data
Definition: datastore.h:66
Framehook to support HOLD within the conference.
Definition: app_sla.c:611

References ast_calloc, ast_channel_datastore_add(), ast_channel_datastore_find(), ast_channel_name(), ast_datastore_alloc, ast_datastore_free(), ast_framehook_attach(), AST_FRAMEHOOK_INTERFACE_VERSION, ast_free, ast_log, AST_LOG_WARNING, ast_strdup, ast_datastore::data, ast_framehook_interface::data, NULL, SCOPED_CHANNELLOCK, sla_framehook(), sla_framehook_consume(), sla_framehook_datastore, and ast_framehook_interface::version.

Referenced by conf_run().

◆ conf_kick_all()

static int conf_kick_all ( struct ast_channel chan,
const char *  confname 
)
static

Definition at line 958 of file app_sla.c.

959{
960 char confkick_args[256];
961
962 snprintf(confkick_args, sizeof(confkick_args), "%s,all", confname);
963 ast_debug(2, "Kicking all participants from conference %s\n", confname);
964
965 if (chan) {
966 return ast_pbx_exec_application(chan, "ConfKick", confkick_args);
967 } else {
968 /* We might not have a channel available to us, use a dummy channel in that case. */
970 if (!chan) {
971 ast_log(LOG_WARNING, "Failed to allocate dummy channel\n");
972 return -1;
973 } else {
974 int res = ast_pbx_exec_application(chan, "ConfKick", confkick_args);
975 ast_channel_unref(chan);
976 return res;
977 }
978 }
979}
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:3008
#define ast_dummy_channel_alloc()
Create a fake channel structure.
Definition: channel.h:1328
#define ast_debug(level,...)
Log a DEBUG message.
#define LOG_WARNING
int ast_pbx_exec_application(struct ast_channel *chan, const char *app_name, const char *app_args)
Execute an application.
Definition: pbx_app.c:501

References ast_channel_unref, ast_debug, ast_dummy_channel_alloc, ast_log, ast_pbx_exec_application(), sla_trunk_ref::chan, and LOG_WARNING.

Referenced by run_station(), sla_station_exec(), and sla_stop_ringing_trunk().

◆ conf_run()

static int conf_run ( struct ast_channel chan,
const char *  confname,
struct ast_flags confflags,
char *  optargs[] 
)
static

Definition at line 923 of file app_sla.c.

924{
925 char confbridge_args[256];
926 int res = 0;
927
928 snprintf(confbridge_args, sizeof(confbridge_args), "%s", confname);
929
930 res |= ast_func_write(chan, "CONFBRIDGE(user,quiet)", ast_test_flag(confflags, CONFFLAG_QUIET) ? "1" : "0");
931 res |= ast_func_write(chan, "CONFBRIDGE(user,dtmf_passthrough)", ast_test_flag(confflags, CONFFLAG_PASS_DTMF) ? "1" : "0");
932 res |= ast_func_write(chan, "CONFBRIDGE(user,marked)", ast_test_flag(confflags, CONFFLAG_MARKEDUSER) ? "1" : "0");
933 res |= ast_func_write(chan, "CONFBRIDGE(user,end_marked)", ast_test_flag(confflags, CONFFLAG_MARKEDEXIT) ? "1" : "0");
934 res |= ast_func_write(chan, "CONFBRIDGE(user,music_on_hold_when_empty)", ast_test_flag(confflags, CONFFLAG_MOH) ? "1" : "0");
936 res |= ast_func_write(chan, "CONFBRIDGE(user,music_on_hold_class)", optargs[SLA_TRUNK_OPT_ARG_MOH_CLASS]);
937 }
938
939 if (res) {
940 ast_log(LOG_ERROR, "Failed to set up conference, aborting\n");
941 return -1;
942 }
943
944 /* Attach a framehook that we'll use to process HOLD from stations. */
945 if (ast_test_flag(confflags, CONFFLAG_SLA_STATION) && attach_framehook(chan, confname)) {
946 return -1;
947 }
948
949 ast_debug(2, "Channel %s is running ConfBridge(%s)\n", ast_channel_name(chan), confbridge_args);
950 res = ast_pbx_exec_application(chan, "ConfBridge", confbridge_args);
951
952 if (ast_test_flag(confflags, CONFFLAG_SLA_STATION)) {
953 remove_framehook(chan);
954 }
955 return res;
956}
static int remove_framehook(struct ast_channel *chan)
Definition: app_sla.c:620
static int attach_framehook(struct ast_channel *chan, const char *confname)
Definition: app_sla.c:666
#define LOG_ERROR
int ast_func_write(struct ast_channel *chan, const char *function, const char *value)
executes a write operation on a function
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
#define ast_test_flag(p, flag)
Definition: utils.h:63

References ast_channel_name(), ast_debug, ast_func_write(), ast_log, ast_pbx_exec_application(), ast_strlen_zero(), ast_test_flag, attach_framehook(), sla_trunk_ref::chan, CONFFLAG_MARKEDEXIT, CONFFLAG_MARKEDUSER, CONFFLAG_MOH, CONFFLAG_PASS_DTMF, CONFFLAG_QUIET, CONFFLAG_SLA_STATION, LOG_ERROR, remove_framehook(), and SLA_TRUNK_OPT_ARG_MOH_CLASS.

Referenced by dial_trunk(), run_station(), sla_station_exec(), and sla_trunk_exec().

◆ create_trunk_ref()

static struct sla_trunk_ref * create_trunk_ref ( struct sla_trunk trunk)
static

Definition at line 2112 of file app_sla.c.

2113{
2114 struct sla_trunk_ref *trunk_ref;
2115
2116 if (!(trunk_ref = ao2_alloc(sizeof(*trunk_ref), sla_trunk_ref_destructor))) {
2117 return NULL;
2118 }
2119
2120 ao2_ref(trunk, 1);
2121 trunk_ref->trunk = trunk;
2122
2123 return trunk_ref;
2124}
static void sla_trunk_ref_destructor(void *obj)
Definition: app_sla.c:2102
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:409
A station's reference to a trunk.
Definition: app_sla.c:261
struct sla_trunk * trunk
Definition: app_sla.c:263

References ao2_alloc, ao2_ref, NULL, sla_trunk_ref_destructor(), and sla_trunk_ref::trunk.

Referenced by sla_add_trunk_to_station().

◆ dial_trunk()

static void * dial_trunk ( void *  data)
static

Definition at line 1800 of file app_sla.c.

1801{
1802 struct dial_trunk_args *args = data;
1803 struct ast_dial *dial;
1804 char *tech, *tech_data;
1805 enum ast_dial_result dial_res;
1806 char conf_name[MAX_CONFNUM];
1807 struct ast_flags conf_flags = { 0 };
1808 RAII_VAR(struct sla_trunk_ref *, trunk_ref, args->trunk_ref, ao2_cleanup);
1809 RAII_VAR(struct sla_station *, station, args->station, ao2_cleanup);
1810 int caller_is_saved;
1811 struct ast_party_caller caller;
1812 int last_state = 0;
1813 int current_state = 0;
1814
1815 if (!(dial = ast_dial_create())) {
1816 ast_mutex_lock(args->cond_lock);
1817 ast_cond_signal(args->cond);
1818 ast_mutex_unlock(args->cond_lock);
1819 return NULL;
1820 }
1821
1822 tech_data = ast_strdupa(trunk_ref->trunk->device);
1823 tech = strsep(&tech_data, "/");
1824 if (ast_dial_append(dial, tech, tech_data, NULL) == -1) {
1825 ast_mutex_lock(args->cond_lock);
1826 ast_cond_signal(args->cond);
1827 ast_mutex_unlock(args->cond_lock);
1828 ast_dial_destroy(dial);
1829 return NULL;
1830 }
1831
1832 /* Do we need to save of the caller ID data? */
1833 caller_is_saved = 0;
1834 if (!sla.attempt_callerid) {
1835 caller_is_saved = 1;
1836 caller = *ast_channel_caller(trunk_ref->chan);
1837 ast_party_caller_init(ast_channel_caller(trunk_ref->chan));
1838 }
1839
1840 dial_res = ast_dial_run(dial, trunk_ref->chan, 1);
1841
1842 /* Restore saved caller ID */
1843 if (caller_is_saved) {
1844 ast_party_caller_free(ast_channel_caller(trunk_ref->chan));
1845 ast_channel_caller_set(trunk_ref->chan, &caller);
1846 }
1847
1848 if (dial_res != AST_DIAL_RESULT_TRYING) {
1849 ast_mutex_lock(args->cond_lock);
1850 ast_cond_signal(args->cond);
1851 ast_mutex_unlock(args->cond_lock);
1852 ast_dial_destroy(dial);
1853 return NULL;
1854 }
1855
1856 /* Wait for dial to end, while servicing the channel */
1857 while (ast_waitfor(trunk_ref->chan, 100)) {
1858 unsigned int done = 0;
1859 struct ast_frame *fr = ast_read(trunk_ref->chan);
1860
1861 if (!fr) {
1862 ast_debug(1, "Channel %s did not return a frame, must have hung up\n", ast_channel_name(trunk_ref->chan));
1863 done = 1;
1864 break;
1865 }
1866 ast_frfree(fr); /* Ignore while dialing */
1867
1868 switch ((dial_res = ast_dial_state(dial))) {
1870 trunk_ref->trunk->chan = ast_dial_answered(dial);
1876 done = 1;
1877 break;
1879 current_state = AST_CONTROL_PROGRESS;
1880 break;
1884 current_state = AST_CONTROL_RINGING;
1885 break;
1886 }
1887 if (done) {
1888 break;
1889 }
1890
1891 /* check that SLA station that originated trunk call is still alive */
1892 if (station && ast_device_state(station->device) == AST_DEVICE_NOT_INUSE) {
1893 ast_debug(3, "Originating station device %s no longer active\n", station->device);
1894 trunk_ref->trunk->chan = NULL;
1895 break;
1896 }
1897
1898 /* If trunk line state changed, send indication back to originating SLA Station channel */
1899 if (current_state != last_state) {
1900 ast_debug(3, "Indicating State Change %d to channel %s\n", current_state, ast_channel_name(trunk_ref->chan));
1901 ast_indicate(trunk_ref->chan, current_state);
1902 last_state = current_state;
1903 }
1904 }
1905
1906 if (!trunk_ref->trunk->chan) {
1907 ast_mutex_lock(args->cond_lock);
1908 ast_cond_signal(args->cond);
1909 ast_mutex_unlock(args->cond_lock);
1910 ast_dial_join(dial);
1911 ast_dial_destroy(dial);
1912 return NULL;
1913 }
1914
1915 snprintf(conf_name, sizeof(conf_name), "SLA_%s", trunk_ref->trunk->name);
1917
1918 ast_mutex_lock(args->cond_lock);
1919 ast_cond_signal(args->cond);
1920 ast_mutex_unlock(args->cond_lock);
1921
1922 ast_debug(2, "Trunk dial %s joining conference %s\n", trunk_ref->trunk->name, conf_name);
1923 conf_run(trunk_ref->trunk->chan, conf_name, &conf_flags, NULL);
1924
1925 /* If the trunk is going away, it is definitely now IDLE. */
1927
1928 trunk_ref->trunk->chan = NULL;
1929 trunk_ref->trunk->on_hold = 0;
1930
1931 ast_dial_join(dial);
1932 ast_dial_destroy(dial);
1933
1934 return NULL;
1935}
static struct @66 sla
A structure for data used by the sla thread.
static void sla_change_trunk_state(const struct sla_trunk *trunk, enum sla_trunk_state state, enum sla_which_trunk_refs inactive_only, const struct sla_trunk_ref *exclude)
Definition: app_sla.c:886
#define MAX_CONFNUM
Definition: app_sla.c:131
static int conf_run(struct ast_channel *chan, const char *confname, struct ast_flags *confflags, char *optargs[])
Definition: app_sla.c:923
char * strsep(char **str, const char *delims)
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:298
#define ao2_cleanup(obj)
Definition: astobj2.h:1934
void ast_channel_caller_set(struct ast_channel *chan, struct ast_party_caller *value)
int ast_waitfor(struct ast_channel *chan, int ms)
Wait for input on a channel.
Definition: channel.c:3130
struct ast_frame * ast_read(struct ast_channel *chan)
Reads a frame.
Definition: channel.c:4214
void ast_party_caller_free(struct ast_party_caller *doomed)
Destroy the caller party contents.
Definition: channel.c:1982
struct ast_party_caller * ast_channel_caller(struct ast_channel *chan)
void ast_party_caller_init(struct ast_party_caller *init)
Initialize the given caller structure.
Definition: channel.c:1945
ast_device_state
Device States.
Definition: devicestate.h:52
@ AST_DEVICE_NOT_INUSE
Definition: devicestate.h:54
enum ast_dial_result ast_dial_state(struct ast_dial *dial)
Return state of dial.
Definition: dial.c:1008
ast_dial_result
List of return codes for dial run API calls.
Definition: dial.h:54
@ AST_DIAL_RESULT_FAILED
Definition: dial.h:56
@ AST_DIAL_RESULT_HANGUP
Definition: dial.h:63
@ AST_DIAL_RESULT_INVALID
Definition: dial.h:55
@ AST_DIAL_RESULT_ANSWERED
Definition: dial.h:61
@ AST_DIAL_RESULT_TIMEOUT
Definition: dial.h:62
@ AST_DIAL_RESULT_TRYING
Definition: dial.h:57
@ AST_DIAL_RESULT_PROGRESS
Definition: dial.h:59
@ AST_DIAL_RESULT_RINGING
Definition: dial.h:58
@ AST_DIAL_RESULT_PROCEEDING
Definition: dial.h:60
@ AST_DIAL_RESULT_UNANSWERED
Definition: dial.h:64
int ast_dial_append(struct ast_dial *dial, const char *tech, const char *device, const struct ast_assigned_ids *assignedids)
Append a channel.
Definition: dial.c:280
struct ast_dial * ast_dial_create(void)
New dialing structure.
Definition: dial.c:223
struct ast_channel * ast_dial_answered(struct ast_dial *dial)
Return channel that answered.
Definition: dial.c:977
enum ast_dial_result ast_dial_run(struct ast_dial *dial, struct ast_channel *chan, int async)
Execute dialing synchronously or asynchronously.
Definition: dial.c:935
enum ast_dial_result ast_dial_join(struct ast_dial *dial)
Cancel async thread.
Definition: dial.c:1017
int ast_dial_destroy(struct ast_dial *dial)
Destroys a dialing structure.
Definition: dial.c:1091
#define ast_frfree(fr)
@ AST_CONTROL_PROGRESS
@ AST_CONTROL_RINGING
#define ast_mutex_unlock(a)
Definition: lock.h:197
#define ast_mutex_lock(a)
Definition: lock.h:196
#define ast_cond_signal(cond)
Definition: lock.h:210
Main dialing structure. Contains global options, channels being dialed, and more!
Definition: dial.c:48
Structure used to handle boolean flags.
Definition: utils.h:199
Data structure associated with a single frame of data.
Caller Party information.
Definition: channel.h:420
int done
Definition: test_amihooks.c:48
const char * args
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:941
#define ast_set_flag(p, flag)
Definition: utils.h:70

References ALL_TRUNK_REFS, ao2_cleanup, args, ast_channel_caller(), ast_channel_caller_set(), ast_channel_name(), ast_cond_signal, AST_CONTROL_PROGRESS, AST_CONTROL_RINGING, ast_debug, AST_DEVICE_NOT_INUSE, ast_dial_answered(), ast_dial_append(), ast_dial_create(), ast_dial_destroy(), ast_dial_join(), AST_DIAL_RESULT_ANSWERED, AST_DIAL_RESULT_FAILED, AST_DIAL_RESULT_HANGUP, AST_DIAL_RESULT_INVALID, AST_DIAL_RESULT_PROCEEDING, AST_DIAL_RESULT_PROGRESS, AST_DIAL_RESULT_RINGING, AST_DIAL_RESULT_TIMEOUT, AST_DIAL_RESULT_TRYING, AST_DIAL_RESULT_UNANSWERED, ast_dial_run(), ast_dial_state(), ast_frfree, ast_indicate(), ast_mutex_lock, ast_mutex_unlock, ast_party_caller_free(), ast_party_caller_init(), ast_read(), ast_set_flag, ast_strdupa, ast_waitfor(), conf_run(), CONFFLAG_MARKEDEXIT, CONFFLAG_MARKEDUSER, CONFFLAG_PASS_DTMF, CONFFLAG_QUIET, CONFFLAG_SLA_TRUNK, done, MAX_CONFNUM, NULL, RAII_VAR, sla, sla_change_trunk_state(), SLA_TRUNK_STATE_IDLE, and strsep().

Referenced by sla_station_exec().

◆ load_config()

static int load_config ( int  reload)
static

Definition at line 2825 of file app_sla.c.

2826{
2827 return sla_load_config(reload);
2828}
static int sla_load_config(int reload)
Definition: app_sla.c:2759
static int reload(void)
Definition: app_sla.c:2870

References reload(), and sla_load_config().

Referenced by load_module(), and reload().

◆ load_module()

static int load_module ( void  )
static

Load the module.

Module loading including tests for configuration or dependencies. This function can return AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_DECLINE, or AST_MODULE_LOAD_SUCCESS. If a dependency or environment variable fails tests return AST_MODULE_LOAD_FAILURE. If the module can not load the configuration file or other non-critical problem return AST_MODULE_LOAD_DECLINE. On success return AST_MODULE_LOAD_SUCCESS.

Definition at line 2855 of file app_sla.c.

2856{
2857 int res = 0;
2858
2859 res |= load_config(0);
2860
2864
2865 res |= ast_devstate_prov_add("SLA", sla_state);
2866
2867 return res;
2868}
static const char *const slatrunk_app
Definition: app_sla.c:134
static struct ast_cli_entry cli_sla[]
Definition: app_sla.c:520
static const char *const slastation_app
Definition: app_sla.c:133
static int sla_trunk_exec(struct ast_channel *chan, const char *data)
Definition: app_sla.c:2159
static enum ast_device_state sla_state(const char *data)
Definition: app_sla.c:2250
static int sla_station_exec(struct ast_channel *chan, const char *data)
Definition: app_sla.c:1955
static int load_config(int reload)
Definition: app_sla.c:2825
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition: cli.h:265
int ast_devstate_prov_add(const char *label, ast_devstate_prov_cb_type callback)
Add device state provider.
Definition: devicestate.c:394
#define ast_register_application_xml(app, execute)
Register an application using XML documentation.
Definition: module.h:640
#define ARRAY_LEN(a)
Definition: utils.h:666

References ARRAY_LEN, ast_cli_register_multiple, ast_devstate_prov_add(), ast_register_application_xml, cli_sla, load_config(), sla_state(), sla_station_exec(), sla_trunk_exec(), slastation_app, and slatrunk_app.

◆ queue_ringing_trunk()

static struct sla_ringing_trunk * queue_ringing_trunk ( struct sla_trunk trunk)
static

Definition at line 2126 of file app_sla.c.

2127{
2128 struct sla_ringing_trunk *ringing_trunk;
2129
2130 if (!(ringing_trunk = ast_calloc(1, sizeof(*ringing_trunk)))) {
2131 return NULL;
2132 }
2133
2134 ao2_ref(trunk, 1);
2135 ringing_trunk->trunk = trunk;
2136 ringing_trunk->ring_begin = ast_tvnow();
2137
2139
2140 ast_mutex_lock(&sla.lock);
2141 AST_LIST_INSERT_HEAD(&sla.ringing_trunks, ringing_trunk, entry);
2142 ast_mutex_unlock(&sla.lock);
2143
2145
2146 return ringing_trunk;
2147}
static void sla_queue_event(enum sla_event_type type)
Definition: app_sla.c:561
#define AST_LIST_INSERT_HEAD(head, elm, field)
Inserts a list entry at the head of a list.
Definition: linkedlists.h:711
A trunk that is ringing.
Definition: app_sla.c:309
struct timeval ring_begin
Definition: app_sla.c:312
struct sla_ringing_trunk::@73 entry
struct sla_trunk * trunk
Definition: app_sla.c:310
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:159

References ALL_TRUNK_REFS, ao2_ref, ast_calloc, AST_LIST_INSERT_HEAD, ast_mutex_lock, ast_mutex_unlock, ast_tvnow(), sla_ringing_trunk::entry, NULL, sla_ringing_trunk::ring_begin, sla, sla_change_trunk_state(), SLA_EVENT_RINGING_TRUNK, sla_queue_event(), SLA_TRUNK_STATE_RINGING, and sla_ringing_trunk::trunk.

Referenced by sla_trunk_exec().

◆ reload()

static int reload ( void  )
static

Definition at line 2870 of file app_sla.c.

2871{
2872 return load_config(1);
2873}

References load_config().

Referenced by load_config(), and sla_load_config().

◆ remove_framehook()

static int remove_framehook ( struct ast_channel chan)
static

Definition at line 620 of file app_sla.c.

621{
622 struct ast_datastore *datastore = NULL;
623 struct sla_framehook_data *data;
624 SCOPED_CHANNELLOCK(chan_lock, chan);
625
627 if (!datastore) {
628 ast_log(AST_LOG_WARNING, "Cannot remove framehook from %s: HOLD_INTERCEPT not currently enabled\n", ast_channel_name(chan));
629 return -1;
630 }
631 data = datastore->data;
632
633 ast_free(data->confname);
634
635 if (ast_framehook_detach(chan, data->framehook_id)) {
636 ast_log(AST_LOG_WARNING, "Failed to remove framehook from channel %s\n", ast_channel_name(chan));
637 return -1;
638 }
639 if (ast_channel_datastore_remove(chan, datastore)) {
640 ast_log(AST_LOG_WARNING, "Failed to remove datastore from channel %s\n", ast_channel_name(chan));
641 return -1;
642 }
643 ast_datastore_free(datastore);
644
645 return 0;
646}
int ast_channel_datastore_remove(struct ast_channel *chan, struct ast_datastore *datastore)
Remove a datastore from a channel.
Definition: channel.c:2363
int ast_framehook_detach(struct ast_channel *chan, int framehook_id)
Detach an framehook from a channel.
Definition: framehook.c:177

References ast_channel_datastore_find(), ast_channel_datastore_remove(), ast_channel_name(), ast_datastore_free(), ast_framehook_detach(), ast_free, ast_log, AST_LOG_WARNING, sla_framehook_data::confname, ast_datastore::data, sla_framehook_data::framehook_id, NULL, SCOPED_CHANNELLOCK, and sla_framehook_datastore.

Referenced by conf_run().

◆ run_station()

static void * run_station ( void *  data)
static

Definition at line 981 of file app_sla.c.

982{
983 RAII_VAR(struct sla_station *, station, NULL, ao2_cleanup);
984 RAII_VAR(struct sla_trunk_ref *, trunk_ref, NULL, ao2_cleanup);
985 struct ast_str *conf_name = ast_str_create(16);
986 struct ast_flags conf_flags = { 0 };
987
988 {
989 struct run_station_args *args = data;
990 station = args->station;
991 trunk_ref = args->trunk_ref;
992 ast_mutex_lock(args->cond_lock);
993 ast_cond_signal(args->cond);
994 ast_mutex_unlock(args->cond_lock);
995 /* args is no longer valid here. */
996 }
997
999 ast_str_set(&conf_name, 0, "SLA_%s", trunk_ref->trunk->name);
1002
1003 ast_debug(2, "Station %s joining conference %s\n", station->name, ast_str_buffer(conf_name));
1004 conf_run(trunk_ref->chan, ast_str_buffer(conf_name), &conf_flags, NULL);
1005
1006 trunk_ref->chan = NULL;
1009 conf_kick_all(NULL, ast_str_buffer(conf_name));
1012 }
1013
1016 station->dial = NULL;
1017 ast_free(conf_name);
1018
1019 return NULL;
1020}
static int conf_kick_all(struct ast_channel *chan, const char *confname)
Definition: app_sla.c:958
static void answer_trunk_chan(struct ast_channel *chan)
Definition: app_sla.c:917
int ast_atomic_fetchadd_int(volatile int *p, int v)
Atomically add v to *p and return the previous value of *p.
Definition: lock.h:764
int ast_atomic_dec_and_test(volatile int *p)
decrement *p by 1 and return true if the variable has reached 0.
Definition: lock.h:774
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:761
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
Definition: strings.h:659
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
Definition: strings.h:1113
Support for dynamic strings.
Definition: strings.h:623
struct sla_station * station
Definition: app_sla.c:911
struct sla_trunk_ref * trunk_ref
Definition: app_sla.c:912
struct ast_dial * dial
Definition: app_sla.c:196
enum sla_trunk_state state
Definition: app_sla.c:264
struct ast_channel * chan
Definition: app_sla.c:265
unsigned int hold_stations
Definition: app_sla.c:239
unsigned int active_stations
Definition: app_sla.c:237
const ast_string_field name
Definition: app_sla.c:232

References sla_trunk::active_stations, ALL_TRUNK_REFS, answer_trunk_chan(), ao2_cleanup, args, ast_atomic_dec_and_test(), ast_atomic_fetchadd_int(), ast_cond_signal, ast_debug, ast_dial_destroy(), ast_dial_join(), ast_free, ast_mutex_lock, ast_mutex_unlock, ast_set_flag, ast_str_buffer(), ast_str_create, ast_str_set(), sla_trunk_ref::chan, conf_kick_all(), conf_run(), CONFFLAG_MARKEDEXIT, CONFFLAG_PASS_DTMF, CONFFLAG_QUIET, CONFFLAG_SLA_STATION, sla_station::dial, sla_trunk::hold_stations, sla_trunk::name, NULL, RAII_VAR, sla_change_trunk_state(), SLA_TRUNK_STATE_IDLE, SLA_TRUNK_STATE_ONHOLD_BYME, sla_trunk_ref::state, run_station_args::station, sla_trunk_ref::trunk, and run_station_args::trunk_ref.

Referenced by sla_handle_dial_state_event().

◆ sla_add_trunk_to_station()

static void sla_add_trunk_to_station ( struct sla_station station,
struct ast_variable var 
)
static

Definition at line 2478 of file app_sla.c.

2479{
2480 RAII_VAR(struct sla_trunk *, trunk, NULL, ao2_cleanup);
2481 struct sla_trunk_ref *trunk_ref = NULL;
2482 struct sla_station_ref *station_ref;
2483 char *trunk_name, *options, *cur;
2484 int existing_trunk_ref = 0;
2485 int existing_station_ref = 0;
2486
2487 options = ast_strdupa(var->value);
2488 trunk_name = strsep(&options, ",");
2489
2490 trunk = sla_find_trunk(trunk_name);
2491 if (!trunk) {
2492 ast_log(LOG_ERROR, "Trunk '%s' not found!\n", var->value);
2493 return;
2494 }
2495
2496 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) {
2497 if (trunk_ref->trunk == trunk) {
2498 trunk_ref->mark = 0;
2499 existing_trunk_ref = 1;
2500 break;
2501 }
2502 }
2503
2504 if (!trunk_ref && !(trunk_ref = create_trunk_ref(trunk))) {
2505 return;
2506 }
2507
2508 trunk_ref->state = SLA_TRUNK_STATE_IDLE;
2509
2510 while ((cur = strsep(&options, ","))) {
2511 char *name, *value = cur;
2512 name = strsep(&value, "=");
2513 if (!strcasecmp(name, "ringtimeout")) {
2514 if (sscanf(value, "%30u", &trunk_ref->ring_timeout) != 1) {
2515 ast_log(LOG_WARNING, "Invalid ringtimeout value '%s' for trunk '%s' on station '%s'\n", value, trunk->name, station->name);
2516 trunk_ref->ring_timeout = 0;
2517 }
2518 } else if (!strcasecmp(name, "ringdelay")) {
2519 if (sscanf(value, "%30u", &trunk_ref->ring_delay) != 1) {
2520 ast_log(LOG_WARNING, "Invalid ringdelay value '%s' for trunk '%s' on station '%s'\n", value, trunk->name, station->name);
2521 trunk_ref->ring_delay = 0;
2522 }
2523 } else {
2524 ast_log(LOG_WARNING, "Invalid option '%s' for trunk '%s' on station '%s'\n", name, trunk->name, station->name);
2525 }
2526 }
2527
2528 AST_LIST_TRAVERSE(&trunk->stations, station_ref, entry) {
2529 if (station_ref->station == station) {
2530 station_ref->mark = 0;
2531 existing_station_ref = 1;
2532 break;
2533 }
2534 }
2535
2536 if (!station_ref && !(station_ref = sla_create_station_ref(station))) {
2537 if (!existing_trunk_ref) {
2538 ao2_ref(trunk_ref, -1);
2539 } else {
2540 trunk_ref->mark = 1;
2541 }
2542 return;
2543 }
2544
2545 if (!existing_station_ref) {
2546 ao2_lock(trunk);
2547 AST_LIST_INSERT_TAIL(&trunk->stations, station_ref, entry);
2548 ast_atomic_fetchadd_int((int *) &trunk->num_stations, 1);
2549 ao2_unlock(trunk);
2550 }
2551
2552 if (!existing_trunk_ref) {
2556 }
2557}
static struct sla_station_ref * sla_create_station_ref(struct sla_station *station)
Definition: app_sla.c:805
static struct sla_trunk_ref * create_trunk_ref(struct sla_trunk *trunk)
Definition: app_sla.c:2112
static struct sla_trunk * sla_find_trunk(const char *name)
Definition: app_sla.c:713
#define var
Definition: ast_expr2f.c:605
#define ao2_unlock(a)
Definition: astobj2.h:729
#define ao2_lock(a)
Definition: astobj2.h:717
static const char name[]
Definition: format_mp3.c:68
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:491
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:731
A reference to a station.
Definition: app_sla.c:220
struct sla_station * station
Definition: app_sla.c:222
struct sla_station_ref::@67 entry
unsigned int mark
Definition: app_sla.c:224
unsigned int ring_timeout
Definition: app_sla.c:269
unsigned int ring_delay
Definition: app_sla.c:273
unsigned int mark
Definition: app_sla.c:275
int value
Definition: syslog.c:37
static struct test_options options

References ao2_cleanup, ao2_lock, ao2_ref, ao2_unlock, ast_atomic_fetchadd_int(), AST_LIST_INSERT_TAIL, AST_LIST_TRAVERSE, ast_log, ast_strdupa, create_trunk_ref(), sla_station_ref::entry, LOG_ERROR, LOG_WARNING, sla_station_ref::mark, sla_trunk_ref::mark, name, NULL, options, RAII_VAR, sla_trunk_ref::ring_delay, sla_trunk_ref::ring_timeout, sla_create_station_ref(), sla_find_trunk(), SLA_TRUNK_STATE_IDLE, sla_trunk_ref::state, sla_station_ref::station, strsep(), sla_trunk_ref::trunk, sla_station::trunks, value, and var.

Referenced by sla_build_station().

◆ sla_build_station()

static int sla_build_station ( struct ast_config cfg,
const char *  cat 
)
static

Definition at line 2559 of file app_sla.c.

2560{
2561 RAII_VAR(struct sla_station *, station, NULL, ao2_cleanup);
2562 struct ast_variable *var;
2563 const char *dev;
2564 int existing_station = 0;
2565
2566 if (!(dev = ast_variable_retrieve(cfg, cat, "device"))) {
2567 ast_log(LOG_ERROR, "SLA Station '%s' defined with no device!\n", cat);
2568 return -1;
2569 }
2570
2571 if ((station = sla_find_station(cat))) {
2572 station->mark = 0;
2573 existing_station = 1;
2574 } else if ((station = ao2_alloc(sizeof(*station), sla_station_destructor))) {
2575 if (ast_string_field_init(station, 32)) {
2576 return -1;
2577 }
2578 ast_string_field_set(station, name, cat);
2579 } else {
2580 return -1;
2581 }
2582
2583 ao2_lock(station);
2584
2585 ast_string_field_set(station, device, dev);
2586
2587 for (var = ast_variable_browse(cfg, cat); var; var = var->next) {
2588 if (!strcasecmp(var->name, "trunk")) {
2589 ao2_unlock(station);
2590 sla_add_trunk_to_station(station, var);
2591 ao2_lock(station);
2592 } else if (!strcasecmp(var->name, "autocontext")) {
2593 ast_string_field_set(station, autocontext, var->value);
2594 } else if (!strcasecmp(var->name, "ringtimeout")) {
2595 if (sscanf(var->value, "%30u", &station->ring_timeout) != 1) {
2596 ast_log(LOG_WARNING, "Invalid ringtimeout '%s' specified for station '%s'\n", var->value, station->name);
2597 station->ring_timeout = 0;
2598 }
2599 } else if (!strcasecmp(var->name, "ringdelay")) {
2600 if (sscanf(var->value, "%30u", &station->ring_delay) != 1) {
2601 ast_log(LOG_WARNING, "Invalid ringdelay '%s' specified for station '%s'\n", var->value, station->name);
2602 station->ring_delay = 0;
2603 }
2604 } else if (!strcasecmp(var->name, "hold")) {
2605 if (!strcasecmp(var->value, "private")) {
2606 station->hold_access = SLA_HOLD_PRIVATE;
2607 } else if (!strcasecmp(var->value, "open")) {
2608 station->hold_access = SLA_HOLD_OPEN;
2609 } else {
2610 ast_log(LOG_WARNING, "Invalid value '%s' for hold on station %s\n", var->value, station->name);
2611 }
2612 } else if (strcasecmp(var->name, "type") && strcasecmp(var->name, "device")) {
2613 ast_log(LOG_ERROR, "Invalid option '%s' specified at line %d of %s!\n", var->name, var->lineno, SLA_CONFIG_FILE);
2614 }
2615 }
2616
2617 ao2_unlock(station);
2618
2619 if (!ast_strlen_zero(station->autocontext)) {
2620 struct sla_trunk_ref *trunk_ref;
2621
2622 if (!ast_context_find_or_create(NULL, NULL, station->autocontext, sla_registrar)) {
2623 ast_log(LOG_ERROR, "Failed to automatically find or create context '%s' for SLA!\n", station->autocontext);
2624 return -1;
2625 }
2626 /* The extension for when the handset goes off-hook.
2627 * exten => station1,1,SLAStation(station1) */
2628 if (ast_add_extension(station->autocontext, 0 /* don't replace */, station->name, 1,
2630 ast_log(LOG_ERROR, "Failed to automatically create extension for trunk '%s'!\n", station->name);
2631 return -1;
2632 }
2633 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) {
2634 char exten[AST_MAX_EXTENSION];
2635 char hint[AST_MAX_EXTENSION + 5];
2636 snprintf(exten, sizeof(exten), "%s_%s", station->name, trunk_ref->trunk->name);
2637 snprintf(hint, sizeof(hint), "SLA:%s", exten);
2638 /* Extension for this line button
2639 * exten => station1_line1,1,SLAStation(station1_line1) */
2640 if (ast_add_extension(station->autocontext, 0 /* don't replace */, exten, 1,
2642 ast_log(LOG_ERROR, "Failed to automatically create extension for trunk '%s'!\n", station->name);
2643 return -1;
2644 }
2645 /* Hint for this line button
2646 * exten => station1_line1,hint,SLA:station1_line1 */
2647 if (ast_add_extension(station->autocontext, 0 /* don't replace */, exten, PRIORITY_HINT,
2648 NULL, NULL, hint, NULL, NULL, sla_registrar)) {
2649 ast_log(LOG_ERROR, "Failed to automatically create hint for trunk '%s'!\n", station->name);
2650 return -1;
2651 }
2652 }
2653 }
2654
2655 if (!existing_station) {
2656 ao2_link(sla_stations, station);
2657 }
2658
2659 return 0;
2660}
static struct ao2_container * sla_stations
Definition: app_sla.c:278
static void sla_add_trunk_to_station(struct sla_station *station, struct ast_variable *var)
Definition: app_sla.c:2478
#define SLA_CONFIG_FILE
Definition: app_sla.c:130
static struct sla_station * sla_find_station(const char *name)
Definition: app_sla.c:726
static void sla_station_destructor(void *obj)
Definition: app_sla.c:2303
static const char sla_registrar[]
Definition: app_sla.c:281
void ast_free_ptr(void *ptr)
free() wrapper
Definition: astmm.c:1739
#define ao2_link(container, obj)
Add an object to a container.
Definition: astobj2.h:1532
#define AST_MAX_EXTENSION
Definition: channel.h:134
const char * ast_variable_retrieve(struct ast_config *config, const char *category, const char *variable)
Definition: main/config.c:869
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category_name)
Definition: extconf.c:1215
int ast_add_extension(const char *context, int replace, const char *extension, int priority, const char *label, const char *callerid, const char *application, void *data, void(*datad)(void *), const char *registrar)
Add and extension to an extension context.
Definition: pbx.c:6943
struct ast_context * ast_context_find_or_create(struct ast_context **extcontexts, struct ast_hashtab *exttable, const char *name, const char *registrar)
Register a new context or find an existing one.
Definition: pbx.c:6164
#define PRIORITY_HINT
Definition: pbx.h:54
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:521
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
Definition: stringfields.h:359
Structure for variables, used for configurations and for channel variables.
struct sla_trunk_ref::@69 entry

References ao2_alloc, ao2_cleanup, ao2_link, ao2_lock, ao2_unlock, ast_add_extension(), ast_context_find_or_create(), ast_free_ptr(), AST_LIST_TRAVERSE, ast_log, AST_MAX_EXTENSION, ast_strdup, ast_string_field_init, ast_string_field_set, ast_strlen_zero(), ast_variable_browse(), ast_variable_retrieve(), sla_trunk_ref::entry, LOG_ERROR, LOG_WARNING, name, sla_trunk::name, NULL, PRIORITY_HINT, RAII_VAR, sla_add_trunk_to_station(), SLA_CONFIG_FILE, sla_find_station(), SLA_HOLD_OPEN, SLA_HOLD_PRIVATE, sla_registrar, sla_station_destructor(), sla_stations, slastation_app, sla_station_ref::station, sla_trunk_ref::trunk, and var.

Referenced by sla_load_config().

◆ sla_build_trunk()

static int sla_build_trunk ( struct ast_config cfg,
const char *  cat 
)
static

Definition at line 2396 of file app_sla.c.

2397{
2398 RAII_VAR(struct sla_trunk *, trunk, NULL, ao2_cleanup);
2399 struct ast_variable *var;
2400 const char *dev;
2401 int existing_trunk = 0;
2402
2403 if (!(dev = ast_variable_retrieve(cfg, cat, "device"))) {
2404 ast_log(LOG_ERROR, "SLA Trunk '%s' defined with no device!\n", cat);
2405 return -1;
2406 }
2407
2408 if (sla_check_device(dev)) {
2409 ast_log(LOG_ERROR, "SLA Trunk '%s' defined with invalid device '%s'!\n", cat, dev);
2410 return -1;
2411 }
2412
2413 if ((trunk = sla_find_trunk(cat))) {
2414 trunk->mark = 0;
2415 existing_trunk = 1;
2416 } else if ((trunk = ao2_alloc(sizeof(*trunk), sla_trunk_destructor))) {
2417 if (ast_string_field_init(trunk, 32)) {
2418 return -1;
2419 }
2420 ast_string_field_set(trunk, name, cat);
2421 } else {
2422 return -1;
2423 }
2424
2425 ao2_lock(trunk);
2426
2427 ast_string_field_set(trunk, device, dev);
2428
2429 for (var = ast_variable_browse(cfg, cat); var; var = var->next) {
2430 if (!strcasecmp(var->name, "autocontext")) {
2431 ast_string_field_set(trunk, autocontext, var->value);
2432 } else if (!strcasecmp(var->name, "ringtimeout")) {
2433 if (sscanf(var->value, "%30u", &trunk->ring_timeout) != 1) {
2434 ast_log(LOG_WARNING, "Invalid ringtimeout '%s' specified for trunk '%s'\n", var->value, trunk->name);
2435 trunk->ring_timeout = 0;
2436 }
2437 } else if (!strcasecmp(var->name, "barge")) {
2438 trunk->barge_disabled = ast_false(var->value);
2439 } else if (!strcasecmp(var->name, "hold")) {
2440 if (!strcasecmp(var->value, "private")) {
2441 trunk->hold_access = SLA_HOLD_PRIVATE;
2442 } else if (!strcasecmp(var->value, "open")) {
2443 trunk->hold_access = SLA_HOLD_OPEN;
2444 } else {
2445 ast_log(LOG_WARNING, "Invalid value '%s' for hold on trunk %s\n", var->value, trunk->name);
2446 }
2447 } else if (strcasecmp(var->name, "type") && strcasecmp(var->name, "device")) {
2448 ast_log(LOG_ERROR, "Invalid option '%s' specified at line %d of %s!\n", var->name, var->lineno, SLA_CONFIG_FILE);
2449 }
2450 }
2451
2452 ao2_unlock(trunk);
2453
2454 if (!ast_strlen_zero(trunk->autocontext)) {
2455 if (!ast_context_find_or_create(NULL, NULL, trunk->autocontext, sla_registrar)) {
2456 ast_log(LOG_ERROR, "Failed to automatically find or create context '%s' for SLA!\n", trunk->autocontext);
2457 return -1;
2458 }
2459
2460 if (ast_add_extension(trunk->autocontext, 0 /* don't replace */, "s", 1,
2462 ast_log(LOG_ERROR, "Failed to automatically create extension for trunk '%s'!\n", trunk->name);
2463 return -1;
2464 }
2465 }
2466
2467 if (!existing_trunk) {
2468 ao2_link(sla_trunks, trunk);
2469 }
2470
2471 return 0;
2472}
static int sla_check_device(const char *device)
Definition: app_sla.c:2367
static void sla_trunk_destructor(void *obj)
Definition: app_sla.c:2381
static struct ao2_container * sla_trunks
Definition: app_sla.c:279
int attribute_pure ast_false(const char *val)
Make sure something is false. Determine if a string containing a boolean value is "false"....
Definition: utils.c:2216

References ao2_alloc, ao2_cleanup, ao2_link, ao2_lock, ao2_unlock, ast_add_extension(), ast_context_find_or_create(), ast_false(), ast_free_ptr(), ast_log, ast_strdup, ast_string_field_init, ast_string_field_set, ast_strlen_zero(), ast_variable_browse(), ast_variable_retrieve(), LOG_ERROR, LOG_WARNING, name, NULL, RAII_VAR, sla_check_device(), SLA_CONFIG_FILE, sla_find_trunk(), SLA_HOLD_OPEN, SLA_HOLD_PRIVATE, sla_registrar, sla_trunk_destructor(), sla_trunks, slatrunk_app, and var.

Referenced by sla_load_config().

◆ sla_calc_station_delays()

static int sla_calc_station_delays ( unsigned int *  timeout)
static

Calculate the ring delay for a station.

Note
Assumes sla.lock is locked

Definition at line 1631 of file app_sla.c.

1632{
1633 struct sla_station *station;
1634 int res = 0;
1635 struct ao2_iterator i;
1636
1638 for (; (station = ao2_iterator_next(&i)); ao2_ref(station, -1)) {
1639 struct sla_ringing_trunk *ringing_trunk;
1640 int time_left;
1641
1642 /* Ignore stations already ringing */
1643 if (sla_check_ringing_station(station)) {
1644 continue;
1645 }
1646
1647 /* Ignore stations already on a call */
1648 if (sla_check_inuse_station(station)) {
1649 continue;
1650 }
1651
1652 /* Ignore stations that don't have one of their trunks ringing */
1653 if (!(ringing_trunk = sla_choose_ringing_trunk(station, NULL, 0))) {
1654 continue;
1655 }
1656
1657 if ((time_left = sla_check_station_delay(station, ringing_trunk)) == INT_MAX) {
1658 continue;
1659 }
1660
1661 /* If there is no time left, then the station needs to start ringing.
1662 * Return non-zero so that an event will be queued up an event to
1663 * make that happen. */
1664 if (time_left <= 0) {
1665 res = 1;
1666 continue;
1667 }
1668
1669 if (time_left < *timeout) {
1670 *timeout = time_left;
1671 }
1672 }
1674
1675 return res;
1676}
static int sla_check_inuse_station(const struct sla_station *station)
Check to see if a station is in use.
Definition: app_sla.c:1330
static struct sla_ringing_trunk * sla_choose_ringing_trunk(struct sla_station *station, struct sla_trunk_ref **trunk_ref, int rm)
Choose the highest priority ringing trunk for a station.
Definition: app_sla.c:1105
static int sla_check_station_delay(struct sla_station *station, struct sla_ringing_trunk *ringing_trunk)
Calculate the ring delay for a given ringing trunk on a station.
Definition: app_sla.c:1363
static int sla_check_ringing_station(const struct sla_station *station)
Check to see if this station is already ringing.
Definition: app_sla.c:1229
#define ao2_iterator_next(iter)
Definition: astobj2.h:1911
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1821

References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_ref, NULL, sla_check_inuse_station(), sla_check_ringing_station(), sla_check_station_delay(), sla_choose_ringing_trunk(), and sla_stations.

Referenced by sla_process_timers().

◆ sla_calc_station_timeouts()

static int sla_calc_station_timeouts ( unsigned int *  timeout)
static

Process station ring timeouts.

Note
Called with sla.lock locked
Returns
non-zero if a change to the ringing stations was made

Definition at line 1539 of file app_sla.c.

1540{
1541 struct sla_ringing_trunk *ringing_trunk;
1542 struct sla_ringing_station *ringing_station;
1543 int res = 0;
1544
1545 AST_LIST_TRAVERSE_SAFE_BEGIN(&sla.ringing_stations, ringing_station, entry) {
1546 unsigned int ring_timeout = 0;
1547 int time_elapsed, time_left = INT_MAX, final_trunk_time_left = INT_MIN;
1548 struct sla_trunk_ref *trunk_ref;
1549
1550 /* If there are any ring timeouts specified for a specific trunk
1551 * on the station, then use the highest per-trunk ring timeout.
1552 * Otherwise, use the ring timeout set for the entire station. */
1553 AST_LIST_TRAVERSE(&ringing_station->station->trunks, trunk_ref, entry) {
1554 struct sla_station_ref *station_ref;
1555 int trunk_time_elapsed, trunk_time_left;
1556
1557 AST_LIST_TRAVERSE(&sla.ringing_trunks, ringing_trunk, entry) {
1558 if (ringing_trunk->trunk == trunk_ref->trunk) {
1559 break;
1560 }
1561 }
1562 if (!ringing_trunk) {
1563 continue;
1564 }
1565
1566 /* If there is a trunk that is ringing without a timeout, then the
1567 * only timeout that could matter is a global station ring timeout. */
1568 if (!trunk_ref->ring_timeout) {
1569 break;
1570 }
1571
1572 /* This trunk on this station is ringing and has a timeout.
1573 * However, make sure this trunk isn't still ringing from a
1574 * previous timeout. If so, don't consider it. */
1575 AST_LIST_TRAVERSE(&ringing_trunk->timed_out_stations, station_ref, entry) {
1576 if (station_ref->station == ringing_station->station) {
1577 break;
1578 }
1579 }
1580 if (station_ref) {
1581 continue;
1582 }
1583
1584 trunk_time_elapsed = ast_tvdiff_ms(ast_tvnow(), ringing_trunk->ring_begin);
1585 trunk_time_left = (trunk_ref->ring_timeout * 1000) - trunk_time_elapsed;
1586 if (trunk_time_left > final_trunk_time_left) {
1587 final_trunk_time_left = trunk_time_left;
1588 }
1589 }
1590
1591 /* No timeout was found for ringing trunks, and no timeout for the entire station */
1592 if (final_trunk_time_left == INT_MIN && !ringing_station->station->ring_timeout) {
1593 continue;
1594 }
1595
1596 /* Compute how much time is left for a global station timeout */
1597 if (ringing_station->station->ring_timeout) {
1598 ring_timeout = ringing_station->station->ring_timeout;
1599 time_elapsed = ast_tvdiff_ms(ast_tvnow(), ringing_station->ring_begin);
1600 time_left = (ring_timeout * 1000) - time_elapsed;
1601 }
1602
1603 /* If the time left based on the per-trunk timeouts is smaller than the
1604 * global station ring timeout, use that. */
1605 if (final_trunk_time_left > INT_MIN && final_trunk_time_left < time_left) {
1606 time_left = final_trunk_time_left;
1607 }
1608
1609 /* If there is no time left, the station needs to stop ringing */
1610 if (time_left <= 0) {
1613 res = 1;
1614 continue;
1615 }
1616
1617 /* There is still some time left for this station to ring, so save that
1618 * timeout if it is the first event scheduled to occur */
1619 if (time_left < *timeout) {
1620 *timeout = time_left;
1621 }
1622 }
1624
1625 return res;
1626}
static void sla_stop_ringing_station(struct sla_ringing_station *ringing_station, enum sla_station_hangup hangup)
Definition: app_sla.c:1038
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
Definition: linkedlists.h:615
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
Definition: linkedlists.h:529
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
Definition: linkedlists.h:557
A station that is ringing.
Definition: app_sla.c:323
struct sla_station * station
Definition: app_sla.c:324
struct timeval ring_begin
Definition: app_sla.c:326
struct sla_ringing_station::@74 entry
struct sla_ringing_trunk::@72 timed_out_stations
unsigned int ring_timeout
Definition: app_sla.c:200
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
Definition: time.h:107

References AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_tvdiff_ms(), ast_tvnow(), sla_station_ref::entry, sla_trunk_ref::entry, sla_ringing_station::entry, sla_ringing_trunk::ring_begin, sla_ringing_station::ring_begin, sla_station::ring_timeout, sla_trunk_ref::ring_timeout, sla, SLA_STATION_HANGUP_TIMEOUT, sla_stop_ringing_station(), sla_station_ref::station, sla_ringing_station::station, sla_ringing_trunk::timed_out_stations, sla_trunk_ref::trunk, sla_ringing_trunk::trunk, and sla_station::trunks.

Referenced by sla_process_timers().

◆ sla_calc_trunk_timeouts()

static int sla_calc_trunk_timeouts ( unsigned int *  timeout)
static

Process trunk ring timeouts.

Note
Called with sla.lock locked
Returns
non-zero if a change to the ringing trunks was made

Definition at line 1507 of file app_sla.c.

1508{
1509 struct sla_ringing_trunk *ringing_trunk;
1510 int res = 0;
1511
1512 AST_LIST_TRAVERSE_SAFE_BEGIN(&sla.ringing_trunks, ringing_trunk, entry) {
1513 int time_left, time_elapsed;
1514 if (!ringing_trunk->trunk->ring_timeout) {
1515 continue;
1516 }
1517 time_elapsed = ast_tvdiff_ms(ast_tvnow(), ringing_trunk->ring_begin);
1518 time_left = (ringing_trunk->trunk->ring_timeout * 1000) - time_elapsed;
1519 if (time_left <= 0) {
1520 pbx_builtin_setvar_helper(ringing_trunk->trunk->chan, "SLATRUNK_STATUS", "RINGTIMEOUT");
1522 sla_stop_ringing_trunk(ringing_trunk);
1523 res = 1;
1524 continue;
1525 }
1526 if (time_left < *timeout) {
1527 *timeout = time_left;
1528 }
1529 }
1531
1532 return res;
1533}
static void sla_stop_ringing_trunk(struct sla_ringing_trunk *ringing_trunk)
Definition: app_sla.c:1024
int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, removing the most recently set value for the same name.
unsigned int ring_timeout
Definition: app_sla.c:241
struct ast_channel * chan
Definition: app_sla.c:240

References AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_tvdiff_ms(), ast_tvnow(), sla_trunk::chan, sla_ringing_trunk::entry, pbx_builtin_setvar_helper(), sla_ringing_trunk::ring_begin, sla_trunk::ring_timeout, sla, sla_stop_ringing_trunk(), and sla_ringing_trunk::trunk.

Referenced by sla_process_timers().

◆ sla_change_trunk_state()

static void sla_change_trunk_state ( const struct sla_trunk trunk,
enum sla_trunk_state  state,
enum sla_which_trunk_refs  inactive_only,
const struct sla_trunk_ref exclude 
)
static

Definition at line 886 of file app_sla.c.

888{
889 struct sla_station *station;
890 struct sla_trunk_ref *trunk_ref;
891 struct ao2_iterator i;
892
894 while ((station = ao2_iterator_next(&i))) {
895 ao2_lock(station);
896 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) {
897 if (trunk_ref->trunk != trunk || (inactive_only ? trunk_ref->chan : 0) || trunk_ref == exclude) {
898 continue;
899 }
900 trunk_ref->state = state;
901 ast_devstate_changed(sla_state_to_devstate(state), AST_DEVSTATE_CACHABLE, "SLA:%s_%s", station->name, trunk->name);
902 break;
903 }
904 ao2_unlock(station);
905 ao2_ref(station, -1);
906 }
908}
static enum ast_device_state sla_state_to_devstate(enum sla_trunk_state state)
Definition: app_sla.c:869
enum cc_state state
Definition: ccss.c:399
@ AST_DEVSTATE_CACHABLE
Definition: devicestate.h:70
int ast_devstate_changed(enum ast_device_state state, enum ast_devstate_cache cachable, const char *fmt,...)
Tells Asterisk the State for Device is changed.
Definition: devicestate.c:513

References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_lock, ao2_ref, ao2_unlock, AST_DEVSTATE_CACHABLE, ast_devstate_changed(), AST_LIST_TRAVERSE, sla_trunk_ref::chan, sla_trunk::name, sla_state_to_devstate(), sla_stations, sla_trunk_ref::state, state, sla_trunk_ref::trunk, and sla_station::trunks.

Referenced by dial_trunk(), queue_ringing_trunk(), run_station(), sla_handle_dial_state_event(), sla_handle_hold_event(), sla_station_exec(), sla_stop_ringing_trunk(), and sla_trunk_exec().

◆ sla_check_device()

static int sla_check_device ( const char *  device)
static

Definition at line 2367 of file app_sla.c.

2368{
2369 char *tech, *tech_data;
2370
2371 tech_data = ast_strdupa(device);
2372 tech = strsep(&tech_data, "/");
2373
2374 if (ast_strlen_zero(tech) || ast_strlen_zero(tech_data)) {
2375 return -1;
2376 }
2377
2378 return 0;
2379}

References ast_strdupa, ast_strlen_zero(), and strsep().

Referenced by sla_build_trunk().

◆ sla_check_failed_station()

static int sla_check_failed_station ( const struct sla_station station)
static

Check to see if this station has failed to be dialed in the past minute.

Note
assumes sla.lock is locked

Definition at line 1245 of file app_sla.c.

1246{
1247 struct sla_failed_station *failed_station;
1248 int res = 0;
1249
1250 AST_LIST_TRAVERSE_SAFE_BEGIN(&sla.failed_stations, failed_station, entry) {
1251 if (station != failed_station->station) {
1252 continue;
1253 }
1254 if (ast_tvdiff_ms(ast_tvnow(), failed_station->last_try) > 1000) {
1256 sla_failed_station_destroy(failed_station);
1257 break;
1258 }
1259 res = 1;
1260 }
1262
1263 return res;
1264}
static void sla_failed_station_destroy(struct sla_failed_station *failed_station)
Definition: app_sla.c:859
A station that failed to be dialed.
Definition: app_sla.c:302
struct sla_station * station
Definition: app_sla.c:303
struct sla_failed_station::@71 entry
struct timeval last_try
Definition: app_sla.c:304

References AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_tvdiff_ms(), ast_tvnow(), sla_failed_station::entry, sla_failed_station::last_try, sla, sla_failed_station_destroy(), and sla_failed_station::station.

Referenced by sla_ring_stations().

◆ sla_check_inuse_station()

static int sla_check_inuse_station ( const struct sla_station station)
static

Check to see if a station is in use.

Definition at line 1330 of file app_sla.c.

1331{
1332 struct sla_trunk_ref *trunk_ref;
1333
1334 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) {
1335 if (trunk_ref->chan) {
1336 return 1;
1337 }
1338 }
1339
1340 return 0;
1341}

References AST_LIST_TRAVERSE, sla_trunk_ref::chan, sla_trunk_ref::entry, and sla_station::trunks.

Referenced by sla_calc_station_delays(), and sla_ring_stations().

◆ sla_check_ringing_station()

static int sla_check_ringing_station ( const struct sla_station station)
static

Check to see if this station is already ringing.

Note
Assumes sla.lock is locked

Definition at line 1229 of file app_sla.c.

1230{
1231 struct sla_ringing_station *ringing_station;
1232
1233 AST_LIST_TRAVERSE(&sla.ringing_stations, ringing_station, entry) {
1234 if (station == ringing_station->station) {
1235 return 1;
1236 }
1237 }
1238
1239 return 0;
1240}

References AST_LIST_TRAVERSE, sla_ringing_station::entry, sla, and sla_ringing_station::station.

Referenced by sla_calc_station_delays(), and sla_ring_stations().

◆ sla_check_station_delay()

static int sla_check_station_delay ( struct sla_station station,
struct sla_ringing_trunk ringing_trunk 
)
static

Calculate the ring delay for a given ringing trunk on a station.

Parameters
stationthe station
ringing_trunkthe trunk. If NULL, the highest priority ringing trunk will be used
Returns
the number of ms left before the delay is complete, or INT_MAX if there is no delay

Definition at line 1363 of file app_sla.c.

1364{
1365 RAII_VAR(struct sla_trunk_ref *, trunk_ref, NULL, ao2_cleanup);
1366 unsigned int delay = UINT_MAX;
1367 int time_left, time_elapsed;
1368
1369 if (!ringing_trunk) {
1370 ringing_trunk = sla_choose_ringing_trunk(station, &trunk_ref, 0);
1371 } else {
1372 trunk_ref = sla_find_trunk_ref(station, ringing_trunk->trunk);
1373 }
1374
1375 if (!ringing_trunk || !trunk_ref) {
1376 return delay;
1377 }
1378
1379 /* If this station has a ring delay specific to the highest priority
1380 * ringing trunk, use that. Otherwise, use the ring delay specified
1381 * globally for the station. */
1382 delay = trunk_ref->ring_delay;
1383 if (!delay) {
1384 delay = station->ring_delay;
1385 }
1386 if (!delay) {
1387 return INT_MAX;
1388 }
1389
1390 time_elapsed = ast_tvdiff_ms(ast_tvnow(), ringing_trunk->ring_begin);
1391 time_left = (delay * 1000) - time_elapsed;
1392
1393 return time_left;
1394}
static struct sla_trunk_ref * sla_find_trunk_ref(const struct sla_station *station, const struct sla_trunk *trunk)
Definition: app_sla.c:1343
unsigned int ring_delay
Definition: app_sla.c:204

References ao2_cleanup, ast_tvdiff_ms(), ast_tvnow(), NULL, RAII_VAR, sla_ringing_trunk::ring_begin, sla_station::ring_delay, sla_choose_ringing_trunk(), sla_find_trunk_ref(), and sla_ringing_trunk::trunk.

Referenced by sla_calc_station_delays(), and sla_ring_stations().

◆ sla_check_station_hold_access()

static int sla_check_station_hold_access ( const struct sla_trunk trunk,
const struct sla_station station 
)
static

Definition at line 735 of file app_sla.c.

736{
737 struct sla_station_ref *station_ref;
738 struct sla_trunk_ref *trunk_ref;
739
740 /* For each station that has this call on hold, check for private hold. */
741 AST_LIST_TRAVERSE(&trunk->stations, station_ref, entry) {
742 AST_LIST_TRAVERSE(&station_ref->station->trunks, trunk_ref, entry) {
743 if (trunk_ref->trunk != trunk || station_ref->station == station) {
744 continue;
745 }
746 if (trunk_ref->state == SLA_TRUNK_STATE_ONHOLD_BYME && station_ref->station->hold_access == SLA_HOLD_PRIVATE) {
747 return 1;
748 }
749 return 0;
750 }
751 }
752
753 return 0;
754}
unsigned int hold_access
Definition: app_sla.c:207
struct sla_trunk::@68 stations

References AST_LIST_TRAVERSE, sla_trunk_ref::entry, sla_station::hold_access, SLA_HOLD_PRIVATE, SLA_TRUNK_STATE_ONHOLD_BYME, sla_trunk_ref::state, sla_station_ref::station, sla_trunk::stations, sla_trunk_ref::trunk, and sla_station::trunks.

Referenced by sla_find_trunk_ref_byname().

◆ sla_check_timed_out_station()

static int sla_check_timed_out_station ( const struct sla_ringing_trunk ringing_trunk,
const struct sla_station station 
)
static

Check to see if dialing this station already timed out for this ringing trunk.

Note
Assumes sla.lock is locked

Definition at line 1084 of file app_sla.c.

1085{
1086 struct sla_station_ref *timed_out_station;
1087
1088 AST_LIST_TRAVERSE(&ringing_trunk->timed_out_stations, timed_out_station, entry) {
1089 if (station == timed_out_station->station) {
1090 return 1;
1091 }
1092 }
1093
1094 return 0;
1095}

References AST_LIST_TRAVERSE, sla_station_ref::entry, sla_station_ref::station, and sla_ringing_trunk::timed_out_stations.

Referenced by sla_choose_ringing_trunk(), and sla_ring_stations().

◆ sla_choose_idle_trunk()

static struct sla_trunk_ref * sla_choose_idle_trunk ( const struct sla_station station)
static

For a given station, choose the highest priority idle trunk.

Precondition
sla_station is locked

Definition at line 1941 of file app_sla.c.

1942{
1943 struct sla_trunk_ref *trunk_ref = NULL;
1944
1945 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) {
1946 if (trunk_ref->state == SLA_TRUNK_STATE_IDLE) {
1947 ao2_ref(trunk_ref, 1);
1948 break;
1949 }
1950 }
1951
1952 return trunk_ref;
1953}

References ao2_ref, AST_LIST_TRAVERSE, sla_trunk_ref::entry, NULL, SLA_TRUNK_STATE_IDLE, sla_trunk_ref::state, and sla_station::trunks.

Referenced by sla_station_exec().

◆ sla_choose_ringing_trunk()

static struct sla_ringing_trunk * sla_choose_ringing_trunk ( struct sla_station station,
struct sla_trunk_ref **  trunk_ref,
int  rm 
)
static

Choose the highest priority ringing trunk for a station.

Parameters
stationthe station
rmremove the ringing trunk once selected
trunk_refa place to store the pointer to this stations reference to the selected trunk
Returns
a pointer to the selected ringing trunk, or NULL if none found
Note
Assumes that sla.lock is locked

Definition at line 1105 of file app_sla.c.

1106{
1107 struct sla_trunk_ref *s_trunk_ref;
1108 struct sla_ringing_trunk *ringing_trunk = NULL;
1109
1110 AST_LIST_TRAVERSE(&station->trunks, s_trunk_ref, entry) {
1111 AST_LIST_TRAVERSE_SAFE_BEGIN(&sla.ringing_trunks, ringing_trunk, entry) {
1112 /* Make sure this is the trunk we're looking for */
1113 if (s_trunk_ref->trunk != ringing_trunk->trunk) {
1114 continue;
1115 }
1116
1117 /* This trunk on the station is ringing. But, make sure this station
1118 * didn't already time out while this trunk was ringing. */
1119 if (sla_check_timed_out_station(ringing_trunk, station)) {
1120 continue;
1121 }
1122
1123 if (rm) {
1125 }
1126
1127 if (trunk_ref) {
1128 ao2_ref(s_trunk_ref, 1);
1129 *trunk_ref = s_trunk_ref;
1130 }
1131
1132 break;
1133 }
1135
1136 if (ringing_trunk) {
1137 break;
1138 }
1139 }
1140
1141 return ringing_trunk;
1142}
static int sla_check_timed_out_station(const struct sla_ringing_trunk *ringing_trunk, const struct sla_station *station)
Check to see if dialing this station already timed out for this ringing trunk.
Definition: app_sla.c:1084

References ao2_ref, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, sla_ringing_trunk::entry, NULL, sla, sla_check_timed_out_station(), sla_trunk_ref::trunk, sla_ringing_trunk::trunk, and sla_station::trunks.

Referenced by sla_calc_station_delays(), sla_check_station_delay(), and sla_handle_dial_state_event().

◆ sla_create_failed_station()

static struct sla_failed_station * sla_create_failed_station ( struct sla_station station)
static

Definition at line 844 of file app_sla.c.

845{
846 struct sla_failed_station *failed_station;
847
848 if (!(failed_station = ast_calloc(1, sizeof(*failed_station)))) {
849 return NULL;
850 }
851
852 ao2_ref(station, 1);
853 failed_station->station = station;
854 failed_station->last_try = ast_tvnow();
855
856 return failed_station;
857}

References ao2_ref, ast_calloc, ast_tvnow(), sla_failed_station::last_try, NULL, and sla_failed_station::station.

Referenced by sla_ring_station().

◆ sla_create_ringing_station()

static struct sla_ringing_station * sla_create_ringing_station ( struct sla_station station)
static

Definition at line 819 of file app_sla.c.

820{
821 struct sla_ringing_station *ringing_station;
822
823 if (!(ringing_station = ast_calloc(1, sizeof(*ringing_station)))) {
824 return NULL;
825 }
826
827 ao2_ref(station, 1);
828 ringing_station->station = station;
829 ringing_station->ring_begin = ast_tvnow();
830
831 return ringing_station;
832}

References ao2_ref, ast_calloc, ast_tvnow(), NULL, sla_ringing_station::ring_begin, and sla_ringing_station::station.

Referenced by sla_ring_station().

◆ sla_create_station_ref()

static struct sla_station_ref * sla_create_station_ref ( struct sla_station station)
static

Definition at line 805 of file app_sla.c.

806{
807 struct sla_station_ref *station_ref;
808
809 if (!(station_ref = ao2_alloc(sizeof(*station_ref), sla_station_ref_destructor))) {
810 return NULL;
811 }
812
813 ao2_ref(station, 1);
814 station_ref->station = station;
815
816 return station_ref;
817}
static void sla_station_ref_destructor(void *obj)
Definition: app_sla.c:795

References ao2_alloc, ao2_ref, NULL, sla_station_ref_destructor(), and sla_station_ref::station.

Referenced by sla_add_trunk_to_station(), and sla_stop_ringing_station().

◆ sla_destroy()

static void sla_destroy ( void  )
static

Definition at line 2341 of file app_sla.c.

2342{
2343 if (sla.thread != AST_PTHREADT_NULL) {
2344 ast_mutex_lock(&sla.lock);
2345 sla.stop = 1;
2346 ast_cond_signal(&sla.cond);
2347 ast_mutex_unlock(&sla.lock);
2348 pthread_join(sla.thread, NULL);
2349 }
2350
2351 /* Drop any created contexts from the dialplan */
2353
2354 ast_mutex_destroy(&sla.lock);
2355 ast_cond_destroy(&sla.cond);
2356
2359
2360 ao2_ref(sla_trunks, -1);
2361 sla_trunks = NULL;
2362
2363 ao2_ref(sla_stations, -1);
2365}
static int sla_trunk_release_refs(void *obj, void *arg, int flags)
Definition: app_sla.c:2279
static int sla_station_release_refs(void *obj, void *arg, int flags)
Definition: app_sla.c:2291
#define ao2_callback(c, flags, cb_fn, arg)
ao2_callback() is a generic function that applies cb_fn() to all objects in a container,...
Definition: astobj2.h:1693
#define ast_cond_destroy(cond)
Definition: lock.h:209
#define AST_PTHREADT_NULL
Definition: lock.h:73
#define ast_mutex_destroy(a)
Definition: lock.h:195
void ast_context_destroy(struct ast_context *con, const char *registrar)
Destroy a context (matches the specified context or ANY context if NULL)
Definition: pbx.c:8236

References ao2_callback, ao2_ref, ast_cond_destroy, ast_cond_signal, ast_context_destroy(), ast_mutex_destroy, ast_mutex_lock, ast_mutex_unlock, AST_PTHREADT_NULL, NULL, sla, sla_registrar, sla_station_release_refs(), sla_stations, sla_trunk_release_refs(), and sla_trunks.

Referenced by unload_module().

◆ sla_dial_state_callback()

static void sla_dial_state_callback ( struct ast_dial dial)
static

Definition at line 1076 of file app_sla.c.

References SLA_EVENT_DIAL_STATE, and sla_queue_event().

Referenced by sla_ring_station().

◆ sla_event_destroy()

static void sla_event_destroy ( struct sla_event event)
static

Definition at line 1720 of file app_sla.c.

1721{
1722 if (event->trunk_ref) {
1723 ao2_ref(event->trunk_ref, -1);
1724 event->trunk_ref = NULL;
1725 }
1726
1727 if (event->station) {
1728 ao2_ref(event->station, -1);
1729 event->station = NULL;
1730 }
1731
1732 ast_free(event);
1733}
Definition: astman.c:222

References ao2_ref, ast_free, and NULL.

Referenced by sla_thread().

◆ sla_failed_station_destroy()

static void sla_failed_station_destroy ( struct sla_failed_station failed_station)
static

Definition at line 859 of file app_sla.c.

860{
861 if (failed_station->station) {
862 ao2_ref(failed_station->station, -1);
863 failed_station->station = NULL;
864 }
865
866 ast_free(failed_station);
867}

References ao2_ref, ast_free, NULL, and sla_failed_station::station.

Referenced by sla_check_failed_station(), and sla_thread().

◆ sla_find_station()

static struct sla_station * sla_find_station ( const char *  name)
static

Definition at line 726 of file app_sla.c.

727{
728 struct sla_station tmp_station = {
729 .name = name,
730 };
731
732 return ao2_find(sla_stations, &tmp_station, OBJ_POINTER);
733}
#define OBJ_POINTER
Definition: astobj2.h:1150
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1736

References ao2_find, name, OBJ_POINTER, and sla_stations.

Referenced by sla_build_station(), sla_state(), and sla_station_exec().

◆ sla_find_trunk()

static struct sla_trunk * sla_find_trunk ( const char *  name)
static

Definition at line 713 of file app_sla.c.

714{
715 struct sla_trunk tmp_trunk = {
716 .name = name,
717 };
718
719 return ao2_find(sla_trunks, &tmp_trunk, OBJ_POINTER);
720}

References ao2_find, name, sla_trunk::name, OBJ_POINTER, and sla_trunks.

Referenced by sla_add_trunk_to_station(), sla_build_trunk(), and sla_trunk_exec().

◆ sla_find_trunk_ref()

static struct sla_trunk_ref * sla_find_trunk_ref ( const struct sla_station station,
const struct sla_trunk trunk 
)
static

Definition at line 1343 of file app_sla.c.

1344{
1345 struct sla_trunk_ref *trunk_ref = NULL;
1346
1347 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) {
1348 if (trunk_ref->trunk == trunk) {
1349 break;
1350 }
1351 }
1352
1353 ao2_ref(trunk_ref, 1);
1354
1355 return trunk_ref;
1356}

References ao2_ref, AST_LIST_TRAVERSE, sla_trunk_ref::entry, NULL, sla_trunk_ref::trunk, and sla_station::trunks.

Referenced by sla_check_station_delay().

◆ sla_find_trunk_ref_byname()

static struct sla_trunk_ref * sla_find_trunk_ref_byname ( const struct sla_station station,
const char *  name 
)
static

Find a trunk reference on a station by name.

Parameters
stationthe station
namethe trunk's name
Precondition
sla_station is locked
Returns
a pointer to the station's trunk reference. If the trunk is not found, it is not idle and barge is disabled, or if it is on hold and private hold is set, then NULL will be returned.

Definition at line 765 of file app_sla.c.

766{
767 struct sla_trunk_ref *trunk_ref = NULL;
768
769 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) {
770 if (strcasecmp(trunk_ref->trunk->name, name)) {
771 continue;
772 }
773
774 if (trunk_ref->trunk->barge_disabled && trunk_ref->state == SLA_TRUNK_STATE_UP) {
775 ast_debug(2, "Barge disabled, trunk not available\n");
776 trunk_ref = NULL;
777 } else if (trunk_ref->trunk->hold_stations && trunk_ref->trunk->hold_access == SLA_HOLD_PRIVATE && trunk_ref->state != SLA_TRUNK_STATE_ONHOLD_BYME) {
778 ast_debug(2, "Private hold by another station\n");
779 trunk_ref = NULL;
780 } else if (sla_check_station_hold_access(trunk_ref->trunk, station)) {
781 ast_debug(2, "No hold access\n");
782 trunk_ref = NULL;
783 }
784
785 break;
786 }
787
788 if (trunk_ref) {
789 ao2_ref(trunk_ref, 1);
790 }
791
792 return trunk_ref;
793}
static int sla_check_station_hold_access(const struct sla_trunk *trunk, const struct sla_station *station)
Definition: app_sla.c:735
unsigned int barge_disabled
Definition: app_sla.c:244
unsigned int hold_access
Definition: app_sla.c:247

References ao2_ref, ast_debug, AST_LIST_TRAVERSE, sla_trunk::barge_disabled, sla_trunk_ref::entry, sla_trunk::hold_access, sla_trunk::hold_stations, name, sla_trunk::name, NULL, sla_check_station_hold_access(), SLA_HOLD_PRIVATE, SLA_TRUNK_STATE_ONHOLD_BYME, SLA_TRUNK_STATE_UP, sla_trunk_ref::state, sla_trunk_ref::trunk, and sla_station::trunks.

Referenced by sla_station_exec().

◆ sla_framehook()

static struct ast_frame * sla_framehook ( struct ast_channel chan,
struct ast_frame f,
enum ast_framehook_event  event,
void *  data 
)
static

Definition at line 648 of file app_sla.c.

649{
650 struct sla_framehook_data *sla_data = data;
651 if (!f || (event != AST_FRAMEHOOK_EVENT_WRITE)) {
652 return f;
653 }
656 }
657 return f;
658}
static void sla_queue_event_conf(enum sla_event_type type, struct ast_channel *chan, const char *confname)
Queue a SLA event from the conference.
Definition: app_sla.c:567
@ AST_FRAMEHOOK_EVENT_WRITE
Definition: framehook.h:153
@ AST_FRAME_CONTROL
@ AST_CONTROL_HOLD
struct ast_frame_subclass subclass
enum ast_frame_type frametype

References AST_CONTROL_HOLD, AST_FRAME_CONTROL, AST_FRAMEHOOK_EVENT_WRITE, sla_framehook_data::confname, ast_frame::frametype, ast_frame_subclass::integer, SLA_EVENT_HOLD, sla_queue_event_conf(), and ast_frame::subclass.

Referenced by attach_framehook().

◆ sla_framehook_consume()

static int sla_framehook_consume ( void *  data,
enum ast_frame_type  type 
)
static

Callback function which informs upstream if we are consuming a frame of a specific type.

Definition at line 661 of file app_sla.c.

662{
663 return (type == AST_FRAME_CONTROL ? 1 : 0);
664}
static const char type[]
Definition: chan_ooh323.c:109

References AST_FRAME_CONTROL, and type.

Referenced by attach_framehook().

◆ sla_handle_dial_state_event()

static void sla_handle_dial_state_event ( void  )
static

Definition at line 1144 of file app_sla.c.

1145{
1146 struct sla_ringing_station *ringing_station;
1147
1148 AST_LIST_TRAVERSE_SAFE_BEGIN(&sla.ringing_stations, ringing_station, entry) {
1149 RAII_VAR(struct sla_trunk_ref *, s_trunk_ref, NULL, ao2_cleanup);
1150 struct sla_ringing_trunk *ringing_trunk = NULL;
1151 struct run_station_args args;
1152 enum ast_dial_result dial_res;
1153 pthread_t dont_care;
1156
1157 switch ((dial_res = ast_dial_state(ringing_station->station->dial))) {
1165 break;
1168 /* Find the appropriate trunk to answer. */
1169 ast_mutex_lock(&sla.lock);
1170 ringing_trunk = sla_choose_ringing_trunk(ringing_station->station, &s_trunk_ref, 1);
1171 ast_mutex_unlock(&sla.lock);
1172 if (!ringing_trunk) {
1173 /* This case happens in a bit of a race condition. If two stations answer
1174 * the outbound call at the same time, the first one will get connected to
1175 * the trunk. When the second one gets here, it will not see any trunks
1176 * ringing so we have no idea what to conect it to. So, we just hang up
1177 * on it. */
1178 ast_debug(1, "Found no ringing trunk for station '%s' to answer!\n", ringing_station->station->name);
1179 ast_dial_join(ringing_station->station->dial);
1180 ast_dial_destroy(ringing_station->station->dial);
1181 ringing_station->station->dial = NULL;
1182 sla_ringing_station_destroy(ringing_station);
1183 break;
1184 }
1185 /* Track the channel that answered this trunk */
1186 s_trunk_ref->chan = ast_dial_answered(ringing_station->station->dial);
1187 /* Actually answer the trunk */
1188 answer_trunk_chan(ringing_trunk->trunk->chan);
1190 /* Now, start a thread that will connect this station to the trunk. The rest of
1191 * the code here sets up the thread and ensures that it is able to save the arguments
1192 * before they are no longer valid since they are allocated on the stack. */
1193 ao2_ref(s_trunk_ref, 1);
1194 args.trunk_ref = s_trunk_ref;
1195 ao2_ref(ringing_station->station, 1);
1196 args.station = ringing_station->station;
1197 args.cond = &cond;
1198 args.cond_lock = &cond_lock;
1199 sla_ringing_trunk_destroy(ringing_trunk);
1200 sla_ringing_station_destroy(ringing_station);
1209 break;
1214 break;
1215 }
1216 if (dial_res == AST_DIAL_RESULT_ANSWERED) {
1217 /* Queue up reprocessing ringing trunks, and then ringing stations again */
1220 break;
1221 }
1222 }
1224}
ast_cond_t cond
Definition: app_sla.c:336
static void * run_station(void *data)
Definition: app_sla.c:981
static void sla_ringing_trunk_destroy(struct sla_ringing_trunk *ringing_trunk)
Definition: app_sla.c:2149
static void sla_ringing_station_destroy(struct sla_ringing_station *ringing_station)
Definition: app_sla.c:834
#define ast_cond_wait(cond, mutex)
Definition: lock.h:212
#define ast_cond_init(cond, attr)
Definition: lock.h:208
#define ast_mutex_init(pmutex)
Definition: lock.h:193
pthread_cond_t ast_cond_t
Definition: lock.h:185
Structure for mutex and tracking information.
Definition: lock.h:142
ast_mutex_t * cond_lock
Definition: app_sla.c:913
#define ast_pthread_create_detached_background(a, b, c, d)
Definition: utils.h:597

References ALL_TRUNK_REFS, answer_trunk_chan(), ao2_cleanup, ao2_ref, args, ast_cond_destroy, ast_cond_init, ast_cond_wait, ast_debug, ast_dial_answered(), ast_dial_destroy(), ast_dial_join(), AST_DIAL_RESULT_ANSWERED, AST_DIAL_RESULT_FAILED, AST_DIAL_RESULT_HANGUP, AST_DIAL_RESULT_INVALID, AST_DIAL_RESULT_PROCEEDING, AST_DIAL_RESULT_PROGRESS, AST_DIAL_RESULT_RINGING, AST_DIAL_RESULT_TIMEOUT, AST_DIAL_RESULT_TRYING, AST_DIAL_RESULT_UNANSWERED, ast_dial_state(), AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_mutex_destroy, ast_mutex_init, ast_mutex_lock, ast_mutex_unlock, ast_pthread_create_detached_background, sla_trunk::chan, cond, run_station_args::cond_lock, sla_station::dial, sla_ringing_station::entry, NULL, RAII_VAR, run_station(), sla, sla_change_trunk_state(), sla_choose_ringing_trunk(), SLA_EVENT_DIAL_STATE, SLA_EVENT_RINGING_TRUNK, sla_queue_event(), sla_ringing_station_destroy(), sla_ringing_trunk_destroy(), SLA_STATION_HANGUP_NORMAL, sla_stop_ringing_station(), SLA_TRUNK_STATE_UP, sla_ringing_station::station, and sla_ringing_trunk::trunk.

Referenced by sla_thread().

◆ sla_handle_hold_event()

static void sla_handle_hold_event ( struct sla_event event)
static

Definition at line 1485 of file app_sla.c.

1486{
1487 ast_atomic_fetchadd_int((int *) &event->trunk_ref->trunk->hold_stations, 1);
1488 event->trunk_ref->state = SLA_TRUNK_STATE_ONHOLD_BYME;
1489 ast_devstate_changed(AST_DEVICE_ONHOLD, AST_DEVSTATE_CACHABLE, "SLA:%s_%s", event->station->name, event->trunk_ref->trunk->name);
1491
1492 if (event->trunk_ref->trunk->active_stations == 1) {
1493 /* The station putting it on hold is the only one on the call, so start
1494 * Music on hold to the trunk. */
1495 event->trunk_ref->trunk->on_hold = 1;
1496 ast_indicate(event->trunk_ref->trunk->chan, AST_CONTROL_HOLD);
1497 }
1498
1499 ast_softhangup(event->trunk_ref->chan, AST_SOFTHANGUP_DEV);
1500 event->trunk_ref->chan = NULL;
1501}
int ast_softhangup(struct ast_channel *chan, int cause)
Softly hangup up a channel.
Definition: channel.c:2440
@ AST_SOFTHANGUP_DEV
Definition: channel.h:1141
@ AST_DEVICE_ONHOLD
Definition: devicestate.h:61

References ast_atomic_fetchadd_int(), AST_CONTROL_HOLD, AST_DEVICE_ONHOLD, AST_DEVSTATE_CACHABLE, ast_devstate_changed(), ast_indicate(), ast_softhangup(), AST_SOFTHANGUP_DEV, INACTIVE_TRUNK_REFS, NULL, sla_change_trunk_state(), SLA_TRUNK_STATE_ONHOLD, and SLA_TRUNK_STATE_ONHOLD_BYME.

Referenced by sla_thread().

◆ sla_handle_ringing_trunk_event()

static void sla_handle_ringing_trunk_event ( void  )
static

Definition at line 1475 of file app_sla.c.

1476{
1477 ast_mutex_lock(&sla.lock);
1479 ast_mutex_unlock(&sla.lock);
1480
1481 /* Find stations that shouldn't be ringing anymore. */
1483}
static void sla_ring_stations(void)
Ring stations based on current set of ringing trunks.
Definition: app_sla.c:1399
static void sla_hangup_stations(void)
Definition: app_sla.c:1445

References ast_mutex_lock, ast_mutex_unlock, sla, sla_hangup_stations(), and sla_ring_stations().

Referenced by sla_thread().

◆ sla_hangup_stations()

static void sla_hangup_stations ( void  )
static

Definition at line 1445 of file app_sla.c.

1446{
1447 struct sla_trunk_ref *trunk_ref;
1448 struct sla_ringing_station *ringing_station;
1449
1450 AST_LIST_TRAVERSE_SAFE_BEGIN(&sla.ringing_stations, ringing_station, entry) {
1451 AST_LIST_TRAVERSE(&ringing_station->station->trunks, trunk_ref, entry) {
1452 struct sla_ringing_trunk *ringing_trunk;
1453 ast_mutex_lock(&sla.lock);
1454 AST_LIST_TRAVERSE(&sla.ringing_trunks, ringing_trunk, entry) {
1455 if (trunk_ref->trunk == ringing_trunk->trunk) {
1456 break;
1457 }
1458 }
1459 ast_mutex_unlock(&sla.lock);
1460 if (ringing_trunk) {
1461 break;
1462 }
1463 }
1464 if (!trunk_ref) {
1466 ast_dial_join(ringing_station->station->dial);
1467 ast_dial_destroy(ringing_station->station->dial);
1468 ringing_station->station->dial = NULL;
1469 sla_ringing_station_destroy(ringing_station);
1470 }
1471 }
1473}

References ast_dial_destroy(), ast_dial_join(), AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_mutex_lock, ast_mutex_unlock, sla_station::dial, sla_ringing_trunk::entry, sla_ringing_station::entry, NULL, sla, sla_ringing_station_destroy(), sla_ringing_station::station, sla_trunk_ref::trunk, sla_ringing_trunk::trunk, and sla_station::trunks.

Referenced by sla_handle_ringing_trunk_event().

◆ sla_hold_str()

static const char * sla_hold_str ( unsigned int  hold_access)
static

Definition at line 350 of file app_sla.c.

351{
352 const char *hold = "Unknown";
353
354 switch (hold_access) {
355 case SLA_HOLD_OPEN:
356 hold = "Open";
357 break;
358 case SLA_HOLD_PRIVATE:
359 hold = "Private";
360 default:
361 break;
362 }
363
364 return hold;
365}
static void hold(struct ast_channel *chan)
Helper method to place a channel in a bridge on hold.

References hold(), SLA_HOLD_OPEN, and SLA_HOLD_PRIVATE.

Referenced by sla_show_stations(), and sla_show_trunks().

◆ sla_in_use()

static int sla_in_use ( void  )
static

Definition at line 2754 of file app_sla.c.

2755{
2757}
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.

References ao2_container_count(), sla_stations, and sla_trunks.

Referenced by sla_load_config().

◆ sla_load_config()

static int sla_load_config ( int  reload)
static

Definition at line 2759 of file app_sla.c.

2760{
2761 struct ast_config *cfg;
2762 struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
2763 const char *cat = NULL;
2764 int res = 0;
2765 const char *val;
2766
2767 if (!reload) {
2768 ast_mutex_init(&sla.lock);
2769 ast_cond_init(&sla.cond, NULL);
2772 }
2773
2774 if (!(cfg = ast_config_load(SLA_CONFIG_FILE, config_flags))) {
2775 return 0; /* Treat no config as normal */
2776 } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
2777 return 0;
2778 } else if (cfg == CONFIG_STATUS_FILEINVALID) {
2779 ast_log(LOG_ERROR, "Config file " SLA_CONFIG_FILE " is in an invalid format. Aborting.\n");
2780 return 0;
2781 }
2782
2783 if (reload) {
2786 }
2787
2788 if ((val = ast_variable_retrieve(cfg, "general", "attemptcallerid"))) {
2789 sla.attempt_callerid = ast_true(val);
2790 }
2791
2792 while ((cat = ast_category_browse(cfg, cat)) && !res) {
2793 const char *type;
2794 if (!strcasecmp(cat, "general")) {
2795 continue;
2796 }
2797 if (!(type = ast_variable_retrieve(cfg, cat, "type"))) {
2798 ast_log(LOG_WARNING, "Invalid entry in %s defined with no type!\n", SLA_CONFIG_FILE);
2799 continue;
2800 }
2801 if (!strcasecmp(type, "trunk")) {
2802 res = sla_build_trunk(cfg, cat);
2803 } else if (!strcasecmp(type, "station")) {
2804 res = sla_build_station(cfg, cat);
2805 } else {
2806 ast_log(LOG_WARNING, "Entry in %s defined with invalid type '%s'!\n", SLA_CONFIG_FILE, type);
2807 }
2808 }
2809
2810 ast_config_destroy(cfg);
2811
2812 if (reload) {
2815 }
2816
2817 /* Start SLA event processing thread once SLA has been configured. */
2818 if (sla.thread == AST_PTHREADT_NULL && sla_in_use()) {
2820 }
2821
2822 return res;
2823}
static int sla_build_station(struct ast_config *cfg, const char *cat)
Definition: app_sla.c:2559
static int sla_trunk_is_marked(void *obj, void *arg, int flags)
Definition: app_sla.c:2698
static int sla_build_trunk(struct ast_config *cfg, const char *cat)
Definition: app_sla.c:2396
static int sla_station_mark(void *obj, void *arg, int flags)
Definition: app_sla.c:2680
static int sla_station_is_marked(void *obj, void *arg, int flags)
Definition: app_sla.c:2726
static int sla_trunk_cmp(void *obj, void *arg, int flags)
Definition: app_sla.c:2327
static int sla_trunk_mark(void *obj, void *arg, int flags)
Definition: app_sla.c:2662
static int sla_in_use(void)
Definition: app_sla.c:2754
static int sla_station_cmp(void *obj, void *arg, int flags)
Definition: app_sla.c:2334
static void * sla_thread(void *data)
Definition: app_sla.c:1735
@ AO2_ALLOC_OPT_LOCK_MUTEX
Definition: astobj2.h:363
@ OBJ_NODATA
Definition: astobj2.h:1044
@ OBJ_MULTIPLE
Definition: astobj2.h:1049
@ OBJ_UNLINK
Definition: astobj2.h:1039
#define ao2_container_alloc_list(ao2_options, container_options, sort_fn, cmp_fn)
Allocate and initialize a list container.
Definition: astobj2.h:1327
#define ast_config_load(filename, flags)
Load a config file.
char * ast_category_browse(struct ast_config *config, const char *prev_name)
Browse categories.
Definition: extconf.c:3326
@ CONFIG_FLAG_FILEUNCHANGED
#define CONFIG_STATUS_FILEUNCHANGED
#define CONFIG_STATUS_FILEINVALID
void ast_config_destroy(struct ast_config *cfg)
Destroys a config.
Definition: extconf.c:1289
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true"....
Definition: utils.c:2199
Definition: ast_expr2.c:325
#define ast_pthread_create(a, b, c, d)
Definition: utils.h:584

References AO2_ALLOC_OPT_LOCK_MUTEX, ao2_callback, ao2_container_alloc_list, ast_category_browse(), ast_cond_init, ast_config_destroy(), ast_config_load, ast_log, ast_mutex_init, ast_pthread_create, AST_PTHREADT_NULL, ast_true(), ast_variable_retrieve(), CONFIG_FLAG_FILEUNCHANGED, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEUNCHANGED, LOG_ERROR, LOG_WARNING, NULL, OBJ_MULTIPLE, OBJ_NODATA, OBJ_UNLINK, reload(), sla, sla_build_station(), sla_build_trunk(), SLA_CONFIG_FILE, sla_in_use(), sla_station_cmp(), sla_station_is_marked(), sla_station_mark(), sla_stations, sla_thread(), sla_trunk_cmp(), sla_trunk_is_marked(), sla_trunk_mark(), sla_trunks, and type.

Referenced by load_config().

◆ sla_process_timers()

static int sla_process_timers ( struct timespec *  ts)
static

Calculate the time until the next known event.

Note
Called with sla.lock locked

Definition at line 1680 of file app_sla.c.

1681{
1682 unsigned int timeout = UINT_MAX;
1683 struct timeval wait;
1684 unsigned int change_made = 0;
1685
1686 /* Check for ring timeouts on ringing trunks */
1687 if (sla_calc_trunk_timeouts(&timeout)) {
1688 change_made = 1;
1689 }
1690
1691 /* Check for ring timeouts on ringing stations */
1692 if (sla_calc_station_timeouts(&timeout)) {
1693 change_made = 1;
1694 }
1695
1696 /* Check for station ring delays */
1697 if (sla_calc_station_delays(&timeout)) {
1698 change_made = 1;
1699 }
1700
1701 /* queue reprocessing of ringing trunks */
1702 if (change_made) {
1704 }
1705
1706 /* No timeout */
1707 if (timeout == UINT_MAX) {
1708 return 0;
1709 }
1710
1711 if (ts) {
1712 wait = ast_tvadd(ast_tvnow(), ast_samp2tv(timeout, 1000));
1713 ts->tv_sec = wait.tv_sec;
1714 ts->tv_nsec = wait.tv_usec * 1000;
1715 }
1716
1717 return 1;
1718}
static int sla_calc_station_delays(unsigned int *timeout)
Calculate the ring delay for a station.
Definition: app_sla.c:1631
static void sla_queue_event_nolock(enum sla_event_type type)
Definition: app_sla.c:556
static int sla_calc_trunk_timeouts(unsigned int *timeout)
Process trunk ring timeouts.
Definition: app_sla.c:1507
static int sla_calc_station_timeouts(unsigned int *timeout)
Process station ring timeouts.
Definition: app_sla.c:1539
struct timeval ast_samp2tv(unsigned int _nsamp, unsigned int _rate)
Returns a timeval corresponding to the duration of n samples at rate r. Useful to convert samples to ...
Definition: time.h:282
struct timeval ast_tvadd(struct timeval a, struct timeval b)
Returns the sum of two timevals a + b.
Definition: extconf.c:2282

References ast_samp2tv(), ast_tvadd(), ast_tvnow(), sla_calc_station_delays(), sla_calc_station_timeouts(), sla_calc_trunk_timeouts(), SLA_EVENT_RINGING_TRUNK, and sla_queue_event_nolock().

Referenced by sla_thread().

◆ sla_queue_event()

static void sla_queue_event ( enum sla_event_type  type)
static

Definition at line 561 of file app_sla.c.

562{
564}
static void sla_queue_event_full(enum sla_event_type type, struct sla_trunk_ref *trunk_ref, struct sla_station *station, int lock)
Definition: app_sla.c:525

References NULL, sla_queue_event_full(), and type.

Referenced by queue_ringing_trunk(), sla_dial_state_callback(), sla_handle_dial_state_event(), sla_station_exec(), and sla_trunk_exec().

◆ sla_queue_event_conf()

static void sla_queue_event_conf ( enum sla_event_type  type,
struct ast_channel chan,
const char *  confname 
)
static

Queue a SLA event from the conference.

Definition at line 567 of file app_sla.c.

568{
569 struct sla_station *station;
570 struct sla_trunk_ref *trunk_ref = NULL;
571 char *trunk_name;
572 struct ao2_iterator i;
573
574 trunk_name = ast_strdupa(confname);
575 strsep(&trunk_name, "_");
576 if (ast_strlen_zero(trunk_name)) {
577 ast_log(LOG_ERROR, "Invalid conference name for SLA - '%s'!\n", confname);
578 return;
579 }
580
582 while ((station = ao2_iterator_next(&i))) {
583 ao2_lock(station);
584 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) {
585 if (trunk_ref->chan == chan && !strcmp(trunk_ref->trunk->name, trunk_name)) {
586 ao2_ref(trunk_ref, 1);
587 break;
588 }
589 }
590 ao2_unlock(station);
591 if (trunk_ref) {
592 /* station reference given to sla_queue_event_full() */
593 break;
594 }
595 ao2_ref(station, -1);
596 }
598
599 if (!trunk_ref) {
600 ast_debug(1, "Trunk not found for event!\n");
601 return;
602 }
603
604 sla_queue_event_full(type, trunk_ref, station, 1);
605}

References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_lock, ao2_ref, ao2_unlock, ast_debug, AST_LIST_TRAVERSE, ast_log, ast_strdupa, ast_strlen_zero(), sla_trunk_ref::chan, LOG_ERROR, sla_trunk::name, NULL, sla_queue_event_full(), sla_stations, strsep(), sla_trunk_ref::trunk, sla_station::trunks, and type.

Referenced by sla_framehook().

◆ sla_queue_event_full()

static void sla_queue_event_full ( enum sla_event_type  type,
struct sla_trunk_ref trunk_ref,
struct sla_station station,
int  lock 
)
static

Definition at line 525 of file app_sla.c.

526{
527 struct sla_event *event;
528
529 if (sla.thread == AST_PTHREADT_NULL) {
530 ao2_ref(station, -1);
531 ao2_ref(trunk_ref, -1);
532 return;
533 }
534
535 if (!(event = ast_calloc(1, sizeof(*event)))) {
536 ao2_ref(station, -1);
537 ao2_ref(trunk_ref, -1);
538 return;
539 }
540
541 event->type = type;
542 event->trunk_ref = trunk_ref;
543 event->station = station;
544
545 if (!lock) {
547 return;
548 }
549
550 ast_mutex_lock(&sla.lock);
552 ast_cond_signal(&sla.cond);
553 ast_mutex_unlock(&sla.lock);
554}
ast_mutex_t lock
Definition: app_sla.c:337
struct sla_station * station
Definition: app_sla.c:295
struct sla_event::@70 entry
struct sla_trunk_ref * trunk_ref
Definition: app_sla.c:296

References ao2_ref, ast_calloc, ast_cond_signal, AST_LIST_INSERT_TAIL, ast_mutex_lock, ast_mutex_unlock, AST_PTHREADT_NULL, sla_event::entry, lock, sla, sla_event::station, sla_event::trunk_ref, and type.

Referenced by sla_queue_event(), sla_queue_event_conf(), and sla_queue_event_nolock().

◆ sla_queue_event_nolock()

static void sla_queue_event_nolock ( enum sla_event_type  type)
static

Definition at line 556 of file app_sla.c.

557{
559}

References NULL, sla_queue_event_full(), and type.

Referenced by sla_process_timers().

◆ sla_ring_station()

static int sla_ring_station ( struct sla_ringing_trunk ringing_trunk,
struct sla_station station 
)
static

Ring a station.

Note
Assumes sla.lock is locked

Definition at line 1269 of file app_sla.c.

1270{
1271 char *tech, *tech_data;
1272 struct ast_dial *dial;
1273 struct sla_ringing_station *ringing_station;
1274 enum ast_dial_result res;
1275 int caller_is_saved;
1276 struct ast_party_caller caller;
1277
1278 if (!(dial = ast_dial_create())) {
1279 return -1;
1280 }
1281
1283 tech_data = ast_strdupa(station->device);
1284 tech = strsep(&tech_data, "/");
1285
1286 if (ast_dial_append(dial, tech, tech_data, NULL) == -1) {
1287 ast_dial_destroy(dial);
1288 return -1;
1289 }
1290
1291 /* Do we need to save off the caller ID data? */
1292 caller_is_saved = 0;
1293 if (!sla.attempt_callerid) {
1294 caller_is_saved = 1;
1295 caller = *ast_channel_caller(ringing_trunk->trunk->chan);
1297 }
1298
1299 res = ast_dial_run(dial, ringing_trunk->trunk->chan, 1);
1300
1301 /* Restore saved caller ID */
1302 if (caller_is_saved) {
1304 ast_channel_caller_set(ringing_trunk->trunk->chan, &caller);
1305 }
1306
1307 if (res != AST_DIAL_RESULT_TRYING) {
1308 struct sla_failed_station *failed_station;
1309 ast_dial_destroy(dial);
1310 if ((failed_station = sla_create_failed_station(station))) {
1311 AST_LIST_INSERT_HEAD(&sla.failed_stations, failed_station, entry);
1312 }
1313 return -1;
1314 }
1315 if (!(ringing_station = sla_create_ringing_station(station))) {
1316 ast_dial_join(dial);
1317 ast_dial_destroy(dial);
1318 return -1;
1319 }
1320
1321 station->dial = dial;
1322
1323 AST_LIST_INSERT_HEAD(&sla.ringing_stations, ringing_station, entry);
1324
1325 return 0;
1326}
static void sla_dial_state_callback(struct ast_dial *dial)
Definition: app_sla.c:1076
static struct sla_ringing_station * sla_create_ringing_station(struct sla_station *station)
Definition: app_sla.c:819
static struct sla_failed_station * sla_create_failed_station(struct sla_station *station)
Definition: app_sla.c:844
void ast_dial_set_state_callback(struct ast_dial *dial, ast_dial_state_callback callback)
Set a callback for state changes.
Definition: dial.c:1269

References ast_channel_caller(), ast_channel_caller_set(), ast_dial_append(), ast_dial_create(), ast_dial_destroy(), ast_dial_join(), AST_DIAL_RESULT_TRYING, ast_dial_run(), ast_dial_set_state_callback(), AST_LIST_INSERT_HEAD, ast_party_caller_free(), ast_party_caller_init(), ast_strdupa, sla_trunk::chan, sla_station::dial, sla_failed_station::entry, NULL, sla, sla_create_failed_station(), sla_create_ringing_station(), sla_dial_state_callback(), sla_failed_station::station, strsep(), and sla_ringing_trunk::trunk.

Referenced by sla_ring_stations().

◆ sla_ring_stations()

static void sla_ring_stations ( void  )
static

Ring stations based on current set of ringing trunks.

Note
Assumes that sla.lock is locked

Definition at line 1399 of file app_sla.c.

1400{
1401 struct sla_station_ref *station_ref;
1402 struct sla_ringing_trunk *ringing_trunk;
1403
1404 /* Make sure that every station that uses at least one of the ringing
1405 * trunks, is ringing. */
1406 AST_LIST_TRAVERSE(&sla.ringing_trunks, ringing_trunk, entry) {
1407 AST_LIST_TRAVERSE(&ringing_trunk->trunk->stations, station_ref, entry) {
1408 int time_left;
1409
1410 /* Is this station already ringing? */
1411 if (sla_check_ringing_station(station_ref->station)) {
1412 continue;
1413 }
1414
1415 /* Is this station already in a call? */
1416 if (sla_check_inuse_station(station_ref->station)) {
1417 continue;
1418 }
1419
1420 /* Did we fail to dial this station earlier? If so, has it been
1421 * a minute since we tried? */
1422 if (sla_check_failed_station(station_ref->station)) {
1423 continue;
1424 }
1425
1426 /* If this station already timed out while this trunk was ringing,
1427 * do not dial it again for this ringing trunk. */
1428 if (sla_check_timed_out_station(ringing_trunk, station_ref->station)) {
1429 continue;
1430 }
1431
1432 /* Check for a ring delay in progress */
1433 time_left = sla_check_station_delay(station_ref->station, ringing_trunk);
1434 if (time_left != INT_MAX && time_left > 0) {
1435 continue;
1436 }
1437
1438 /* It is time to make this station begin to ring. Do it! */
1439 sla_ring_station(ringing_trunk, station_ref->station);
1440 }
1441 }
1442 /* Now, all of the stations that should be ringing, are ringing. */
1443}
static int sla_check_failed_station(const struct sla_station *station)
Check to see if this station has failed to be dialed in the past minute.
Definition: app_sla.c:1245
static int sla_ring_station(struct sla_ringing_trunk *ringing_trunk, struct sla_station *station)
Ring a station.
Definition: app_sla.c:1269

References AST_LIST_TRAVERSE, sla_ringing_trunk::entry, sla, sla_check_failed_station(), sla_check_inuse_station(), sla_check_ringing_station(), sla_check_station_delay(), sla_check_timed_out_station(), sla_ring_station(), sla_station_ref::station, sla_trunk::stations, and sla_ringing_trunk::trunk.

Referenced by sla_handle_ringing_trunk_event().

◆ sla_ringing_station_destroy()

static void sla_ringing_station_destroy ( struct sla_ringing_station ringing_station)
static

Definition at line 834 of file app_sla.c.

835{
836 if (ringing_station->station) {
837 ao2_ref(ringing_station->station, -1);
838 ringing_station->station = NULL;
839 }
840
841 ast_free(ringing_station);
842}

References ao2_ref, ast_free, NULL, and sla_ringing_station::station.

Referenced by sla_handle_dial_state_event(), sla_hangup_stations(), sla_stop_ringing_station(), and sla_thread().

◆ sla_ringing_trunk_destroy()

static void sla_ringing_trunk_destroy ( struct sla_ringing_trunk ringing_trunk)
static

Definition at line 2149 of file app_sla.c.

2150{
2151 if (ringing_trunk->trunk) {
2152 ao2_ref(ringing_trunk->trunk, -1);
2153 ringing_trunk->trunk = NULL;
2154 }
2155
2156 ast_free(ringing_trunk);
2157}

References ao2_ref, ast_free, NULL, and sla_ringing_trunk::trunk.

Referenced by sla_handle_dial_state_event(), sla_station_exec(), sla_stop_ringing_trunk(), and sla_trunk_exec().

◆ sla_show_stations()

static char * sla_show_stations ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 441 of file app_sla.c.

442{
443 struct ao2_iterator i;
444 struct sla_station *station;
445
446 switch (cmd) {
447 case CLI_INIT:
448 e->command = "sla show stations";
449 e->usage =
450 "Usage: sla show stations\n"
451 " This will list all stations defined in sla.conf\n";
452 return NULL;
453 case CLI_GENERATE:
454 return NULL;
455 }
456
457 ast_cli(a->fd, "\n"
458 "=============================================================\n"
459 "=== Configured SLA Stations =================================\n"
460 "=============================================================\n"
461 "===\n");
463 for (; (station = ao2_iterator_next(&i)); ao2_ref(station, -1)) {
464 struct sla_trunk_ref *trunk_ref;
465 char ring_timeout[16] = "(none)";
466 char ring_delay[16] = "(none)";
467
468 ao2_lock(station);
469
470 if (station->ring_timeout) {
471 snprintf(ring_timeout, sizeof(ring_timeout), "%u", station->ring_timeout);
472 }
473 if (station->ring_delay) {
474 snprintf(ring_delay, sizeof(ring_delay), "%u", station->ring_delay);
475 }
476 ast_cli(a->fd, "=== ---------------------------------------------------------\n"
477 "=== Station Name: %s\n"
478 "=== ==> Device: %s\n"
479 "=== ==> AutoContext: %s\n"
480 "=== ==> RingTimeout: %s\n"
481 "=== ==> RingDelay: %s\n"
482 "=== ==> HoldAccess: %s\n"
483 "=== ==> Trunks ...\n",
484 station->name, station->device,
485 S_OR(station->autocontext, "(none)"),
487 sla_hold_str(station->hold_access));
488 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) {
489 if (trunk_ref->ring_timeout) {
490 snprintf(ring_timeout, sizeof(ring_timeout), "%u", trunk_ref->ring_timeout);
491 } else {
492 strcpy(ring_timeout, "(none)");
493 }
494 if (trunk_ref->ring_delay) {
495 snprintf(ring_delay, sizeof(ring_delay), "%u", trunk_ref->ring_delay);
496 } else {
497 strcpy(ring_delay, "(none)");
498 }
499
500 ast_cli(a->fd, "=== ==> Trunk Name: %s\n"
501 "=== ==> State: %s\n"
502 "=== ==> RingTimeout: %s\n"
503 "=== ==> RingDelay: %s\n",
504 trunk_ref->trunk->name,
505 trunkstate2str(trunk_ref->state),
507 }
508 ast_cli(a->fd, "=== ---------------------------------------------------------\n"
509 "===\n");
510
511 ao2_unlock(station);
512 }
514 ast_cli(a->fd, "============================================================\n"
515 "\n");
516
517 return CLI_SUCCESS;
518}
static const char * sla_hold_str(unsigned int hold_access)
Definition: app_sla.c:350
static const char * trunkstate2str(enum sla_trunk_state state)
Definition: app_sla.c:427
#define CLI_SUCCESS
Definition: cli.h:44
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
@ CLI_INIT
Definition: cli.h:152
@ CLI_GENERATE
Definition: cli.h:153
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one.
Definition: strings.h:80
char * command
Definition: cli.h:186
const char * usage
Definition: cli.h:177
static struct test_val a

References a, ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_lock, ao2_ref, ao2_unlock, ast_cli(), AST_LIST_TRAVERSE, CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, sla_trunk_ref::entry, sla_station::hold_access, sla_trunk::name, NULL, sla_station::ring_delay, sla_trunk_ref::ring_delay, sla_station::ring_timeout, sla_trunk_ref::ring_timeout, S_OR, sla_hold_str(), sla_stations, sla_trunk_ref::state, sla_trunk_ref::trunk, sla_station::trunks, trunkstate2str(), and ast_cli_entry::usage.

◆ sla_show_trunks()

static char * sla_show_trunks ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 367 of file app_sla.c.

368{
369 struct ao2_iterator i;
370 struct sla_trunk *trunk;
371
372 switch (cmd) {
373 case CLI_INIT:
374 e->command = "sla show trunks";
375 e->usage =
376 "Usage: sla show trunks\n"
377 " This will list all trunks defined in sla.conf\n";
378 return NULL;
379 case CLI_GENERATE:
380 return NULL;
381 }
382
383 ast_cli(a->fd, "\n"
384 "=============================================================\n"
385 "=== Configured SLA Trunks ===================================\n"
386 "=============================================================\n"
387 "===\n");
389 for (; (trunk = ao2_iterator_next(&i)); ao2_ref(trunk, -1)) {
390 struct sla_station_ref *station_ref;
391 char ring_timeout[23] = "(none)";
392
393 ao2_lock(trunk);
394
395 if (trunk->ring_timeout) {
396 snprintf(ring_timeout, sizeof(ring_timeout), "%u Seconds", trunk->ring_timeout);
397 }
398
399 ast_cli(a->fd, "=== ---------------------------------------------------------\n"
400 "=== Trunk Name: %s\n"
401 "=== ==> Device: %s\n"
402 "=== ==> AutoContext: %s\n"
403 "=== ==> RingTimeout: %s\n"
404 "=== ==> BargeAllowed: %s\n"
405 "=== ==> HoldAccess: %s\n"
406 "=== ==> Stations ...\n",
407 trunk->name, trunk->device,
408 S_OR(trunk->autocontext, "(none)"),
409 ring_timeout,
410 trunk->barge_disabled ? "No" : "Yes",
411 sla_hold_str(trunk->hold_access));
412
413 AST_LIST_TRAVERSE(&trunk->stations, station_ref, entry) {
414 ast_cli(a->fd, "=== ==> Station name: %s\n", station_ref->station->name);
415 }
416
417 ast_cli(a->fd, "=== ---------------------------------------------------------\n===\n");
418
419 ao2_unlock(trunk);
420 }
422 ast_cli(a->fd, "=============================================================\n\n");
423
424 return CLI_SUCCESS;
425}
const ast_string_field autocontext
Definition: app_sla.c:232
const ast_string_field device
Definition: app_sla.c:232

References a, ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_lock, ao2_ref, ao2_unlock, ast_cli(), AST_LIST_TRAVERSE, sla_trunk::autocontext, sla_trunk::barge_disabled, CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, sla_trunk::device, sla_station_ref::entry, sla_trunk::hold_access, sla_trunk::name, NULL, sla_trunk::ring_timeout, S_OR, sla_hold_str(), sla_trunks, sla_station_ref::station, sla_trunk::stations, and ast_cli_entry::usage.

◆ sla_state()

static enum ast_device_state sla_state ( const char *  data)
static

Definition at line 2250 of file app_sla.c.

2251{
2252 char *buf, *station_name, *trunk_name;
2253 RAII_VAR(struct sla_station *, station, NULL, ao2_cleanup);
2254 struct sla_trunk_ref *trunk_ref;
2256
2257 trunk_name = buf = ast_strdupa(data);
2258 station_name = strsep(&trunk_name, "_");
2259
2260 station = sla_find_station(station_name);
2261 if (station) {
2262 ao2_lock(station);
2263 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) {
2264 if (!strcasecmp(trunk_name, trunk_ref->trunk->name)) {
2265 res = sla_state_to_devstate(trunk_ref->state);
2266 break;
2267 }
2268 }
2269 ao2_unlock(station);
2270 }
2271
2272 if (res == AST_DEVICE_INVALID) {
2273 ast_log(LOG_ERROR, "Could not determine state for trunk %s on station %s!\n", trunk_name, station_name);
2274 }
2275
2276 return res;
2277}
@ AST_DEVICE_INVALID
Definition: devicestate.h:57
char buf[BUFSIZE]
Definition: eagi_proxy.c:66

References ao2_cleanup, ao2_lock, ao2_unlock, AST_DEVICE_INVALID, AST_LIST_TRAVERSE, ast_log, ast_strdupa, buf, sla_trunk_ref::entry, LOG_ERROR, sla_trunk::name, NULL, RAII_VAR, sla_find_station(), sla_state_to_devstate(), sla_trunk_ref::state, strsep(), and sla_trunk_ref::trunk.

Referenced by load_module().

◆ sla_state_to_devstate()

static enum ast_device_state sla_state_to_devstate ( enum sla_trunk_state  state)
static

◆ sla_station_cmp()

static int sla_station_cmp ( void *  obj,
void *  arg,
int  flags 
)
static

Definition at line 2334 of file app_sla.c.

2335{
2336 struct sla_station *station = obj, *station2 = arg;
2337
2338 return !strcasecmp(station->name, station2->name) ? CMP_MATCH | CMP_STOP : 0;
2339}
@ CMP_MATCH
Definition: astobj2.h:1027
@ CMP_STOP
Definition: astobj2.h:1028

References CMP_MATCH, and CMP_STOP.

Referenced by sla_load_config().

◆ sla_station_destructor()

static void sla_station_destructor ( void *  obj)
static

Definition at line 2303 of file app_sla.c.

2304{
2305 struct sla_station *station = obj;
2306
2307 ast_debug(1, "sla_station destructor for '%s'\n", station->name);
2308
2309 if (!ast_strlen_zero(station->autocontext)) {
2310 struct sla_trunk_ref *trunk_ref;
2311
2312 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) {
2313 char exten[AST_MAX_EXTENSION];
2314 char hint[AST_MAX_EXTENSION + 5];
2315 snprintf(exten, sizeof(exten), "%s_%s", station->name, trunk_ref->trunk->name);
2316 snprintf(hint, sizeof(hint), "SLA:%s", exten);
2317 ast_context_remove_extension(station->autocontext, exten, 1, sla_registrar);
2318 ast_context_remove_extension(station->autocontext, hint, PRIORITY_HINT, sla_registrar);
2319 }
2320 }
2321
2322 sla_station_release_refs(station, NULL, 0);
2323
2325}
int ast_context_remove_extension(const char *context, const char *extension, int priority, const char *registrar)
Simply remove extension from context.
Definition: pbx.c:4963
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
Definition: stringfields.h:374

References ast_context_remove_extension(), ast_debug, AST_LIST_TRAVERSE, AST_MAX_EXTENSION, ast_string_field_free_memory, ast_strlen_zero(), sla_trunk_ref::entry, sla_trunk::name, NULL, PRIORITY_HINT, sla_registrar, sla_station_release_refs(), sla_trunk_ref::trunk, and sla_station::trunks.

Referenced by sla_build_station().

◆ sla_station_exec()

static int sla_station_exec ( struct ast_channel chan,
const char *  data 
)
static

Definition at line 1955 of file app_sla.c.

1956{
1957 char *station_name, *trunk_name;
1958 RAII_VAR(struct sla_station *, station, NULL, ao2_cleanup);
1959 RAII_VAR(struct sla_trunk_ref *, trunk_ref, NULL, ao2_cleanup);
1960 char conf_name[MAX_CONFNUM];
1961 struct ast_flags conf_flags = { 0 };
1962
1963 if (ast_strlen_zero(data)) {
1964 ast_log(LOG_WARNING, "Invalid Arguments to SLAStation!\n");
1965 pbx_builtin_setvar_helper(chan, "SLASTATION_STATUS", "FAILURE");
1966 return 0;
1967 }
1968
1969 trunk_name = ast_strdupa(data);
1970 station_name = strsep(&trunk_name, "_");
1971
1972 if (ast_strlen_zero(station_name)) {
1973 ast_log(LOG_WARNING, "Invalid Arguments to SLAStation!\n");
1974 pbx_builtin_setvar_helper(chan, "SLASTATION_STATUS", "FAILURE");
1975 return 0;
1976 }
1977
1978 station = sla_find_station(station_name);
1979
1980 if (!station) {
1981 ast_log(LOG_WARNING, "Station '%s' not found!\n", station_name);
1982 pbx_builtin_setvar_helper(chan, "SLASTATION_STATUS", "FAILURE");
1983 return 0;
1984 }
1985
1986 ao2_lock(station);
1987 if (!ast_strlen_zero(trunk_name)) {
1988 trunk_ref = sla_find_trunk_ref_byname(station, trunk_name);
1989 } else {
1990 trunk_ref = sla_choose_idle_trunk(station);
1991 }
1992 ao2_unlock(station);
1993
1994 if (!trunk_ref) {
1995 if (ast_strlen_zero(trunk_name)) {
1996 ast_log(LOG_NOTICE, "No trunks available for call.\n");
1997 } else {
1998 ast_log(LOG_NOTICE, "Can't join existing call on trunk '%s' due to access controls.\n", trunk_name);
1999 }
2000 pbx_builtin_setvar_helper(chan, "SLASTATION_STATUS", "CONGESTION");
2001 return 0;
2002 }
2003
2004 if (trunk_ref->state == SLA_TRUNK_STATE_ONHOLD_BYME) {
2005 if (ast_atomic_dec_and_test((int *) &trunk_ref->trunk->hold_stations) == 1) {
2007 } else {
2008 trunk_ref->state = SLA_TRUNK_STATE_UP;
2009 ast_devstate_changed(AST_DEVICE_INUSE, AST_DEVSTATE_CACHABLE, "SLA:%s_%s", station->name, trunk_ref->trunk->name);
2010 }
2011 } else if (trunk_ref->state == SLA_TRUNK_STATE_RINGING) {
2012 struct sla_ringing_trunk *ringing_trunk;
2013
2014 ast_mutex_lock(&sla.lock);
2015 AST_LIST_TRAVERSE_SAFE_BEGIN(&sla.ringing_trunks, ringing_trunk, entry) {
2016 if (ringing_trunk->trunk == trunk_ref->trunk) {
2018 break;
2019 }
2020 }
2022 ast_mutex_unlock(&sla.lock);
2023
2024 if (ringing_trunk) {
2025 answer_trunk_chan(ringing_trunk->trunk->chan);
2027
2028 sla_ringing_trunk_destroy(ringing_trunk);
2029
2030 /* Queue up reprocessing ringing trunks, and then ringing stations again */
2033 }
2034 }
2035
2036 trunk_ref->chan = chan;
2037
2038 if (!trunk_ref->trunk->chan) {
2039 ast_mutex_t cond_lock;
2041 pthread_t dont_care;
2042 struct dial_trunk_args args = {
2043 .trunk_ref = trunk_ref,
2044 .station = station,
2045 .cond_lock = &cond_lock,
2046 .cond = &cond,
2047 };
2048 ao2_ref(trunk_ref, 1);
2049 ao2_ref(station, 1);
2051 /* Create a thread to dial the trunk and dump it into the conference.
2052 * However, we want to wait until the trunk has been dialed and the
2053 * conference is created before continuing on here.
2054 * Don't autoservice the channel or we'll have multiple threads
2055 * handling it. dial_trunk services the channel.
2056 */
2065
2066 if (!trunk_ref->trunk->chan) {
2067 ast_debug(1, "Trunk didn't get created. chan: %lx\n", (unsigned long) trunk_ref->trunk->chan);
2068 pbx_builtin_setvar_helper(chan, "SLASTATION_STATUS", "CONGESTION");
2070 trunk_ref->chan = NULL;
2071 return 0;
2072 }
2073 }
2074
2075 if (ast_atomic_fetchadd_int((int *) &trunk_ref->trunk->active_stations, 1) == 0 &&
2077 trunk_ref->trunk->on_hold = 0;
2080 }
2081
2082 snprintf(conf_name, sizeof(conf_name), "SLA_%s", trunk_ref->trunk->name);
2084 ast_answer(chan);
2085
2086 ast_debug(2, "Station %s joining conference %s\n", station->name, conf_name);
2087 conf_run(chan, conf_name, &conf_flags, NULL);
2088
2089 trunk_ref->chan = NULL;
2092 conf_kick_all(chan, conf_name);
2095 }
2096
2097 pbx_builtin_setvar_helper(chan, "SLASTATION_STATUS", "SUCCESS");
2098
2099 return 0;
2100}
static struct sla_trunk_ref * sla_choose_idle_trunk(const struct sla_station *station)
For a given station, choose the highest priority idle trunk.
Definition: app_sla.c:1941
static struct sla_trunk_ref * sla_find_trunk_ref_byname(const struct sla_station *station, const char *name)
Find a trunk reference on a station by name.
Definition: app_sla.c:765
static void * dial_trunk(void *data)
Definition: app_sla.c:1800
int ast_answer(struct ast_channel *chan)
Answer a channel.
Definition: channel.c:2774
@ AST_CONTROL_UNHOLD
#define LOG_NOTICE
struct sla_station * station
Definition: app_sla.c:1795
ast_mutex_t * cond_lock
Definition: app_sla.c:1796
struct sla_trunk_ref * trunk_ref
Definition: app_sla.c:1794
unsigned int on_hold
Definition: app_sla.c:250

References sla_trunk::active_stations, ALL_TRUNK_REFS, answer_trunk_chan(), ao2_cleanup, ao2_lock, ao2_ref, ao2_unlock, args, ast_answer(), ast_atomic_dec_and_test(), ast_atomic_fetchadd_int(), ast_cond_destroy, ast_cond_init, ast_cond_wait, AST_CONTROL_UNHOLD, ast_debug, AST_DEVICE_INUSE, AST_DEVSTATE_CACHABLE, ast_devstate_changed(), ast_indicate(), AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_log, ast_mutex_destroy, ast_mutex_init, ast_mutex_lock, ast_mutex_unlock, ast_pthread_create_detached_background, ast_set_flag, ast_strdupa, ast_strlen_zero(), sla_trunk::chan, sla_trunk_ref::chan, cond, dial_trunk_args::cond_lock, conf_kick_all(), conf_run(), CONFFLAG_MARKEDEXIT, CONFFLAG_PASS_DTMF, CONFFLAG_QUIET, CONFFLAG_SLA_STATION, dial_trunk(), sla_ringing_trunk::entry, sla_trunk::hold_stations, LOG_NOTICE, LOG_WARNING, MAX_CONFNUM, sla_trunk::name, NULL, sla_trunk::on_hold, pbx_builtin_setvar_helper(), RAII_VAR, sla, sla_change_trunk_state(), sla_choose_idle_trunk(), SLA_EVENT_DIAL_STATE, SLA_EVENT_RINGING_TRUNK, sla_find_station(), sla_find_trunk_ref_byname(), sla_queue_event(), sla_ringing_trunk_destroy(), SLA_TRUNK_STATE_IDLE, SLA_TRUNK_STATE_ONHOLD_BYME, SLA_TRUNK_STATE_RINGING, SLA_TRUNK_STATE_UP, sla_trunk_ref::state, dial_trunk_args::station, strsep(), sla_trunk_ref::trunk, sla_ringing_trunk::trunk, and dial_trunk_args::trunk_ref.

Referenced by load_module().

◆ sla_station_is_marked()

static int sla_station_is_marked ( void *  obj,
void *  arg,
int  flags 
)
static

Definition at line 2726 of file app_sla.c.

2727{
2728 struct sla_station *station = obj;
2729
2730 ao2_lock(station);
2731
2732 if (station->mark) {
2733 /* Only remove all of the trunk references if the station itself is going away */
2734 sla_station_release_refs(station, NULL, 0);
2735 } else {
2736 struct sla_trunk_ref *trunk_ref;
2737
2738 /* Otherwise only remove references to trunks no longer in the config */
2739 AST_LIST_TRAVERSE_SAFE_BEGIN(&station->trunks, trunk_ref, entry) {
2740 if (!trunk_ref->mark) {
2741 continue;
2742 }
2744 ao2_ref(trunk_ref, -1);
2745 }
2747 }
2748
2749 ao2_unlock(station);
2750
2751 return station->mark ? CMP_MATCH : 0;
2752}
unsigned int mark
Definition: app_sla.c:209

References ao2_lock, ao2_ref, ao2_unlock, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, CMP_MATCH, sla_trunk_ref::entry, sla_station::mark, sla_trunk_ref::mark, NULL, sla_station_release_refs(), and sla_station::trunks.

Referenced by sla_load_config().

◆ sla_station_mark()

static int sla_station_mark ( void *  obj,
void *  arg,
int  flags 
)
static

Definition at line 2680 of file app_sla.c.

2681{
2682 struct sla_station *station = obj;
2683 struct sla_trunk_ref *trunk_ref;
2684
2685 ao2_lock(station);
2686
2687 station->mark = 1;
2688
2689 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) {
2690 trunk_ref->mark = 1;
2691 }
2692
2693 ao2_unlock(station);
2694
2695 return 0;
2696}

References ao2_lock, ao2_unlock, AST_LIST_TRAVERSE, sla_trunk_ref::entry, sla_station::mark, sla_trunk_ref::mark, and sla_station::trunks.

Referenced by sla_load_config().

◆ sla_station_ref_destructor()

static void sla_station_ref_destructor ( void *  obj)
static

Definition at line 795 of file app_sla.c.

796{
797 struct sla_station_ref *station_ref = obj;
798
799 if (station_ref->station) {
800 ao2_ref(station_ref->station, -1);
801 station_ref->station = NULL;
802 }
803}

References ao2_ref, NULL, and sla_station_ref::station.

Referenced by sla_create_station_ref().

◆ sla_station_release_refs()

static int sla_station_release_refs ( void *  obj,
void *  arg,
int  flags 
)
static

Definition at line 2291 of file app_sla.c.

2292{
2293 struct sla_station *station = obj;
2294 struct sla_trunk_ref *trunk_ref;
2295
2296 while ((trunk_ref = AST_LIST_REMOVE_HEAD(&station->trunks, entry))) {
2297 ao2_ref(trunk_ref, -1);
2298 }
2299
2300 return 0;
2301}
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:833

References ao2_ref, AST_LIST_REMOVE_HEAD, sla_trunk_ref::entry, and sla_station::trunks.

Referenced by sla_destroy(), sla_station_destructor(), and sla_station_is_marked().

◆ sla_stop_ringing_station()

static void sla_stop_ringing_station ( struct sla_ringing_station ringing_station,
enum sla_station_hangup  hangup 
)
static

Definition at line 1038 of file app_sla.c.

1039{
1040 struct sla_ringing_trunk *ringing_trunk;
1041 struct sla_trunk_ref *trunk_ref;
1042 struct sla_station_ref *station_ref;
1043
1044 ast_dial_join(ringing_station->station->dial);
1045 ast_dial_destroy(ringing_station->station->dial);
1046 ringing_station->station->dial = NULL;
1047
1049 goto done;
1050 }
1051
1052 /* If the station is being hung up because of a timeout, then add it to the
1053 * list of timed out stations on each of the ringing trunks. This is so
1054 * that when doing further processing to figure out which stations should be
1055 * ringing, which trunk to answer, determining timeouts, etc., we know which
1056 * ringing trunks we should ignore. */
1057 AST_LIST_TRAVERSE(&sla.ringing_trunks, ringing_trunk, entry) {
1058 AST_LIST_TRAVERSE(&ringing_station->station->trunks, trunk_ref, entry) {
1059 if (ringing_trunk->trunk == trunk_ref->trunk) {
1060 break;
1061 }
1062 }
1063 if (!trunk_ref) {
1064 continue;
1065 }
1066 if (!(station_ref = sla_create_station_ref(ringing_station->station))) {
1067 continue;
1068 }
1069 AST_LIST_INSERT_TAIL(&ringing_trunk->timed_out_stations, station_ref, entry);
1070 }
1071
1072done:
1073 sla_ringing_station_destroy(ringing_station);
1074}
static int hangup(void *data)
Definition: chan_pjsip.c:2520

References ast_dial_destroy(), ast_dial_join(), AST_LIST_INSERT_TAIL, AST_LIST_TRAVERSE, sla_station::dial, done, sla_station_ref::entry, hangup(), NULL, sla, sla_create_station_ref(), sla_ringing_station_destroy(), SLA_STATION_HANGUP_NORMAL, sla_ringing_station::station, sla_ringing_trunk::timed_out_stations, sla_trunk_ref::trunk, sla_ringing_trunk::trunk, and sla_station::trunks.

Referenced by sla_calc_station_timeouts(), and sla_handle_dial_state_event().

◆ sla_stop_ringing_trunk()

static void sla_stop_ringing_trunk ( struct sla_ringing_trunk ringing_trunk)
static

Definition at line 1024 of file app_sla.c.

1025{
1026 struct sla_station_ref *station_ref;
1027
1028 conf_kick_all(ringing_trunk->trunk->chan, ringing_trunk->trunk->name);
1030
1031 while ((station_ref = AST_LIST_REMOVE_HEAD(&ringing_trunk->timed_out_stations, entry))) {
1032 ao2_ref(station_ref, -1);
1033 }
1034
1035 sla_ringing_trunk_destroy(ringing_trunk);
1036}

References ALL_TRUNK_REFS, ao2_ref, AST_LIST_REMOVE_HEAD, sla_trunk::chan, conf_kick_all(), sla_station_ref::entry, sla_trunk::name, NULL, sla_change_trunk_state(), sla_ringing_trunk_destroy(), SLA_TRUNK_STATE_IDLE, sla_ringing_trunk::timed_out_stations, and sla_ringing_trunk::trunk.

Referenced by sla_calc_trunk_timeouts().

◆ sla_thread()

static void * sla_thread ( void *  data)
static

Definition at line 1735 of file app_sla.c.

1736{
1737 struct sla_failed_station *failed_station;
1738 struct sla_ringing_station *ringing_station;
1739
1740 ast_mutex_lock(&sla.lock);
1741
1742 while (!sla.stop) {
1743 struct sla_event *event;
1744 struct timespec ts = { 0, };
1745 unsigned int have_timeout = 0;
1746
1747 if (AST_LIST_EMPTY(&sla.event_q)) {
1748 if ((have_timeout = sla_process_timers(&ts))) {
1749 ast_cond_timedwait(&sla.cond, &sla.lock, &ts);
1750 } else {
1751 ast_cond_wait(&sla.cond, &sla.lock);
1752 }
1753 if (sla.stop) {
1754 break;
1755 }
1756 }
1757
1758 if (have_timeout) {
1760 }
1761
1762 while ((event = AST_LIST_REMOVE_HEAD(&sla.event_q, entry))) {
1763 ast_mutex_unlock(&sla.lock);
1764 switch (event->type) {
1765 case SLA_EVENT_HOLD:
1767 break;
1770 break;
1773 break;
1774 }
1776 ast_mutex_lock(&sla.lock);
1777 }
1778 }
1779
1780 ast_mutex_unlock(&sla.lock);
1781
1782 while ((ringing_station = AST_LIST_REMOVE_HEAD(&sla.ringing_stations, entry))) {
1783 sla_ringing_station_destroy(ringing_station);
1784 }
1785
1786 while ((failed_station = AST_LIST_REMOVE_HEAD(&sla.failed_stations, entry))) {
1787 sla_failed_station_destroy(failed_station);
1788 }
1789
1790 return NULL;
1791}
static void sla_handle_ringing_trunk_event(void)
Definition: app_sla.c:1475
static void sla_handle_dial_state_event(void)
Definition: app_sla.c:1144
static void sla_event_destroy(struct sla_event *event)
Definition: app_sla.c:1720
static void sla_handle_hold_event(struct sla_event *event)
Definition: app_sla.c:1485
static int sla_process_timers(struct timespec *ts)
Calculate the time until the next known event.
Definition: app_sla.c:1680
#define AST_LIST_EMPTY(head)
Checks whether the specified list contains any entries.
Definition: linkedlists.h:450
#define ast_cond_timedwait(cond, mutex, time)
Definition: lock.h:213

References ast_cond_timedwait, ast_cond_wait, AST_LIST_EMPTY, AST_LIST_REMOVE_HEAD, ast_mutex_lock, ast_mutex_unlock, NULL, sla, sla_event_destroy(), SLA_EVENT_DIAL_STATE, SLA_EVENT_HOLD, SLA_EVENT_RINGING_TRUNK, sla_failed_station_destroy(), sla_handle_dial_state_event(), sla_handle_hold_event(), sla_handle_ringing_trunk_event(), sla_process_timers(), and sla_ringing_station_destroy().

Referenced by sla_load_config().

◆ sla_trunk_cmp()

static int sla_trunk_cmp ( void *  obj,
void *  arg,
int  flags 
)
static

Definition at line 2327 of file app_sla.c.

2328{
2329 struct sla_trunk *trunk = obj, *trunk2 = arg;
2330
2331 return !strcasecmp(trunk->name, trunk2->name) ? CMP_MATCH | CMP_STOP : 0;
2332}

References CMP_MATCH, CMP_STOP, and sla_trunk::name.

Referenced by sla_load_config().

◆ sla_trunk_destructor()

static void sla_trunk_destructor ( void *  obj)
static

Definition at line 2381 of file app_sla.c.

2382{
2383 struct sla_trunk *trunk = obj;
2384
2385 ast_debug(1, "sla_trunk destructor for '%s'\n", trunk->name);
2386
2387 if (!ast_strlen_zero(trunk->autocontext)) {
2389 }
2390
2391 sla_trunk_release_refs(trunk, NULL, 0);
2392
2394}

References ast_context_remove_extension(), ast_debug, ast_string_field_free_memory, ast_strlen_zero(), sla_trunk::autocontext, sla_trunk::name, NULL, sla_registrar, and sla_trunk_release_refs().

Referenced by sla_build_trunk().

◆ sla_trunk_exec()

static int sla_trunk_exec ( struct ast_channel chan,
const char *  data 
)
static

Definition at line 2159 of file app_sla.c.

2160{
2161 char conf_name[MAX_CONFNUM];
2162 struct ast_flags conf_flags = { 0 };
2163 RAII_VAR(struct sla_trunk *, trunk, NULL, ao2_cleanup);
2164 struct sla_ringing_trunk *ringing_trunk;
2166 AST_APP_ARG(trunk_name);
2168 );
2169 char *opts[SLA_TRUNK_OPT_ARG_ARRAY_SIZE] = { NULL, };
2170 struct ast_flags opt_flags = { 0 };
2171 char *parse;
2172
2173 if (ast_strlen_zero(data)) {
2174 ast_log(LOG_ERROR, "The SLATrunk application requires an argument, the trunk name\n");
2175 return -1;
2176 }
2177
2178 parse = ast_strdupa(data);
2180 if (args.argc == 2) {
2181 if (ast_app_parse_options(sla_trunk_opts, &opt_flags, opts, args.options)) {
2182 ast_log(LOG_ERROR, "Error parsing options for SLATrunk\n");
2183 return -1;
2184 }
2185 }
2186
2187 trunk = sla_find_trunk(args.trunk_name);
2188
2189 if (!trunk) {
2190 ast_log(LOG_ERROR, "SLA Trunk '%s' not found!\n", args.trunk_name);
2191 pbx_builtin_setvar_helper(chan, "SLATRUNK_STATUS", "FAILURE");
2192 return 0;
2193 }
2194
2195 if (trunk->chan) {
2196 ast_log(LOG_ERROR, "Call came in on %s, but the trunk is already in use!\n", args.trunk_name);
2197 pbx_builtin_setvar_helper(chan, "SLATRUNK_STATUS", "FAILURE");
2198 return 0;
2199 }
2200
2201 trunk->chan = chan;
2202
2203 if (!(ringing_trunk = queue_ringing_trunk(trunk))) {
2204 pbx_builtin_setvar_helper(chan, "SLATRUNK_STATUS", "FAILURE");
2205 return 0;
2206 }
2207
2208 snprintf(conf_name, sizeof(conf_name), "SLA_%s", args.trunk_name);
2210
2211 if (ast_test_flag(&opt_flags, SLA_TRUNK_OPT_MOH)) {
2212 ast_indicate(chan, -1);
2213 ast_set_flag(&conf_flags, CONFFLAG_MOH);
2214 } else {
2216 }
2217
2218 ast_debug(2, "Trunk %s joining conference %s\n", args.trunk_name, conf_name);
2219 conf_run(chan, conf_name, &conf_flags, opts);
2220 trunk->chan = NULL;
2221 trunk->on_hold = 0;
2222
2224
2225 if (!pbx_builtin_getvar_helper(chan, "SLATRUNK_STATUS")) {
2226 pbx_builtin_setvar_helper(chan, "SLATRUNK_STATUS", "SUCCESS");
2227 }
2228
2229 /* Remove the entry from the list of ringing trunks if it is still there. */
2230 ast_mutex_lock(&sla.lock);
2231 AST_LIST_TRAVERSE_SAFE_BEGIN(&sla.ringing_trunks, ringing_trunk, entry) {
2232 if (ringing_trunk->trunk == trunk) {
2234 break;
2235 }
2236 }
2238 ast_mutex_unlock(&sla.lock);
2239 if (ringing_trunk) {
2240 sla_ringing_trunk_destroy(ringing_trunk);
2241 pbx_builtin_setvar_helper(chan, "SLATRUNK_STATUS", "UNANSWERED");
2242 /* Queue reprocessing of ringing trunks to make stations stop ringing
2243 * that shouldn't be ringing after this trunk stopped. */
2245 }
2246
2247 return 0;
2248}
static struct sla_ringing_trunk * queue_ringing_trunk(struct sla_trunk *trunk)
Definition: app_sla.c:2126
static const struct ast_app_option sla_trunk_opts[128]
Definition: app_sla.c:162
#define AST_APP_ARG(name)
Define an application argument.
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application's arguments.
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the 'standard' argument separation process for an application.
int ast_app_parse_options(const struct ast_app_option *options, struct ast_flags *flags, char **args, char *optstr)
Parses a string containing application options and sets flags/arguments.
Definition: main/app.c:3066
const char * pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name)
Return a pointer to the value of the corresponding channel variable.

References ALL_TRUNK_REFS, ao2_cleanup, args, AST_APP_ARG, ast_app_parse_options(), AST_CONTROL_RINGING, ast_debug, AST_DECLARE_APP_ARGS, ast_indicate(), AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_log, ast_mutex_lock, ast_mutex_unlock, ast_set_flag, AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), ast_test_flag, conf_run(), CONFFLAG_MARKEDEXIT, CONFFLAG_MARKEDUSER, CONFFLAG_MOH, CONFFLAG_PASS_DTMF, CONFFLAG_QUIET, LOG_ERROR, MAX_CONFNUM, NULL, options, pbx_builtin_getvar_helper(), pbx_builtin_setvar_helper(), queue_ringing_trunk(), RAII_VAR, sla, sla_change_trunk_state(), SLA_EVENT_RINGING_TRUNK, sla_find_trunk(), sla_queue_event(), sla_ringing_trunk_destroy(), SLA_TRUNK_OPT_ARG_ARRAY_SIZE, SLA_TRUNK_OPT_MOH, sla_trunk_opts, SLA_TRUNK_STATE_IDLE, and sla_ringing_trunk::trunk.

Referenced by load_module().

◆ sla_trunk_is_marked()

static int sla_trunk_is_marked ( void *  obj,
void *  arg,
int  flags 
)
static

Definition at line 2698 of file app_sla.c.

2699{
2700 struct sla_trunk *trunk = obj;
2701
2702 ao2_lock(trunk);
2703
2704 if (trunk->mark) {
2705 /* Only remove all of the station references if the trunk itself is going away */
2706 sla_trunk_release_refs(trunk, NULL, 0);
2707 } else {
2708 struct sla_station_ref *station_ref;
2709
2710 /* Otherwise only remove references to stations no longer in the config */
2711 AST_LIST_TRAVERSE_SAFE_BEGIN(&trunk->stations, station_ref, entry) {
2712 if (!station_ref->mark) {
2713 continue;
2714 }
2716 ao2_ref(station_ref, -1);
2717 }
2719 }
2720
2721 ao2_unlock(trunk);
2722
2723 return trunk->mark ? CMP_MATCH : 0;
2724}
unsigned int mark
Definition: app_sla.c:252

References ao2_lock, ao2_ref, ao2_unlock, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, CMP_MATCH, sla_station_ref::entry, sla_station_ref::mark, sla_trunk::mark, NULL, sla_trunk_release_refs(), and sla_trunk::stations.

Referenced by sla_load_config().

◆ sla_trunk_mark()

static int sla_trunk_mark ( void *  obj,
void *  arg,
int  flags 
)
static

Definition at line 2662 of file app_sla.c.

2663{
2664 struct sla_trunk *trunk = obj;
2665 struct sla_station_ref *station_ref;
2666
2667 ao2_lock(trunk);
2668
2669 trunk->mark = 1;
2670
2671 AST_LIST_TRAVERSE(&trunk->stations, station_ref, entry) {
2672 station_ref->mark = 1;
2673 }
2674
2675 ao2_unlock(trunk);
2676
2677 return 0;
2678}

References ao2_lock, ao2_unlock, AST_LIST_TRAVERSE, sla_station_ref::entry, sla_station_ref::mark, sla_trunk::mark, and sla_trunk::stations.

Referenced by sla_load_config().

◆ sla_trunk_ref_destructor()

static void sla_trunk_ref_destructor ( void *  obj)
static

Definition at line 2102 of file app_sla.c.

2103{
2104 struct sla_trunk_ref *trunk_ref = obj;
2105
2106 if (trunk_ref->trunk) {
2107 ao2_ref(trunk_ref->trunk, -1);
2108 trunk_ref->trunk = NULL;
2109 }
2110}

References ao2_ref, NULL, and sla_trunk_ref::trunk.

Referenced by create_trunk_ref().

◆ sla_trunk_release_refs()

static int sla_trunk_release_refs ( void *  obj,
void *  arg,
int  flags 
)
static

Definition at line 2279 of file app_sla.c.

2280{
2281 struct sla_trunk *trunk = obj;
2282 struct sla_station_ref *station_ref;
2283
2284 while ((station_ref = AST_LIST_REMOVE_HEAD(&trunk->stations, entry))) {
2285 ao2_ref(station_ref, -1);
2286 }
2287
2288 return 0;
2289}

References ao2_ref, AST_LIST_REMOVE_HEAD, sla_station_ref::entry, and sla_trunk::stations.

Referenced by sla_destroy(), sla_trunk_destructor(), and sla_trunk_is_marked().

◆ trunkstate2str()

static const char * trunkstate2str ( enum sla_trunk_state  state)
static

Definition at line 427 of file app_sla.c.

428{
429#define S(e) case e: return # e;
430 switch (state) {
436 }
437 return "Unknown State";
438#undef S
439}
#define S(e)

References S, SLA_TRUNK_STATE_IDLE, SLA_TRUNK_STATE_ONHOLD, SLA_TRUNK_STATE_ONHOLD_BYME, SLA_TRUNK_STATE_RINGING, and SLA_TRUNK_STATE_UP.

Referenced by sla_show_stations().

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 2830 of file app_sla.c.

2831{
2832 int res = 0;
2833
2837
2838 ast_devstate_prov_del("SLA");
2839
2840 sla_destroy();
2841
2842 return res;
2843}
static void sla_destroy(void)
Definition: app_sla.c:2341
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: clicompat.c:30
int ast_devstate_prov_del(const char *label)
Remove device state provider.
Definition: devicestate.c:421
int ast_unregister_application(const char *app)
Unregister an application.
Definition: pbx_app.c:392

References ARRAY_LEN, ast_cli_unregister_multiple(), ast_devstate_prov_del(), ast_unregister_application(), cli_sla, sla_destroy(), slastation_app, and slatrunk_app.

Variable Documentation

◆ __mod_info

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Shared Line Appearances" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .support_level = AST_MODULE_SUPPORT_EXTENDED, .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_DEVSTATE_PROVIDER, }
static

Definition at line 2881 of file app_sla.c.

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 2881 of file app_sla.c.

◆ attempt_callerid

unsigned int attempt_callerid

Attempt to handle CallerID, even though it is known not to work properly in some situations.

Definition at line 345 of file app_sla.c.

◆ cli_sla

struct ast_cli_entry cli_sla[]
static
Initial value:
= {
{ .handler = sla_show_trunks , .summary = "Show SLA Trunks" ,},
{ .handler = sla_show_stations , .summary = "Show SLA Stations" ,},
}
static char * sla_show_stations(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: app_sla.c:441
static char * sla_show_trunks(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: app_sla.c:367

Definition at line 520 of file app_sla.c.

Referenced by load_module(), and unload_module().

◆ cond

ast_cond_t cond

◆ 

struct { ... } event_q

◆ 

struct { ... } failed_stations

◆ first

struct sla_event* first

◆ last

struct sla_event* last

◆ lock

Definition at line 337 of file app_sla.c.

Referenced by __ast_bucket_scheme_register(), __ast_cli_generator(), __ast_codec_register_with_format(), __ast_format_interface_register(), __ast_named_lock_get(), action_lock_unlock_helper(), add_headers_to_message(), add_masquerade_store(), add_transferer_role(), aeap_transport_read(), aeap_transport_write(), after_bridge_cb_find(), after_bridge_cb_setup(), aor_alloc(), ari_ws_session_reset(), ast_aeap_connect(), ast_ari_add_handler(), ast_bridge_basic_set_flags(), ast_bridge_read_after_goto(), ast_bridge_transfer_attended(), ast_bridge_transfer_blind(), ast_cdr_fork(), ast_channel_move(), ast_clear_mixmonitor_methods(), ast_config_engine_deregister(), ast_config_engine_register(), ast_endpoint_snapshot_create(), ast_format_cache_set(), ast_get_extension_for_mime_type(), ast_get_format_for_file_ext(), ast_localtime_wakeup_monitor(), ast_realtime_is_mapping_defined(), ast_serializer_shutdown_group_join(), ast_set_mixmonitor_methods(), ast_sip_format_endpoint_ami(), ast_sip_identify_endpoint(), ast_sip_publish_client_remove(), ast_sip_publish_client_send(), ast_sip_register_endpoint_formatter(), ast_sip_register_endpoint_identifier_with_name(), ast_sip_register_event_publisher_handler(), ast_sip_register_supplement(), ast_sip_session_add_supplements(), ast_sip_session_register_sdp_handler(), ast_sip_session_register_supplement_with_module(), ast_sip_session_unregister_supplement(), ast_sip_unregister_endpoint_formatter(), ast_sip_unregister_endpoint_identifier(), ast_sip_unregister_event_publisher_handler(), ast_sip_unregister_supplement(), ast_spinlock_destroy(), ast_spinlock_init(), ast_spinlock_lock(), ast_spinlock_trylock(), ast_spinlock_unlock(), ast_start_mixmonitor(), ast_stop_mixmonitor(), ast_taskprocessor_set_local(), AST_TEST_DEFINE(), ast_threadpool_push(), ast_threadpool_set_size(), ast_unreal_channel_push_to_bridge(), bridge_base_init(), bridge_basic_change_personality(), bridge_register(), bucket_file_wizard_retrieve(), bucket_wizard_retrieve(), builtin_feature_get_exten(), cancel_and_unpublish(), channel_get_external_vars(), clear_stimulus_queue(), cli_show_channels(), cli_show_endpoint_identifiers(), complex_task(), conf_announce_channel_push(), consumer_exec(), consumer_exec_sync(), consumer_should_stay(), consumer_wait_for(), consumer_wait_for_completion(), expire_contact(), find_engine(), find_route(), generic_lock_unlock_helper(), get_park_common_datastore_copy(), get_publishes_and_update_state(), get_root_handler(), get_wait_bridge_wrapper(), handle_bridge_enter(), handle_cli_core_show_config_mappings(), handle_local_optimization_begin(), handle_local_optimization_end(), has_complex_started(), has_masquerade_store(), internal_feature_read(), internal_feature_write(), internal_featuremap_read(), internal_featuremap_write(), load_module(), load_task(), lock_it(), lock_thread(), message_sink_cb(), mid_test_sync(), one_protocol(), persistent_endpoint_find_or_create(), playback_cancel(), playback_final_update(), playback_first_update(), playback_forward(), playback_pause(), playback_restart(), playback_reverse(), playback_stop(), playback_unpause(), poke_worker(), prometheus_callback_register(), prometheus_callback_unregister(), prometheus_last_scrape_time_get(), prometheus_metric_register(), prometheus_metric_registered_count(), prometheus_metric_unregister(), publisher_client_send(), recording_set_state(), reload_module(), remove_hooks_on_personality_change(), remove_masquerade_store(), remove_stasis_subscriptions(), report_fax_status(), report_receive_fax_status(), report_send_fax_status(), set_touch_variables(), shutdown_has_completed(), shutdown_poke(), shutdown_task_exec(), shutdown_waitfor_completion(), shutdown_waitfor_start(), signal_condition(), simple_task(), sip_outbound_publish_callback(), sip_publisher_service_queue(), sla_queue_event_full(), snoop_determine_format(), sorcery_observer_created(), sorcery_observer_deleted(), sorcery_observer_loaded(), sorcery_observer_updated(), stasis_app_control_record(), stasis_app_playback_get_state(), stasis_app_playback_operation(), stasis_app_recording_operation(), stasis_message_sink_dtor(), stasis_message_sink_should_stay(), stasis_message_sink_wait_for(), stasis_message_sink_wait_for_count(), task(), task_wait(), test_emptied(), test_state_changed(), test_sub(), test_task_pushed(), threadpool_active_thread_idle(), threadpool_idle_thread_dead(), threadpool_tps_emptied(), threadpool_tps_task_pushed(), threadpool_zombie_thread_dead(), unload_module(), unlock_it(), wait_for_completion(), wait_for_complex_completion(), wait_for_complex_start(), wait_for_empty_notice(), wait_for_stimulus(), wait_for_task_pushed(), wait_until_thread_state(), and worker_set_state().

◆ 

struct { ... } ringing_stations

◆ 

struct { ... } ringing_trunks

◆ 

struct { ... } sla

◆ sla_framehook_datastore

const struct ast_datastore_info sla_framehook_datastore
static
Initial value:
= {
.type = "app_sla",
}

Definition at line 616 of file app_sla.c.

Referenced by attach_framehook(), and remove_framehook().

◆ sla_registrar

const char sla_registrar[] = "SLA"
static

◆ sla_stations

struct ao2_container* sla_stations
static

◆ sla_trunk_opts

const struct ast_app_option sla_trunk_opts[128] = { [ 'M' ] = { .flag = SLA_TRUNK_OPT_MOH , .arg_index = SLA_TRUNK_OPT_ARG_MOH_CLASS + 1 }, }
static

Definition at line 162 of file app_sla.c.

Referenced by sla_trunk_exec().

◆ sla_trunks

struct ao2_container* sla_trunks
static

◆ slastation_app

const char* const slastation_app = "SLAStation"
static

Definition at line 133 of file app_sla.c.

Referenced by load_module(), sla_build_station(), and unload_module().

◆ slatrunk_app

const char* const slatrunk_app = "SLATrunk"
static

Definition at line 134 of file app_sla.c.

Referenced by load_module(), sla_build_trunk(), and unload_module().

◆ stop

unsigned int stop

◆ thread

pthread_t thread