#include "asterisk.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <zaptel/zaptel.h>
#include "asterisk/lock.h"
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/config.h"
#include "asterisk/app.h"
#include "asterisk/dsp.h"
#include "asterisk/musiconhold.h"
#include "asterisk/manager.h"
#include "asterisk/options.h"
#include "asterisk/cli.h"
#include "asterisk/say.h"
#include "asterisk/utils.h"
#include "asterisk/translate.h"
#include "asterisk/ulaw.h"
#include "asterisk/astobj.h"
#include "asterisk/devicestate.h"
#include "asterisk/dial.h"
#include "asterisk/causes.h"
#include "enter.h"
#include "leave.h"
Go to the source code of this file.
Data Structures | |
struct | ast_conf_user |
struct | ast_conference |
The MeetMe Conference object. More... | |
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_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 |
struct | sla_trunk |
struct | sla_trunk_ref |
struct | volume |
Defines | |
#define | AST_FRAME_BITS 32 |
#define | CONF_SIZE 320 |
#define | CONFIG_FILE_NAME "meetme.conf" |
#define | DEFAULT_AUDIO_BUFFERS 32 |
#define | MAX_CONFNUM 80 |
#define | MAX_PIN 80 |
#define | MEETME_DELAYDETECTENDTALK 1000 |
#define | MEETME_DELAYDETECTTALK 300 |
#define | S(e) case e: return # e; |
#define | SLA_CONFIG_FILE "sla.conf" |
Enumerations | |
enum | { ADMINFLAG_MUTED = (1 << 1), ADMINFLAG_SELFMUTED = (1 << 2), ADMINFLAG_KICKME = (1 << 3) } |
enum | { CONFFLAG_ADMIN = (1 << 0), CONFFLAG_MONITOR = (1 << 1), CONFFLAG_POUNDEXIT = (1 << 2), CONFFLAG_STARMENU = (1 << 3), CONFFLAG_TALKER = (1 << 4), CONFFLAG_QUIET = (1 << 5), CONFFLAG_ANNOUNCEUSERCOUNT = (1 << 6), CONFFLAG_AGI = (1 << 7), CONFFLAG_MOH = (1 << 8), CONFFLAG_MARKEDEXIT = (1 << 9), CONFFLAG_WAITMARKED = (1 << 10), CONFFLAG_EXIT_CONTEXT = (1 << 11), CONFFLAG_MARKEDUSER = (1 << 12), CONFFLAG_INTROUSER = (1 << 13), CONFFLAG_RECORDCONF = (1<< 14), CONFFLAG_MONITORTALKER = (1 << 15), CONFFLAG_DYNAMIC = (1 << 16), CONFFLAG_DYNAMICPIN = (1 << 17), CONFFLAG_EMPTY = (1 << 18), CONFFLAG_EMPTYNOPIN = (1 << 19), CONFFLAG_ALWAYSPROMPT = (1 << 20), CONFFLAG_OPTIMIZETALKER = (1 << 21), CONFFLAG_NOONLYPERSON = (1 << 22), CONFFLAG_INTROUSERNOREVIEW = (1 << 23), CONFFLAG_STARTMUTED = (1 << 24), CONFFLAG_PASS_DTMF = (1 << 25), CONFFLAG_SLA_STATION = (1 << 26), CONFFLAG_SLA_TRUNK = (1 << 27) } |
enum | { OPT_ARG_WAITMARKED = 0, OPT_ARG_ARRAY_SIZE = 1 } |
enum | entrance_sound { ENTER, LEAVE } |
enum | recording_state { MEETME_RECORD_OFF, MEETME_RECORD_STARTED, MEETME_RECORD_ACTIVE, MEETME_RECORD_TERMINATE } |
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 } |
enum | volume_action { VOL_UP, VOL_DOWN } |
Functions | |
static int | action_meetmemute (struct mansession *s, const struct message *m) |
static int | action_meetmeunmute (struct mansession *s, const struct message *m) |
static int | admin_exec (struct ast_channel *chan, void *data) |
The MeetMeadmin application. | |
AST_APP_OPTIONS (meetme_opts, BEGIN_OPTIONS AST_APP_OPTION('A', CONFFLAG_MARKEDUSER), AST_APP_OPTION('a', CONFFLAG_ADMIN), AST_APP_OPTION('b', CONFFLAG_AGI), AST_APP_OPTION('c', CONFFLAG_ANNOUNCEUSERCOUNT), AST_APP_OPTION('D', CONFFLAG_DYNAMICPIN), AST_APP_OPTION('d', CONFFLAG_DYNAMIC), AST_APP_OPTION('E', CONFFLAG_EMPTYNOPIN), AST_APP_OPTION('e', CONFFLAG_EMPTY), AST_APP_OPTION('F', CONFFLAG_PASS_DTMF), AST_APP_OPTION('i', CONFFLAG_INTROUSER), AST_APP_OPTION('I', CONFFLAG_INTROUSERNOREVIEW), AST_APP_OPTION('M', CONFFLAG_MOH), AST_APP_OPTION('m', CONFFLAG_STARTMUTED), AST_APP_OPTION('o', CONFFLAG_OPTIMIZETALKER), AST_APP_OPTION('P', CONFFLAG_ALWAYSPROMPT), AST_APP_OPTION('p', CONFFLAG_POUNDEXIT), AST_APP_OPTION('q', CONFFLAG_QUIET), AST_APP_OPTION('r', CONFFLAG_RECORDCONF), AST_APP_OPTION('s', CONFFLAG_STARMENU), AST_APP_OPTION('T', CONFFLAG_MONITORTALKER), AST_APP_OPTION('l', CONFFLAG_MONITOR), AST_APP_OPTION('t', CONFFLAG_TALKER), AST_APP_OPTION_ARG('w', CONFFLAG_WAITMARKED, OPT_ARG_WAITMARKED), AST_APP_OPTION('X', CONFFLAG_EXIT_CONTEXT), AST_APP_OPTION('x', CONFFLAG_MARKEDEXIT), AST_APP_OPTION('1', CONFFLAG_NOONLYPERSON), END_OPTIONS) | |
static | AST_LIST_HEAD_STATIC (confs, ast_conference) |
AST_MODULE_INFO (ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT,"MeetMe conference bridge",.load=load_module,.unload=unload_module,.reload=reload,) | |
static | AST_RWLIST_HEAD_STATIC (sla_trunks, sla_trunk) |
static | AST_RWLIST_HEAD_STATIC (sla_stations, sla_station) |
static struct ast_conference * | build_conf (char *confno, char *pin, char *pinadmin, int make, int dynamic, int refcount) |
Find or create a conference. | |
static int | careful_write (int fd, unsigned char *data, int len, int block) |
static char * | complete_meetmecmd (const char *line, const char *word, int pos, int state) |
static int | conf_exec (struct ast_channel *chan, void *data) |
The meetme() application. | |
static void | conf_flush (int fd, struct ast_channel *chan) |
static int | conf_free (struct ast_conference *conf) |
static void | conf_play (struct ast_channel *chan, struct ast_conference *conf, enum entrance_sound sound) |
static void | conf_queue_dtmf (const struct ast_conference *conf, const struct ast_conf_user *sender, struct ast_frame *f) |
static int | conf_run (struct ast_channel *chan, struct ast_conference *conf, int confflags, char *optargs[]) |
static int | count_exec (struct ast_channel *chan, void *data) |
The MeetmeCount application. | |
static struct sla_trunk_ref * | create_trunk_ref (struct sla_trunk *trunk) |
static void | destroy_station (struct sla_station *station) |
static void | destroy_trunk (struct sla_trunk *trunk) |
static void * | dial_trunk (void *data) |
static int | dispose_conf (struct ast_conference *conf) |
static struct ast_conference * | find_conf (struct ast_channel *chan, char *confno, int make, int dynamic, char *dynamic_pin, size_t pin_buf_len, int refcount, struct ast_flags *confflags) |
static struct ast_conference * | find_conf_realtime (struct ast_channel *chan, char *confno, int make, int dynamic, char *dynamic_pin, size_t pin_buf_len, int refcount, struct ast_flags *confflags) |
static struct ast_conf_user * | find_user (struct ast_conference *conf, char *callerident) |
static char * | istalking (int x) |
static int | load_config (int reload) |
static void | load_config_meetme (void) |
static int | load_module (void) |
static int | meetme_cmd (int fd, int argc, char **argv) |
static int | meetmemute (struct mansession *s, const struct message *m, int mute) |
static int | meetmestate (const char *data) |
Callback for devicestate providers. | |
static struct sla_ringing_trunk * | queue_ringing_trunk (struct sla_trunk *trunk) |
static void * | recordthread (void *args) |
static int | reload (void) |
static void | reset_volumes (struct ast_conf_user *user) |
static void * | run_station (void *data) |
static int | set_listen_volume (struct ast_conf_user *user, int volume) |
static int | set_talk_volume (struct ast_conf_user *user, int volume) |
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. | |
static int | sla_calc_station_timeouts (unsigned int *timeout) |
Process station ring timeouts. | |
static int | sla_calc_trunk_timeouts (unsigned int *timeout) |
Process trunk ring timeouts. | |
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. | |
static int | sla_check_inuse_station (const struct sla_station *station) |
Check to see if a station is in use. | |
static int | sla_check_ringing_station (const struct sla_station *station) |
Check to see if this station is already ringing. | |
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. | |
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. | |
static struct sla_trunk_ref * | sla_choose_idle_trunk (const struct sla_station *station) |
For a given station, choose the highest priority idle trunk. | |
static struct sla_ringing_trunk * | sla_choose_ringing_trunk (struct sla_station *station, struct sla_trunk_ref **trunk_ref, int remove) |
Choose the highest priority ringing trunk for a station. | |
static struct sla_ringing_station * | sla_create_ringing_station (struct sla_station *station) |
static struct sla_station_ref * | sla_create_station_ref (struct sla_station *station) |
static void | sla_destroy (void) |
static void | sla_dial_state_callback (struct ast_dial *dial) |
static struct sla_station * | sla_find_station (const char *name) |
Find an SLA station by name. | |
static struct sla_trunk * | sla_find_trunk (const char *name) |
Find an SLA trunk by name. | |
static struct sla_trunk_ref * | sla_find_trunk_ref (const struct sla_station *station, const struct sla_trunk *trunk) |
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. | |
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_load_config (void) |
static int | sla_process_timers (struct timespec *ts) |
Calculate the time until the next known event. | |
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, struct ast_conference *conf) |
Queue a SLA event from the conference. | |
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. | |
static void | sla_ring_stations (void) |
Ring stations based on current set of ringing trunks. | |
static int | sla_show_stations (int fd, int argc, char **argv) |
static int | sla_show_trunks (int fd, int argc, char **argv) |
static int | sla_state (const char *data) |
static int | sla_station_exec (struct ast_channel *chan, void *data) |
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_exec (struct ast_channel *chan, void *data) |
static const char * | trunkstate2str (enum sla_trunk_state state) |
static void | tweak_listen_volume (struct ast_conf_user *user, enum volume_action action) |
static void | tweak_talk_volume (struct ast_conf_user *user, enum volume_action action) |
static void | tweak_volume (struct volume *vol, enum volume_action action) |
static int | unload_module (void) |
Variables | |
static const char * | app = "MeetMe" |
static const char * | app2 = "MeetMeCount" |
static const char * | app3 = "MeetMeAdmin" |
static int | audio_buffers |
static struct ast_cli_entry | cli_meetme [] |
static unsigned int | conf_map [1024] = {0, } |
static const char * | descrip |
static const char * | descrip2 |
static const char * | descrip3 |
static char const | gain_map [] |
static char | meetme_usage [] |
struct { | |
ast_cond_t cond | |
ast_mutex_t lock | |
pthread_t thread | |
} | sla |
A structure for data used by the sla thread. | |
static const char | sla_registrar [] = "SLA" |
static const char | sla_show_stations_usage [] |
static const char | sla_show_trunks_usage [] |
static const char * | slastation_app = "SLAStation" |
static const char * | slastation_desc |
static const char * | slastation_synopsis = "Shared Line Appearance Station" |
static const char * | slatrunk_app = "SLATrunk" |
static const char * | slatrunk_desc |
static const char * | slatrunk_synopsis = "Shared Line Appearance Trunk" |
static const char * | synopsis = "MeetMe conference bridge" |
static const char * | synopsis2 = "MeetMe participant count" |
static const char * | synopsis3 = "MeetMe conference Administration" |
Definition in file app_meetme.c.
#define AST_FRAME_BITS 32 |
Definition at line 88 of file app_meetme.c.
Referenced by conf_free(), conf_run(), and recordthread().
#define CONF_SIZE 320 |
#define CONFIG_FILE_NAME "meetme.conf" |
Definition at line 73 of file app_meetme.c.
Referenced by conf_exec(), find_conf(), and load_config_meetme().
#define DEFAULT_AUDIO_BUFFERS 32 |
each buffer is 20ms, so this is 640ms total
Definition at line 77 of file app_meetme.c.
Referenced by load_config_meetme().
#define MAX_CONFNUM 80 |
Definition at line 315 of file app_meetme.c.
Referenced by conf_exec(), dial_trunk(), run_station(), sla_station_exec(), and sla_trunk_exec().
#define MAX_PIN 80 |
#define MEETME_DELAYDETECTENDTALK 1000 |
#define MEETME_DELAYDETECTTALK 300 |
#define S | ( | e | ) | case e: return # e; |
Referenced by sms_readfile(), and trunkstate2str().
#define SLA_CONFIG_FILE "sla.conf" |
Definition at line 74 of file app_meetme.c.
Referenced by sla_build_station(), sla_build_trunk(), and sla_load_config().
anonymous enum |
ADMINFLAG_MUTED | User is muted |
ADMINFLAG_SELFMUTED | User muted self |
ADMINFLAG_KICKME | User has been kicked |
Definition at line 79 of file app_meetme.c.
00079 { 00080 ADMINFLAG_MUTED = (1 << 1), /*!< User is muted */ 00081 ADMINFLAG_SELFMUTED = (1 << 2), /*!< User muted self */ 00082 ADMINFLAG_KICKME = (1 << 3) /*!< User has been kicked */ 00083 };
anonymous enum |
CONFFLAG_ADMIN | user has admin access on the conference |
CONFFLAG_MONITOR | If set the user can only receive audio from the conference |
CONFFLAG_POUNDEXIT | If set asterisk will exit conference when '#' is pressed |
CONFFLAG_STARMENU | If set asterisk will provide a menu to the user when '*' is pressed |
CONFFLAG_TALKER | If set the use can only send audio to the conference |
CONFFLAG_QUIET | If set there will be no enter or leave sounds |
CONFFLAG_ANNOUNCEUSERCOUNT | If set, when user joins the conference, they will be told the number of users that are already in |
CONFFLAG_AGI | Set to run AGI Script in Background |
CONFFLAG_MOH | Set to have music on hold when user is alone in conference |
CONFFLAG_MARKEDEXIT | If set the MeetMe will return if all marked with this flag left |
CONFFLAG_WAITMARKED | If set, the MeetMe will wait until a marked user enters |
CONFFLAG_EXIT_CONTEXT | If set, the MeetMe will exit to the specified context |
CONFFLAG_MARKEDUSER | If set, the user will be marked |
CONFFLAG_INTROUSER | If set, user will be ask record name on entry of conference |
CONFFLAG_RECORDCONF | If set, the MeetMe will be recorded |
CONFFLAG_MONITORTALKER | If set, the user will be monitored if the user is talking or not |
CONFFLAG_DYNAMIC | |
CONFFLAG_DYNAMICPIN | |
CONFFLAG_EMPTY | |
CONFFLAG_EMPTYNOPIN | |
CONFFLAG_ALWAYSPROMPT | |
CONFFLAG_OPTIMIZETALKER | If set, treats talking users as muted users |
CONFFLAG_NOONLYPERSON | If set, won't speak the extra prompt when the first person enters the conference |
CONFFLAG_INTROUSERNOREVIEW | If set, user will be asked to record name on entry of conference without review |
CONFFLAG_STARTMUTED | If set, the user will be initially self-muted |
CONFFLAG_PASS_DTMF | Pass DTMF through the conference |
CONFFLAG_SLA_STATION | This is a SLA station. (Only for use by the SLA applications.) |
CONFFLAG_SLA_TRUNK | This is a SLA trunk. (Only for use by the SLA applications.) |
Definition at line 109 of file app_meetme.c.
00109 { 00110 /*! user has admin access on the conference */ 00111 CONFFLAG_ADMIN = (1 << 0), 00112 /*! If set the user can only receive audio from the conference */ 00113 CONFFLAG_MONITOR = (1 << 1), 00114 /*! If set asterisk will exit conference when '#' is pressed */ 00115 CONFFLAG_POUNDEXIT = (1 << 2), 00116 /*! If set asterisk will provide a menu to the user when '*' is pressed */ 00117 CONFFLAG_STARMENU = (1 << 3), 00118 /*! If set the use can only send audio to the conference */ 00119 CONFFLAG_TALKER = (1 << 4), 00120 /*! If set there will be no enter or leave sounds */ 00121 CONFFLAG_QUIET = (1 << 5), 00122 /*! If set, when user joins the conference, they will be told the number 00123 * of users that are already in */ 00124 CONFFLAG_ANNOUNCEUSERCOUNT = (1 << 6), 00125 /*! Set to run AGI Script in Background */ 00126 CONFFLAG_AGI = (1 << 7), 00127 /*! Set to have music on hold when user is alone in conference */ 00128 CONFFLAG_MOH = (1 << 8), 00129 /*! If set the MeetMe will return if all marked with this flag left */ 00130 CONFFLAG_MARKEDEXIT = (1 << 9), 00131 /*! If set, the MeetMe will wait until a marked user enters */ 00132 CONFFLAG_WAITMARKED = (1 << 10), 00133 /*! If set, the MeetMe will exit to the specified context */ 00134 CONFFLAG_EXIT_CONTEXT = (1 << 11), 00135 /*! If set, the user will be marked */ 00136 CONFFLAG_MARKEDUSER = (1 << 12), 00137 /*! If set, user will be ask record name on entry of conference */ 00138 CONFFLAG_INTROUSER = (1 << 13), 00139 /*! If set, the MeetMe will be recorded */ 00140 CONFFLAG_RECORDCONF = (1<< 14), 00141 /*! If set, the user will be monitored if the user is talking or not */ 00142 CONFFLAG_MONITORTALKER = (1 << 15), 00143 CONFFLAG_DYNAMIC = (1 << 16), 00144 CONFFLAG_DYNAMICPIN = (1 << 17), 00145 CONFFLAG_EMPTY = (1 << 18), 00146 CONFFLAG_EMPTYNOPIN = (1 << 19), 00147 CONFFLAG_ALWAYSPROMPT = (1 << 20), 00148 /*! If set, treats talking users as muted users */ 00149 CONFFLAG_OPTIMIZETALKER = (1 << 21), 00150 /*! If set, won't speak the extra prompt when the first person 00151 * enters the conference */ 00152 CONFFLAG_NOONLYPERSON = (1 << 22), 00153 /*! If set, user will be asked to record name on entry of conference 00154 * without review */ 00155 CONFFLAG_INTROUSERNOREVIEW = (1 << 23), 00156 /*! If set, the user will be initially self-muted */ 00157 CONFFLAG_STARTMUTED = (1 << 24), 00158 /*! Pass DTMF through the conference */ 00159 CONFFLAG_PASS_DTMF = (1 << 25), 00160 /*! This is a SLA station. (Only for use by the SLA applications.) */ 00161 CONFFLAG_SLA_STATION = (1 << 26), 00162 /*! This is a SLA trunk. (Only for use by the SLA applications.) */ 00163 CONFFLAG_SLA_TRUNK = (1 << 27), 00164 };
anonymous enum |
Definition at line 166 of file app_meetme.c.
00166 { 00167 OPT_ARG_WAITMARKED = 0, 00168 OPT_ARG_ARRAY_SIZE = 1, 00169 };
enum entrance_sound |
enum recording_state |
Definition at line 100 of file app_meetme.c.
00100 { 00101 MEETME_RECORD_OFF, 00102 MEETME_RECORD_STARTED, 00103 MEETME_RECORD_ACTIVE, 00104 MEETME_RECORD_TERMINATE 00105 };
enum sla_event_type |
Event types that can be queued up for the SLA thread.
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 470 of file app_meetme.c.
00470 { 00471 /*! A station has put the call on hold */ 00472 SLA_EVENT_HOLD, 00473 /*! The state of a dial has changed */ 00474 SLA_EVENT_DIAL_STATE, 00475 /*! The state of a ringing trunk has changed */ 00476 SLA_EVENT_RINGING_TRUNK, 00477 };
enum sla_hold_access |
Definition at line 384 of file app_meetme.c.
00384 { 00385 /*! This means that any station can put it on hold, and any station 00386 * can retrieve the call from hold. */ 00387 SLA_HOLD_OPEN, 00388 /*! This means that only the station that put the call on hold may 00389 * retrieve it from hold. */ 00390 SLA_HOLD_PRIVATE, 00391 };
enum sla_station_hangup |
Definition at line 503 of file app_meetme.c.
00503 { 00504 SLA_STATION_HANGUP_NORMAL, 00505 SLA_STATION_HANGUP_TIMEOUT, 00506 };
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 |
Definition at line 376 of file app_meetme.c.
00376 { 00377 SLA_TRUNK_STATE_IDLE, 00378 SLA_TRUNK_STATE_RINGING, 00379 SLA_TRUNK_STATE_UP, 00380 SLA_TRUNK_STATE_ONHOLD, 00381 SLA_TRUNK_STATE_ONHOLD_BYME, 00382 };
enum sla_which_trunk_refs |
Definition at line 371 of file app_meetme.c.
00371 { 00372 ALL_TRUNK_REFS, 00373 INACTIVE_TRUNK_REFS, 00374 };
enum volume_action |
static int action_meetmemute | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 2972 of file app_meetme.c.
References meetmemute().
Referenced by load_module().
02973 { 02974 return meetmemute(s, m, 1); 02975 }
static int action_meetmeunmute | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 2977 of file app_meetme.c.
References meetmemute().
Referenced by load_module().
02978 { 02979 return meetmemute(s, m, 0); 02980 }
static int admin_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
The MeetMeadmin application.
Definition at line 2758 of file app_meetme.c.
References ADMINFLAG_KICKME, ADMINFLAG_MUTED, ADMINFLAG_SELFMUTED, ast_conf_user::adminflags, AST_APP_ARG, AST_DECLARE_APP_ARGS, AST_LIST_LAST, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_module_user_add, ast_module_user_remove, AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), CONFFLAG_ADMIN, ast_conference::confno, dispose_conf(), find_user(), ast_conference::locked, LOG_NOTICE, LOG_WARNING, ast_conference::refcount, reset_volumes(), tweak_listen_volume(), tweak_talk_volume(), ast_conf_user::userflags, VOL_DOWN, and VOL_UP.
Referenced by load_module(), meetme_cmd(), run_station(), sla_station_exec(), and sla_stop_ringing_trunk().
02758 { 02759 char *params; 02760 struct ast_conference *cnf; 02761 struct ast_conf_user *user = NULL; 02762 struct ast_module_user *u; 02763 AST_DECLARE_APP_ARGS(args, 02764 AST_APP_ARG(confno); 02765 AST_APP_ARG(command); 02766 AST_APP_ARG(user); 02767 ); 02768 02769 if (ast_strlen_zero(data)) { 02770 ast_log(LOG_WARNING, "MeetMeAdmin requires an argument!\n"); 02771 return -1; 02772 } 02773 02774 u = ast_module_user_add(chan); 02775 02776 AST_LIST_LOCK(&confs); 02777 02778 params = ast_strdupa(data); 02779 AST_STANDARD_APP_ARGS(args, params); 02780 02781 if (!args.command) { 02782 ast_log(LOG_WARNING, "MeetmeAdmin requires a command!\n"); 02783 AST_LIST_UNLOCK(&confs); 02784 ast_module_user_remove(u); 02785 return -1; 02786 } 02787 AST_LIST_TRAVERSE(&confs, cnf, list) { 02788 if (!strcmp(cnf->confno, args.confno)) 02789 break; 02790 } 02791 02792 if (!cnf) { 02793 ast_log(LOG_WARNING, "Conference number '%s' not found!\n", args.confno); 02794 AST_LIST_UNLOCK(&confs); 02795 ast_module_user_remove(u); 02796 return 0; 02797 } 02798 02799 ast_atomic_fetchadd_int(&cnf->refcount, 1); 02800 02801 if (args.user) 02802 user = find_user(cnf, args.user); 02803 02804 switch (*args.command) { 02805 case 76: /* L: Lock */ 02806 cnf->locked = 1; 02807 break; 02808 case 108: /* l: Unlock */ 02809 cnf->locked = 0; 02810 break; 02811 case 75: /* K: kick all users */ 02812 AST_LIST_TRAVERSE(&cnf->userlist, user, list) 02813 user->adminflags |= ADMINFLAG_KICKME; 02814 break; 02815 case 101: /* e: Eject last user*/ 02816 user = AST_LIST_LAST(&cnf->userlist); 02817 if (!(user->userflags & CONFFLAG_ADMIN)) 02818 user->adminflags |= ADMINFLAG_KICKME; 02819 else 02820 ast_log(LOG_NOTICE, "Not kicking last user, is an Admin!\n"); 02821 break; 02822 case 77: /* M: Mute */ 02823 if (user) { 02824 user->adminflags |= ADMINFLAG_MUTED; 02825 } else 02826 ast_log(LOG_NOTICE, "Specified User not found!\n"); 02827 break; 02828 case 78: /* N: Mute all (non-admin) users */ 02829 AST_LIST_TRAVERSE(&cnf->userlist, user, list) { 02830 if (!(user->userflags & CONFFLAG_ADMIN)) 02831 user->adminflags |= ADMINFLAG_MUTED; 02832 } 02833 break; 02834 case 109: /* m: Unmute */ 02835 if (user) { 02836 user->adminflags &= ~(ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED); 02837 } else 02838 ast_log(LOG_NOTICE, "Specified User not found!\n"); 02839 break; 02840 case 110: /* n: Unmute all users */ 02841 AST_LIST_TRAVERSE(&cnf->userlist, user, list) 02842 user->adminflags &= ~(ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED); 02843 break; 02844 case 107: /* k: Kick user */ 02845 if (user) 02846 user->adminflags |= ADMINFLAG_KICKME; 02847 else 02848 ast_log(LOG_NOTICE, "Specified User not found!\n"); 02849 break; 02850 case 118: /* v: Lower all users listen volume */ 02851 AST_LIST_TRAVERSE(&cnf->userlist, user, list) 02852 tweak_listen_volume(user, VOL_DOWN); 02853 break; 02854 case 86: /* V: Raise all users listen volume */ 02855 AST_LIST_TRAVERSE(&cnf->userlist, user, list) 02856 tweak_listen_volume(user, VOL_UP); 02857 break; 02858 case 115: /* s: Lower all users speaking volume */ 02859 AST_LIST_TRAVERSE(&cnf->userlist, user, list) 02860 tweak_talk_volume(user, VOL_DOWN); 02861 break; 02862 case 83: /* S: Raise all users speaking volume */ 02863 AST_LIST_TRAVERSE(&cnf->userlist, user, list) 02864 tweak_talk_volume(user, VOL_UP); 02865 break; 02866 case 82: /* R: Reset all volume levels */ 02867 AST_LIST_TRAVERSE(&cnf->userlist, user, list) 02868 reset_volumes(user); 02869 break; 02870 case 114: /* r: Reset user's volume level */ 02871 if (user) 02872 reset_volumes(user); 02873 else 02874 ast_log(LOG_NOTICE, "Specified User not found!\n"); 02875 break; 02876 case 85: /* U: Raise user's listen volume */ 02877 if (user) 02878 tweak_listen_volume(user, VOL_UP); 02879 else 02880 ast_log(LOG_NOTICE, "Specified User not found!\n"); 02881 break; 02882 case 117: /* u: Lower user's listen volume */ 02883 if (user) 02884 tweak_listen_volume(user, VOL_DOWN); 02885 else 02886 ast_log(LOG_NOTICE, "Specified User not found!\n"); 02887 break; 02888 case 84: /* T: Raise user's talk volume */ 02889 if (user) 02890 tweak_talk_volume(user, VOL_UP); 02891 else 02892 ast_log(LOG_NOTICE, "Specified User not found!\n"); 02893 break; 02894 case 116: /* t: Lower user's talk volume */ 02895 if (user) 02896 tweak_talk_volume(user, VOL_DOWN); 02897 else 02898 ast_log(LOG_NOTICE, "Specified User not found!\n"); 02899 break; 02900 } 02901 02902 AST_LIST_UNLOCK(&confs); 02903 02904 dispose_conf(cnf); 02905 02906 ast_module_user_remove(u); 02907 02908 return 0; 02909 }
AST_APP_OPTIONS | ( | meetme_opts | , | |
BEGIN_OPTIONS | AST_APP_OPTION('A', CONFFLAG_MARKEDUSER), | |||
AST_APP_OPTION('a', CONFFLAG_ADMIN) | , | |||
AST_APP_OPTION('b', CONFFLAG_AGI) | , | |||
AST_APP_OPTION('c', CONFFLAG_ANNOUNCEUSERCOUNT) | , | |||
AST_APP_OPTION('D', CONFFLAG_DYNAMICPIN) | , | |||
AST_APP_OPTION('d', CONFFLAG_DYNAMIC) | , | |||
AST_APP_OPTION('E', CONFFLAG_EMPTYNOPIN) | , | |||
AST_APP_OPTION('e', CONFFLAG_EMPTY) | , | |||
AST_APP_OPTION('F', CONFFLAG_PASS_DTMF) | , | |||
AST_APP_OPTION('i', CONFFLAG_INTROUSER) | , | |||
AST_APP_OPTION('I', CONFFLAG_INTROUSERNOREVIEW) | , | |||
AST_APP_OPTION('M', CONFFLAG_MOH) | , | |||
AST_APP_OPTION('m', CONFFLAG_STARTMUTED) | , | |||
AST_APP_OPTION('o', CONFFLAG_OPTIMIZETALKER) | , | |||
AST_APP_OPTION('P', CONFFLAG_ALWAYSPROMPT) | , | |||
AST_APP_OPTION('p', CONFFLAG_POUNDEXIT) | , | |||
AST_APP_OPTION('q', CONFFLAG_QUIET) | , | |||
AST_APP_OPTION('r', CONFFLAG_RECORDCONF) | , | |||
AST_APP_OPTION('s', CONFFLAG_STARMENU) | , | |||
AST_APP_OPTION('T', CONFFLAG_MONITORTALKER) | , | |||
AST_APP_OPTION('l', CONFFLAG_MONITOR) | , | |||
AST_APP_OPTION('t', CONFFLAG_TALKER) | , | |||
AST_APP_OPTION_ARG('w', CONFFLAG_WAITMARKED, OPT_ARG_WAITMARKED) | , | |||
AST_APP_OPTION('X', CONFFLAG_EXIT_CONTEXT) | , | |||
AST_APP_OPTION('x', CONFFLAG_MARKEDEXIT) | , | |||
AST_APP_OPTION('1', CONFFLAG_NOONLYPERSON) | , | |||
END_OPTIONS | ||||
) |
static AST_LIST_HEAD_STATIC | ( | confs | , | |
ast_conference | ||||
) | [static] |
AST_MODULE_INFO | ( | ASTERISK_GPL_KEY | , | |
AST_MODFLAG_DEFAULT | , | |||
"MeetMe conference bridge" | , | |||
. | load = load_module , |
|||
. | unload = unload_module , |
|||
. | reload = reload | |||
) |
static AST_RWLIST_HEAD_STATIC | ( | sla_trunks | , | |
sla_trunk | ||||
) | [static] |
static AST_RWLIST_HEAD_STATIC | ( | sla_stations | , | |
sla_station | ||||
) | [static] |
static struct ast_conference* build_conf | ( | char * | confno, | |
char * | pin, | |||
char * | pinadmin, | |||
int | make, | |||
int | dynamic, | |||
int | refcount | |||
) | [static, read] |
Find or create a conference.
confno | The conference name/number | |
pin | The regular user pin | |
pinadmin | The admin pin | |
make | Make the conf if it doesn't exist | |
dynamic | Mark the newly created conference as dynamic | |
refcount | How many references to mark on the conference |
Definition at line 739 of file app_meetme.c.
References ast_calloc, AST_FORMAT_SLINEAR, ast_hangup(), AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_mutex_init(), ast_request(), ast_set_read_format(), ast_set_write_format(), ast_verbose(), ast_conference::chan, conf_map, ast_conference::confno, ast_conference::fd, ast_channel::fds, free, ast_conference::isdynamic, ast_conference::listenlock, LOG_WARNING, option_verbose, ast_conference::pin, ast_conference::pinadmin, ast_conference::playlock, ast_conference::refcount, ast_conference::start, VERBOSE_PREFIX_3, and ast_conference::zapconf.
Referenced by dial_trunk(), find_conf(), find_conf_realtime(), run_station(), sla_station_exec(), and sla_trunk_exec().
00740 { 00741 struct ast_conference *cnf; 00742 struct zt_confinfo ztc = { 0, }; 00743 int confno_int = 0; 00744 00745 AST_LIST_LOCK(&confs); 00746 00747 AST_LIST_TRAVERSE(&confs, cnf, list) { 00748 if (!strcmp(confno, cnf->confno)) 00749 break; 00750 } 00751 00752 if (cnf || (!make && !dynamic)) 00753 goto cnfout; 00754 00755 /* Make a new one */ 00756 if (!(cnf = ast_calloc(1, sizeof(*cnf)))) 00757 goto cnfout; 00758 00759 ast_mutex_init(&cnf->playlock); 00760 ast_mutex_init(&cnf->listenlock); 00761 ast_copy_string(cnf->confno, confno, sizeof(cnf->confno)); 00762 ast_copy_string(cnf->pin, pin, sizeof(cnf->pin)); 00763 ast_copy_string(cnf->pinadmin, pinadmin, sizeof(cnf->pinadmin)); 00764 00765 /* Setup a new zap conference */ 00766 ztc.confno = -1; 00767 ztc.confmode = ZT_CONF_CONFANN | ZT_CONF_CONFANNMON; 00768 cnf->fd = open("/dev/zap/pseudo", O_RDWR); 00769 if (cnf->fd < 0 || ioctl(cnf->fd, ZT_SETCONF, &ztc)) { 00770 ast_log(LOG_WARNING, "Unable to open pseudo device\n"); 00771 if (cnf->fd >= 0) 00772 close(cnf->fd); 00773 free(cnf); 00774 cnf = NULL; 00775 goto cnfout; 00776 } 00777 00778 cnf->zapconf = ztc.confno; 00779 00780 /* Setup a new channel for playback of audio files */ 00781 cnf->chan = ast_request("zap", AST_FORMAT_SLINEAR, "pseudo", NULL); 00782 if (cnf->chan) { 00783 ast_set_read_format(cnf->chan, AST_FORMAT_SLINEAR); 00784 ast_set_write_format(cnf->chan, AST_FORMAT_SLINEAR); 00785 ztc.chan = 0; 00786 ztc.confno = cnf->zapconf; 00787 ztc.confmode = ZT_CONF_CONFANN | ZT_CONF_CONFANNMON; 00788 if (ioctl(cnf->chan->fds[0], ZT_SETCONF, &ztc)) { 00789 ast_log(LOG_WARNING, "Error setting conference\n"); 00790 if (cnf->chan) 00791 ast_hangup(cnf->chan); 00792 else 00793 close(cnf->fd); 00794 free(cnf); 00795 cnf = NULL; 00796 goto cnfout; 00797 } 00798 } 00799 00800 /* Fill the conference struct */ 00801 cnf->start = time(NULL); 00802 cnf->isdynamic = dynamic ? 1 : 0; 00803 if (option_verbose > 2) 00804 ast_verbose(VERBOSE_PREFIX_3 "Created MeetMe conference %d for conference '%s'\n", cnf->zapconf, cnf->confno); 00805 AST_LIST_INSERT_HEAD(&confs, cnf, list); 00806 00807 /* Reserve conference number in map */ 00808 if ((sscanf(cnf->confno, "%d", &confno_int) == 1) && (confno_int >= 0 && confno_int < 1024)) 00809 conf_map[confno_int] = 1; 00810 00811 cnfout: 00812 if (cnf) 00813 ast_atomic_fetchadd_int(&cnf->refcount, refcount); 00814 00815 AST_LIST_UNLOCK(&confs); 00816 00817 return cnf; 00818 }
static int careful_write | ( | int | fd, | |
unsigned char * | data, | |||
int | len, | |||
int | block | |||
) | [static] |
Definition at line 574 of file app_meetme.c.
References ast_log(), and LOG_WARNING.
Referenced by conf_play(), and conf_run().
00575 { 00576 int res; 00577 int x; 00578 00579 while (len) { 00580 if (block) { 00581 x = ZT_IOMUX_WRITE | ZT_IOMUX_SIGEVENT; 00582 res = ioctl(fd, ZT_IOMUX, &x); 00583 } else 00584 res = 0; 00585 if (res >= 0) 00586 res = write(fd, data, len); 00587 if (res < 1) { 00588 if (errno != EAGAIN) { 00589 ast_log(LOG_WARNING, "Failed to write audio data to conference: %s\n", strerror(errno)); 00590 return -1; 00591 } else 00592 return 0; 00593 } 00594 len -= res; 00595 data += res; 00596 } 00597 00598 return 0; 00599 }
static char* complete_meetmecmd | ( | const char * | line, | |
const char * | word, | |||
int | pos, | |||
int | state | |||
) | [static] |
Definition at line 968 of file app_meetme.c.
References ast_cli_complete(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_strdup, ast_strdupa, ast_conference::confno, len, strdup, strsep(), and ast_conf_user::user_no.
00969 { 00970 static char *cmds[] = {"lock", "unlock", "mute", "unmute", "kick", "list", NULL}; 00971 00972 int len = strlen(word); 00973 int which = 0; 00974 struct ast_conference *cnf = NULL; 00975 struct ast_conf_user *usr = NULL; 00976 char *confno = NULL; 00977 char usrno[50] = ""; 00978 char *myline, *ret = NULL; 00979 00980 if (pos == 1) { /* Command */ 00981 return ast_cli_complete(word, cmds, state); 00982 } else if (pos == 2) { /* Conference Number */ 00983 AST_LIST_LOCK(&confs); 00984 AST_LIST_TRAVERSE(&confs, cnf, list) { 00985 if (!strncasecmp(word, cnf->confno, len) && ++which > state) { 00986 ret = cnf->confno; 00987 break; 00988 } 00989 } 00990 ret = ast_strdup(ret); /* dup before releasing the lock */ 00991 AST_LIST_UNLOCK(&confs); 00992 return ret; 00993 } else if (pos == 3) { 00994 /* User Number || Conf Command option*/ 00995 if (strstr(line, "mute") || strstr(line, "kick")) { 00996 if (state == 0 && (strstr(line, "kick") || strstr(line,"mute")) && !strncasecmp(word, "all", len)) 00997 return strdup("all"); 00998 which++; 00999 AST_LIST_LOCK(&confs); 01000 01001 /* TODO: Find the conf number from the cmdline (ignore spaces) <- test this and make it fail-safe! */ 01002 myline = ast_strdupa(line); 01003 if (strsep(&myline, " ") && strsep(&myline, " ") && !confno) { 01004 while((confno = strsep(&myline, " ")) && (strcmp(confno, " ") == 0)) 01005 ; 01006 } 01007 01008 AST_LIST_TRAVERSE(&confs, cnf, list) { 01009 if (!strcmp(confno, cnf->confno)) 01010 break; 01011 } 01012 01013 if (cnf) { 01014 /* Search for the user */ 01015 AST_LIST_TRAVERSE(&cnf->userlist, usr, list) { 01016 snprintf(usrno, sizeof(usrno), "%d", usr->user_no); 01017 if (!strncasecmp(word, usrno, len) && ++which > state) 01018 break; 01019 } 01020 } 01021 AST_LIST_UNLOCK(&confs); 01022 return usr ? strdup(usrno) : NULL; 01023 } else if ( strstr(line, "list") && ( 0 == state ) ) 01024 return strdup("concise"); 01025 } 01026 01027 return NULL; 01028 }
static int conf_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
The meetme() application.
Definition at line 2495 of file app_meetme.c.
References ast_channel::_state, ast_answer(), AST_APP_ARG, ast_app_getdata(), ast_app_parse_options(), ast_config_destroy(), ast_config_load(), AST_DECLARE_APP_ARGS, AST_DIGIT_ANY, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_module_user_add, ast_module_user_remove, ast_say_digits(), ast_set_flag, AST_STANDARD_APP_ARGS, AST_STATE_UP, ast_stopstream(), ast_strdupa, ast_streamfile(), ast_strlen_zero(), ast_test_flag, ast_variable_browse(), ast_waitstream(), conf_map, conf_run(), CONFFLAG_ADMIN, CONFFLAG_ALWAYSPROMPT, CONFFLAG_DYNAMIC, CONFFLAG_DYNAMICPIN, CONFFLAG_EMPTY, CONFFLAG_EMPTYNOPIN, CONFIG_FILE_NAME, ast_conference::confno, dispose_conf(), find_conf(), find_conf_realtime(), ast_flags::flags, LOG_ERROR, LOG_WARNING, MAX_CONFNUM, MAX_PIN, ast_variable::name, ast_variable::next, OPT_ARG_ARRAY_SIZE, ast_conference::pin, ast_conference::pinadmin, strsep(), ast_variable::value, and var.
Referenced by load_module().
02496 { 02497 int res=-1; 02498 struct ast_module_user *u; 02499 char confno[MAX_CONFNUM] = ""; 02500 int allowretry = 0; 02501 int retrycnt = 0; 02502 struct ast_conference *cnf = NULL; 02503 struct ast_flags confflags = {0}; 02504 int dynamic = 0; 02505 int empty = 0, empty_no_pin = 0; 02506 int always_prompt = 0; 02507 char *notdata, *info, the_pin[MAX_PIN] = ""; 02508 AST_DECLARE_APP_ARGS(args, 02509 AST_APP_ARG(confno); 02510 AST_APP_ARG(options); 02511 AST_APP_ARG(pin); 02512 ); 02513 char *optargs[OPT_ARG_ARRAY_SIZE] = { NULL, }; 02514 02515 u = ast_module_user_add(chan); 02516 02517 if (ast_strlen_zero(data)) { 02518 allowretry = 1; 02519 notdata = ""; 02520 } else { 02521 notdata = data; 02522 } 02523 02524 if (chan->_state != AST_STATE_UP) 02525 ast_answer(chan); 02526 02527 info = ast_strdupa(notdata); 02528 02529 AST_STANDARD_APP_ARGS(args, info); 02530 02531 if (args.confno) { 02532 ast_copy_string(confno, args.confno, sizeof(confno)); 02533 if (ast_strlen_zero(confno)) { 02534 allowretry = 1; 02535 } 02536 } 02537 02538 if (args.pin) 02539 ast_copy_string(the_pin, args.pin, sizeof(the_pin)); 02540 02541 if (args.options) { 02542 ast_app_parse_options(meetme_opts, &confflags, optargs, args.options); 02543 dynamic = ast_test_flag(&confflags, CONFFLAG_DYNAMIC | CONFFLAG_DYNAMICPIN); 02544 if (ast_test_flag(&confflags, CONFFLAG_DYNAMICPIN) && !args.pin) 02545 strcpy(the_pin, "q"); 02546 02547 empty = ast_test_flag(&confflags, CONFFLAG_EMPTY | CONFFLAG_EMPTYNOPIN); 02548 empty_no_pin = ast_test_flag(&confflags, CONFFLAG_EMPTYNOPIN); 02549 always_prompt = ast_test_flag(&confflags, CONFFLAG_ALWAYSPROMPT); 02550 } 02551 02552 do { 02553 if (retrycnt > 3) 02554 allowretry = 0; 02555 if (empty) { 02556 int i; 02557 struct ast_config *cfg; 02558 struct ast_variable *var; 02559 int confno_int; 02560 02561 /* We only need to load the config file for static and empty_no_pin (otherwise we don't care) */ 02562 if ((empty_no_pin) || (!dynamic)) { 02563 cfg = ast_config_load(CONFIG_FILE_NAME); 02564 if (cfg) { 02565 var = ast_variable_browse(cfg, "rooms"); 02566 while (var) { 02567 if (!strcasecmp(var->name, "conf")) { 02568 char *stringp = ast_strdupa(var->value); 02569 if (stringp) { 02570 char *confno_tmp = strsep(&stringp, "|,"); 02571 int found = 0; 02572 if (!dynamic) { 02573 /* For static: run through the list and see if this conference is empty */ 02574 AST_LIST_LOCK(&confs); 02575 AST_LIST_TRAVERSE(&confs, cnf, list) { 02576 if (!strcmp(confno_tmp, cnf->confno)) { 02577 /* The conference exists, therefore it's not empty */ 02578 found = 1; 02579 break; 02580 } 02581 } 02582 AST_LIST_UNLOCK(&confs); 02583 if (!found) { 02584 /* At this point, we have a confno_tmp (static conference) that is empty */ 02585 if ((empty_no_pin && ast_strlen_zero(stringp)) || (!empty_no_pin)) { 02586 /* Case 1: empty_no_pin and pin is nonexistent (NULL) 02587 * Case 2: empty_no_pin and pin is blank (but not NULL) 02588 * Case 3: not empty_no_pin 02589 */ 02590 ast_copy_string(confno, confno_tmp, sizeof(confno)); 02591 break; 02592 /* XXX the map is not complete (but we do have a confno) */ 02593 } 02594 } 02595 } 02596 } 02597 } 02598 var = var->next; 02599 } 02600 ast_config_destroy(cfg); 02601 } 02602 } 02603 02604 /* Select first conference number not in use */ 02605 if (ast_strlen_zero(confno) && dynamic) { 02606 AST_LIST_LOCK(&confs); 02607 for (i = 0; i < sizeof(conf_map) / sizeof(conf_map[0]); i++) { 02608 if (!conf_map[i]) { 02609 snprintf(confno, sizeof(confno), "%d", i); 02610 conf_map[i] = 1; 02611 break; 02612 } 02613 } 02614 AST_LIST_UNLOCK(&confs); 02615 } 02616 02617 /* Not found? */ 02618 if (ast_strlen_zero(confno)) { 02619 res = ast_streamfile(chan, "conf-noempty", chan->language); 02620 if (!res) 02621 ast_waitstream(chan, ""); 02622 } else { 02623 if (sscanf(confno, "%d", &confno_int) == 1) { 02624 res = ast_streamfile(chan, "conf-enteringno", chan->language); 02625 if (!res) { 02626 ast_waitstream(chan, ""); 02627 res = ast_say_digits(chan, confno_int, "", chan->language); 02628 } 02629 } else { 02630 ast_log(LOG_ERROR, "Could not scan confno '%s'\n", confno); 02631 } 02632 } 02633 } 02634 02635 while (allowretry && (ast_strlen_zero(confno)) && (++retrycnt < 4)) { 02636 /* Prompt user for conference number */ 02637 res = ast_app_getdata(chan, "conf-getconfno", confno, sizeof(confno) - 1, 0); 02638 if (res < 0) { 02639 /* Don't try to validate when we catch an error */ 02640 confno[0] = '\0'; 02641 allowretry = 0; 02642 break; 02643 } 02644 } 02645 if (!ast_strlen_zero(confno)) { 02646 /* Check the validity of the conference */ 02647 cnf = find_conf(chan, confno, 1, dynamic, the_pin, 02648 sizeof(the_pin), 1, &confflags); 02649 if (!cnf) { 02650 cnf = find_conf_realtime(chan, confno, 1, dynamic, 02651 the_pin, sizeof(the_pin), 1, &confflags); 02652 } 02653 02654 if (!cnf) { 02655 res = ast_streamfile(chan, "conf-invalid", chan->language); 02656 if (!res) 02657 ast_waitstream(chan, ""); 02658 res = -1; 02659 if (allowretry) 02660 confno[0] = '\0'; 02661 } else { 02662 if ((!ast_strlen_zero(cnf->pin) && 02663 !ast_test_flag(&confflags, CONFFLAG_ADMIN)) || 02664 (!ast_strlen_zero(cnf->pinadmin) && 02665 ast_test_flag(&confflags, CONFFLAG_ADMIN))) { 02666 char pin[MAX_PIN] = ""; 02667 int j; 02668 02669 /* Allow the pin to be retried up to 3 times */ 02670 for (j = 0; j < 3; j++) { 02671 if (*the_pin && (always_prompt == 0)) { 02672 ast_copy_string(pin, the_pin, sizeof(pin)); 02673 res = 0; 02674 } else { 02675 /* Prompt user for pin if pin is required */ 02676 res = ast_app_getdata(chan, "conf-getpin", pin + strlen(pin), sizeof(pin) - 1 - strlen(pin), 0); 02677 } 02678 if (res >= 0) { 02679 if (!strcasecmp(pin, cnf->pin) || 02680 (!ast_strlen_zero(cnf->pinadmin) && 02681 !strcasecmp(pin, cnf->pinadmin))) { 02682 /* Pin correct */ 02683 allowretry = 0; 02684 if (!ast_strlen_zero(cnf->pinadmin) && !strcasecmp(pin, cnf->pinadmin)) 02685 ast_set_flag(&confflags, CONFFLAG_ADMIN); 02686 /* Run the conference */ 02687 res = conf_run(chan, cnf, confflags.flags, optargs); 02688 break; 02689 } else { 02690 /* Pin invalid */ 02691 if (!ast_streamfile(chan, "conf-invalidpin", chan->language)) { 02692 res = ast_waitstream(chan, AST_DIGIT_ANY); 02693 ast_stopstream(chan); 02694 } 02695 else { 02696 ast_log(LOG_WARNING, "Couldn't play invalid pin msg!\n"); 02697 break; 02698 } 02699 if (res < 0) 02700 break; 02701 pin[0] = res; 02702 pin[1] = '\0'; 02703 res = -1; 02704 if (allowretry) 02705 confno[0] = '\0'; 02706 } 02707 } else { 02708 /* failed when getting the pin */ 02709 res = -1; 02710 allowretry = 0; 02711 /* see if we need to get rid of the conference */ 02712 break; 02713 } 02714 02715 /* Don't retry pin with a static pin */ 02716 if (*the_pin && (always_prompt==0)) { 02717 break; 02718 } 02719 } 02720 } else { 02721 /* No pin required */ 02722 allowretry = 0; 02723 02724 /* Run the conference */ 02725 res = conf_run(chan, cnf, confflags.flags, optargs); 02726 } 02727 dispose_conf(cnf); 02728 cnf = NULL; 02729 } 02730 } 02731 } while (allowretry); 02732 02733 if (cnf) 02734 dispose_conf(cnf); 02735 02736 ast_module_user_remove(u); 02737 02738 return res; 02739 }
static void conf_flush | ( | int | fd, | |
struct ast_channel * | chan | |||
) | [static] |
Definition at line 1194 of file app_meetme.c.
References ast_frfree(), ast_log(), ast_read(), ast_waitfor(), f, and LOG_WARNING.
Referenced by conf_run().
01195 { 01196 int x; 01197 01198 /* read any frames that may be waiting on the channel 01199 and throw them away 01200 */ 01201 if (chan) { 01202 struct ast_frame *f; 01203 01204 /* when no frames are available, this will wait 01205 for 1 millisecond maximum 01206 */ 01207 while (ast_waitfor(chan, 1)) { 01208 f = ast_read(chan); 01209 if (f) 01210 ast_frfree(f); 01211 else /* channel was hung up or something else happened */ 01212 break; 01213 } 01214 } 01215 01216 /* flush any data sitting in the pseudo channel */ 01217 x = ZT_FLUSH_ALL; 01218 if (ioctl(fd, ZT_FLUSH, &x)) 01219 ast_log(LOG_WARNING, "Error flushing channel\n"); 01220 01221 }
static int conf_free | ( | struct ast_conference * | conf | ) | [static] |
Definition at line 1225 of file app_meetme.c.
References AST_FRAME_BITS, ast_frfree(), ast_hangup(), AST_LIST_LOCK, AST_LIST_REMOVE, AST_LIST_UNLOCK, ast_translator_free_path(), ast_conference::chan, ast_conference::fd, free, ast_conference::lchan, MEETME_RECORD_ACTIVE, MEETME_RECORD_OFF, MEETME_RECORD_TERMINATE, ast_conference::origframe, ast_conference::transframe, and ast_conference::transpath.
Referenced by dispose_conf().
01226 { 01227 int x; 01228 01229 AST_LIST_REMOVE(&confs, conf, list); 01230 01231 if (conf->recording == MEETME_RECORD_ACTIVE) { 01232 conf->recording = MEETME_RECORD_TERMINATE; 01233 AST_LIST_UNLOCK(&confs); 01234 while (1) { 01235 usleep(1); 01236 AST_LIST_LOCK(&confs); 01237 if (conf->recording == MEETME_RECORD_OFF) 01238 break; 01239 AST_LIST_UNLOCK(&confs); 01240 } 01241 } 01242 01243 for (x=0;x<AST_FRAME_BITS;x++) { 01244 if (conf->transframe[x]) 01245 ast_frfree(conf->transframe[x]); 01246 if (conf->transpath[x]) 01247 ast_translator_free_path(conf->transpath[x]); 01248 } 01249 if (conf->origframe) 01250 ast_frfree(conf->origframe); 01251 if (conf->lchan) 01252 ast_hangup(conf->lchan); 01253 if (conf->chan) 01254 ast_hangup(conf->chan); 01255 else 01256 close(conf->fd); 01257 01258 free(conf); 01259 01260 return 0; 01261 }
static void conf_play | ( | struct ast_channel * | chan, | |
struct ast_conference * | conf, | |||
enum entrance_sound | sound | |||
) | [static] |
Definition at line 692 of file app_meetme.c.
References ast_channel::_softhangup, ast_autoservice_start(), ast_autoservice_stop(), AST_LIST_LOCK, AST_LIST_UNLOCK, careful_write(), enter, ENTER, ast_conference::fd, leave, LEAVE, and len.
Referenced by conf_run().
00693 { 00694 unsigned char *data; 00695 int len; 00696 int res = -1; 00697 00698 if (!chan->_softhangup) 00699 res = ast_autoservice_start(chan); 00700 00701 AST_LIST_LOCK(&confs); 00702 00703 switch(sound) { 00704 case ENTER: 00705 data = enter; 00706 len = sizeof(enter); 00707 break; 00708 case LEAVE: 00709 data = leave; 00710 len = sizeof(leave); 00711 break; 00712 default: 00713 data = NULL; 00714 len = 0; 00715 } 00716 if (data) { 00717 careful_write(conf->fd, data, len, 1); 00718 } 00719 00720 AST_LIST_UNLOCK(&confs); 00721 00722 if (!res) 00723 ast_autoservice_stop(chan); 00724 }
static void conf_queue_dtmf | ( | const struct ast_conference * | conf, | |
const struct ast_conf_user * | sender, | |||
struct ast_frame * | f | |||
) | [static] |
Definition at line 1263 of file app_meetme.c.
References AST_LIST_TRAVERSE, ast_log(), ast_write(), ast_conf_user::chan, and LOG_WARNING.
Referenced by conf_run().
01265 { 01266 struct ast_conf_user *user; 01267 01268 AST_LIST_TRAVERSE(&conf->userlist, user, list) { 01269 if (user == sender) 01270 continue; 01271 if (ast_write(user->chan, f) < 0) 01272 ast_log(LOG_WARNING, "Error writing frame to channel %s\n", user->chan->name); 01273 } 01274 }
static int conf_run | ( | struct ast_channel * | chan, | |
struct ast_conference * | conf, | |||
int | confflags, | |||
char * | optargs[] | |||
) | [static] |
Definition at line 1363 of file app_meetme.c.
References volume::actual, ADMINFLAG_KICKME, ADMINFLAG_MUTED, ADMINFLAG_SELFMUTED, ast_conf_user::adminflags, ast_calloc, ast_channel_setoption(), ast_check_hangup(), ast_config_AST_SPOOL_DIR, AST_CONTROL_HOLD, ast_device_state_changed(), AST_DIGIT_ANY, ast_dsp_free(), ast_dsp_new(), ast_dsp_silence(), ast_filedelete(), ast_fileexists(), AST_FORMAT_SLINEAR, ast_frame_adjust_volume(), AST_FRAME_BITS, AST_FRAME_CONTROL, AST_FRAME_DTMF, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, AST_FRAME_NULL, AST_FRAME_VOICE, ast_frfree(), AST_FRIENDLY_OFFSET, ast_goto_if_exists(), ast_hangup(), ast_indicate(), AST_LIST_EMPTY, AST_LIST_INSERT_TAIL, AST_LIST_LAST, AST_LIST_LOCK, AST_LIST_REMOVE, AST_LIST_UNLOCK, ast_log(), AST_MAX_CONTEXT, AST_MAX_EXTENSION, ast_moh_start(), ast_moh_stop(), ast_mutex_lock(), ast_mutex_unlock(), ast_null_frame, AST_OPTION_TONE_VERIFY, ast_play_and_record(), ast_pthread_create_background, ast_read(), ast_read_noaudio(), ast_record_review(), ast_request(), ast_say_number(), ast_set_read_format(), ast_set_write_format(), ast_stopstream(), ast_strdupa, ast_streamfile(), ast_strlen_zero(), ast_translate(), ast_translator_build_path(), ast_update_realtime(), ast_verbose(), ast_waitfor_nandfds(), ast_waitstream(), ast_write(), ast_conference::attr, careful_write(), ast_conference::chan, ast_conf_user::chan, ast_channel::cid, ast_callerid::cid_name, ast_callerid::cid_num, conf_flush(), conf_play(), conf_queue_dtmf(), CONF_SIZE, CONFFLAG_ADMIN, CONFFLAG_AGI, CONFFLAG_ANNOUNCEUSERCOUNT, CONFFLAG_EXIT_CONTEXT, CONFFLAG_INTROUSER, CONFFLAG_INTROUSERNOREVIEW, CONFFLAG_MARKEDEXIT, CONFFLAG_MARKEDUSER, CONFFLAG_MOH, CONFFLAG_MONITOR, CONFFLAG_MONITORTALKER, CONFFLAG_NOONLYPERSON, CONFFLAG_OPTIMIZETALKER, CONFFLAG_PASS_DTMF, CONFFLAG_POUNDEXIT, CONFFLAG_QUIET, CONFFLAG_RECORDCONF, CONFFLAG_SLA_STATION, CONFFLAG_STARMENU, CONFFLAG_STARTMUTED, CONFFLAG_TALKER, CONFFLAG_WAITMARKED, ast_conference::confno, ast_channel::context, ast_frame::data, ast_frame::datalen, volume::desired, ENTER, EVENT_FLAG_CALL, exitcontext, f, ast_conference::fd, ast_channel::fds, ast_frame::frametype, free, ast_conf_user::jointime, ast_conference::lchan, LEAVE, ast_conf_user::listen, ast_conference::listenlock, ast_conference::locked, LOG_DEBUG, LOG_WARNING, ast_channel::macrocontext, manager_event(), ast_conference::markedusers, MEETME_DELAYDETECTENDTALK, MEETME_DELAYDETECTTALK, MEETME_RECORD_OFF, ast_conf_user::namerecloc, ast_frame::offset, OPT_ARG_WAITMARKED, option_debug, ast_conference::origframe, pbx_builtin_getvar_helper(), pbx_builtin_setvar_helper(), pbx_exec(), pbx_findapp(), ast_conference::playlock, ast_channel::rawwriteformat, ast_conference::recordingfilename, ast_conference::recordingformat, ast_conference::recordthread, reset_volumes(), s, S_OR, ast_frame::samples, set_talk_volume(), SLA_EVENT_HOLD, sla_queue_event_conf(), ast_frame::subclass, ast_conf_user::talk, ast_conf_user::talking, ast_channel::tech, ast_conference::transframe, ast_conference::transpath, tweak_listen_volume(), tweak_talk_volume(), ast_channel_tech::type, ast_conf_user::user_no, ast_conf_user::userflags, ast_conference::users, VERBOSE_PREFIX_4, VOL_DOWN, VOL_UP, ast_conf_user::zapchannel, and ast_conference::zapconf.
Referenced by conf_exec(), dial_trunk(), run_station(), sla_station_exec(), and sla_trunk_exec().
01364 { 01365 struct ast_conf_user *user = NULL; 01366 struct ast_conf_user *usr = NULL; 01367 int fd; 01368 struct zt_confinfo ztc, ztc_empty; 01369 struct ast_frame *f; 01370 struct ast_channel *c; 01371 struct ast_frame fr; 01372 int outfd; 01373 int ms; 01374 int nfds; 01375 int res; 01376 int flags; 01377 int retryzap; 01378 int origfd; 01379 int musiconhold = 0; 01380 int firstpass = 0; 01381 int lastmarked = 0; 01382 int currentmarked = 0; 01383 int ret = -1; 01384 int x; 01385 int menu_active = 0; 01386 int using_pseudo = 0; 01387 int duration=20; 01388 int hr, min, sec; 01389 int sent_event = 0; 01390 time_t now; 01391 struct ast_dsp *dsp=NULL; 01392 struct ast_app *app; 01393 const char *agifile; 01394 const char *agifiledefault = "conf-background.agi"; 01395 char meetmesecs[30] = ""; 01396 char exitcontext[AST_MAX_CONTEXT] = ""; 01397 char recordingtmp[AST_MAX_EXTENSION] = ""; 01398 char members[10] = ""; 01399 int dtmf, opt_waitmarked_timeout = 0; 01400 time_t timeout = 0; 01401 ZT_BUFFERINFO bi; 01402 char __buf[CONF_SIZE + AST_FRIENDLY_OFFSET]; 01403 char *buf = __buf + AST_FRIENDLY_OFFSET; 01404 01405 if (!(user = ast_calloc(1, sizeof(*user)))) 01406 return ret; 01407 01408 /* Possible timeout waiting for marked user */ 01409 if ((confflags & CONFFLAG_WAITMARKED) && 01410 !ast_strlen_zero(optargs[OPT_ARG_WAITMARKED]) && 01411 (sscanf(optargs[OPT_ARG_WAITMARKED], "%d", &opt_waitmarked_timeout) == 1) && 01412 (opt_waitmarked_timeout > 0)) { 01413 timeout = time(NULL) + opt_waitmarked_timeout; 01414 } 01415 01416 if (confflags & CONFFLAG_RECORDCONF) { 01417 if (!conf->recordingfilename) { 01418 conf->recordingfilename = pbx_builtin_getvar_helper(chan, "MEETME_RECORDINGFILE"); 01419 if (!conf->recordingfilename) { 01420 snprintf(recordingtmp, sizeof(recordingtmp), "meetme-conf-rec-%s-%s", conf->confno, chan->uniqueid); 01421 conf->recordingfilename = ast_strdupa(recordingtmp); 01422 } 01423 conf->recordingformat = pbx_builtin_getvar_helper(chan, "MEETME_RECORDINGFORMAT"); 01424 if (!conf->recordingformat) { 01425 snprintf(recordingtmp, sizeof(recordingtmp), "wav"); 01426 conf->recordingformat = ast_strdupa(recordingtmp); 01427 } 01428 ast_verbose(VERBOSE_PREFIX_4 "Starting recording of MeetMe Conference %s into file %s.%s.\n", 01429 conf->confno, conf->recordingfilename, conf->recordingformat); 01430 } 01431 } 01432 01433 if ((conf->recording == MEETME_RECORD_OFF) && (confflags & CONFFLAG_RECORDCONF) && ((conf->lchan = ast_request("zap", AST_FORMAT_SLINEAR, "pseudo", NULL)))) { 01434 ast_set_read_format(conf->lchan, AST_FORMAT_SLINEAR); 01435 ast_set_write_format(conf->lchan, AST_FORMAT_SLINEAR); 01436 ztc.chan = 0; 01437 ztc.confno = conf->zapconf; 01438 ztc.confmode = ZT_CONF_CONFANN | ZT_CONF_CONFANNMON; 01439 if (ioctl(conf->lchan->fds[0], ZT_SETCONF, &ztc)) { 01440 ast_log(LOG_WARNING, "Error starting listen channel\n"); 01441 ast_hangup(conf->lchan); 01442 conf->lchan = NULL; 01443 } else { 01444 pthread_attr_init(&conf->attr); 01445 pthread_attr_setdetachstate(&conf->attr, PTHREAD_CREATE_DETACHED); 01446 ast_pthread_create_background(&conf->recordthread, &conf->attr, recordthread, conf); 01447 pthread_attr_destroy(&conf->attr); 01448 } 01449 } 01450 01451 time(&user->jointime); 01452 01453 if (conf->locked && (!(confflags & CONFFLAG_ADMIN))) { 01454 /* Sorry, but this confernce is locked! */ 01455 if (!ast_streamfile(chan, "conf-locked", chan->language)) 01456 ast_waitstream(chan, ""); 01457 goto outrun; 01458 } 01459 01460 if (confflags & CONFFLAG_MARKEDUSER) 01461 conf->markedusers++; 01462 01463 ast_mutex_lock(&conf->playlock); 01464 01465 if (AST_LIST_EMPTY(&conf->userlist)) 01466 user->user_no = 1; 01467 else 01468 user->user_no = AST_LIST_LAST(&conf->userlist)->user_no + 1; 01469 01470 AST_LIST_INSERT_TAIL(&conf->userlist, user, list); 01471 01472 user->chan = chan; 01473 user->userflags = confflags; 01474 user->adminflags = (confflags & CONFFLAG_STARTMUTED) ? ADMINFLAG_SELFMUTED : 0; 01475 user->talking = -1; 01476 conf->users++; 01477 /* Update table */ 01478 snprintf(members, sizeof(members), "%d", conf->users); 01479 ast_update_realtime("meetme", "confno", conf->confno, "members", members , NULL); 01480 01481 /* This device changed state now - if this is the first user */ 01482 if (conf->users == 1) 01483 ast_device_state_changed("meetme:%s", conf->confno); 01484 01485 ast_mutex_unlock(&conf->playlock); 01486 01487 if (confflags & CONFFLAG_EXIT_CONTEXT) { 01488 if ((agifile = pbx_builtin_getvar_helper(chan, "MEETME_EXIT_CONTEXT"))) 01489 ast_copy_string(exitcontext, agifile, sizeof(exitcontext)); 01490 else if (!ast_strlen_zero(chan->macrocontext)) 01491 ast_copy_string(exitcontext, chan->macrocontext, sizeof(exitcontext)); 01492 else 01493 ast_copy_string(exitcontext, chan->context, sizeof(exitcontext)); 01494 } 01495 01496 if (!(confflags & CONFFLAG_QUIET) && ((confflags & CONFFLAG_INTROUSER) || (confflags & CONFFLAG_INTROUSERNOREVIEW))) { 01497 snprintf(user->namerecloc, sizeof(user->namerecloc), 01498 "%s/meetme/meetme-username-%s-%d", ast_config_AST_SPOOL_DIR, 01499 conf->confno, user->user_no); 01500 if (confflags & CONFFLAG_INTROUSERNOREVIEW) 01501 res = ast_play_and_record(chan, "vm-rec-name", user->namerecloc, 10, "sln", &duration, 128, 0, NULL); 01502 else 01503 res = ast_record_review(chan, "vm-rec-name", user->namerecloc, 10, "sln", &duration, NULL); 01504 if (res == -1) 01505 goto outrun; 01506 } 01507 01508 if ( !(confflags & (CONFFLAG_QUIET | CONFFLAG_NOONLYPERSON)) ) { 01509 if (conf->users == 1 && !(confflags & CONFFLAG_WAITMARKED)) 01510 if (!ast_streamfile(chan, "conf-onlyperson", chan->language)) 01511 ast_waitstream(chan, ""); 01512 if ((confflags & CONFFLAG_WAITMARKED) && conf->markedusers == 0) 01513 if (!ast_streamfile(chan, "conf-waitforleader", chan->language)) 01514 ast_waitstream(chan, ""); 01515 } 01516 01517 if (!(confflags & CONFFLAG_QUIET) && (confflags & CONFFLAG_ANNOUNCEUSERCOUNT) && conf->users > 1) { 01518 int keepplaying = 1; 01519 01520 if (conf->users == 2) { 01521 if (!ast_streamfile(chan,"conf-onlyone",chan->language)) { 01522 res = ast_waitstream(chan, AST_DIGIT_ANY); 01523 ast_stopstream(chan); 01524 if (res > 0) 01525 keepplaying=0; 01526 else if (res == -1) 01527 goto outrun; 01528 } 01529 } else { 01530 if (!ast_streamfile(chan, "conf-thereare", chan->language)) { 01531 res = ast_waitstream(chan, AST_DIGIT_ANY); 01532 ast_stopstream(chan); 01533 if (res > 0) 01534 keepplaying=0; 01535 else if (res == -1) 01536 goto outrun; 01537 } 01538 if (keepplaying) { 01539 res = ast_say_number(chan, conf->users - 1, AST_DIGIT_ANY, chan->language, (char *) NULL); 01540 if (res > 0) 01541 keepplaying=0; 01542 else if (res == -1) 01543 goto outrun; 01544 } 01545 if (keepplaying && !ast_streamfile(chan, "conf-otherinparty", chan->language)) { 01546 res = ast_waitstream(chan, AST_DIGIT_ANY); 01547 ast_stopstream(chan); 01548 if (res > 0) 01549 keepplaying=0; 01550 else if (res == -1) 01551 goto outrun; 01552 } 01553 } 01554 } 01555 01556 ast_indicate(chan, -1); 01557 01558 if (ast_set_write_format(chan, AST_FORMAT_SLINEAR) < 0) { 01559 ast_log(LOG_WARNING, "Unable to set '%s' to write linear mode\n", chan->name); 01560 goto outrun; 01561 } 01562 01563 if (ast_set_read_format(chan, AST_FORMAT_SLINEAR) < 0) { 01564 ast_log(LOG_WARNING, "Unable to set '%s' to read linear mode\n", chan->name); 01565 goto outrun; 01566 } 01567 01568 retryzap = strcasecmp(chan->tech->type, "Zap"); 01569 user->zapchannel = !retryzap; 01570 01571 zapretry: 01572 origfd = chan->fds[0]; 01573 if (retryzap) { 01574 fd = open("/dev/zap/pseudo", O_RDWR); 01575 if (fd < 0) { 01576 ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno)); 01577 goto outrun; 01578 } 01579 using_pseudo = 1; 01580 /* Make non-blocking */ 01581 flags = fcntl(fd, F_GETFL); 01582 if (flags < 0) { 01583 ast_log(LOG_WARNING, "Unable to get flags: %s\n", strerror(errno)); 01584 close(fd); 01585 goto outrun; 01586 } 01587 if (fcntl(fd, F_SETFL, flags | O_NONBLOCK)) { 01588 ast_log(LOG_WARNING, "Unable to set flags: %s\n", strerror(errno)); 01589 close(fd); 01590 goto outrun; 01591 } 01592 /* Setup buffering information */ 01593 memset(&bi, 0, sizeof(bi)); 01594 bi.bufsize = CONF_SIZE/2; 01595 bi.txbufpolicy = ZT_POLICY_IMMEDIATE; 01596 bi.rxbufpolicy = ZT_POLICY_IMMEDIATE; 01597 bi.numbufs = audio_buffers; 01598 if (ioctl(fd, ZT_SET_BUFINFO, &bi)) { 01599 ast_log(LOG_WARNING, "Unable to set buffering information: %s\n", strerror(errno)); 01600 close(fd); 01601 goto outrun; 01602 } 01603 x = 1; 01604 if (ioctl(fd, ZT_SETLINEAR, &x)) { 01605 ast_log(LOG_WARNING, "Unable to set linear mode: %s\n", strerror(errno)); 01606 close(fd); 01607 goto outrun; 01608 } 01609 nfds = 1; 01610 } else { 01611 /* XXX Make sure we're not running on a pseudo channel XXX */ 01612 fd = chan->fds[0]; 01613 nfds = 0; 01614 } 01615 memset(&ztc, 0, sizeof(ztc)); 01616 memset(&ztc_empty, 0, sizeof(ztc_empty)); 01617 /* Check to see if we're in a conference... */ 01618 ztc.chan = 0; 01619 if (ioctl(fd, ZT_GETCONF, &ztc)) { 01620 ast_log(LOG_WARNING, "Error getting conference\n"); 01621 close(fd); 01622 goto outrun; 01623 } 01624 if (ztc.confmode) { 01625 /* Whoa, already in a conference... Retry... */ 01626 if (!retryzap) { 01627 ast_log(LOG_DEBUG, "Zap channel is in a conference already, retrying with pseudo\n"); 01628 retryzap = 1; 01629 goto zapretry; 01630 } 01631 } 01632 memset(&ztc, 0, sizeof(ztc)); 01633 /* Add us to the conference */ 01634 ztc.chan = 0; 01635 ztc.confno = conf->zapconf; 01636 01637 ast_mutex_lock(&conf->playlock); 01638 01639 if (!(confflags & CONFFLAG_QUIET) && ((confflags & CONFFLAG_INTROUSER) || (confflags & CONFFLAG_INTROUSERNOREVIEW)) && conf->users > 1) { 01640 if (conf->chan && ast_fileexists(user->namerecloc, NULL, NULL)) { 01641 if (!ast_streamfile(conf->chan, user->namerecloc, chan->language)) 01642 ast_waitstream(conf->chan, ""); 01643 if (!ast_streamfile(conf->chan, "conf-hasjoin", chan->language)) 01644 ast_waitstream(conf->chan, ""); 01645 } 01646 } 01647 01648 if (confflags & CONFFLAG_MONITOR) 01649 ztc.confmode = ZT_CONF_CONFMON | ZT_CONF_LISTENER; 01650 else if (confflags & CONFFLAG_TALKER) 01651 ztc.confmode = ZT_CONF_CONF | ZT_CONF_TALKER; 01652 else 01653 ztc.confmode = ZT_CONF_CONF | ZT_CONF_TALKER | ZT_CONF_LISTENER; 01654 01655 if (ioctl(fd, ZT_SETCONF, &ztc)) { 01656 ast_log(LOG_WARNING, "Error setting conference\n"); 01657 close(fd); 01658 ast_mutex_unlock(&conf->playlock); 01659 goto outrun; 01660 } 01661 ast_log(LOG_DEBUG, "Placed channel %s in ZAP conf %d\n", chan->name, conf->zapconf); 01662 01663 if (!sent_event) { 01664 manager_event(EVENT_FLAG_CALL, "MeetmeJoin", 01665 "Channel: %s\r\n" 01666 "Uniqueid: %s\r\n" 01667 "Meetme: %s\r\n" 01668 "Usernum: %d\r\n", 01669 chan->name, chan->uniqueid, conf->confno, user->user_no); 01670 sent_event = 1; 01671 } 01672 01673 if (!firstpass && !(confflags & CONFFLAG_MONITOR) && !(confflags & CONFFLAG_ADMIN)) { 01674 firstpass = 1; 01675 if (!(confflags & CONFFLAG_QUIET)) 01676 if (!(confflags & CONFFLAG_WAITMARKED) || ((confflags & CONFFLAG_MARKEDUSER) && (conf->markedusers >= 1))) 01677 conf_play(chan, conf, ENTER); 01678 } 01679 01680 ast_mutex_unlock(&conf->playlock); 01681 01682 conf_flush(fd, chan); 01683 01684 if (confflags & CONFFLAG_AGI) { 01685 /* Get name of AGI file to run from $(MEETME_AGI_BACKGROUND) 01686 or use default filename of conf-background.agi */ 01687 01688 agifile = pbx_builtin_getvar_helper(chan, "MEETME_AGI_BACKGROUND"); 01689 if (!agifile) 01690 agifile = agifiledefault; 01691 01692 if (user->zapchannel) { 01693 /* Set CONFMUTE mode on Zap channel to mute DTMF tones */ 01694 x = 1; 01695 ast_channel_setoption(chan, AST_OPTION_TONE_VERIFY, &x, sizeof(char), 0); 01696 } 01697 /* Find a pointer to the agi app and execute the script */ 01698 app = pbx_findapp("agi"); 01699 if (app) { 01700 char *s = ast_strdupa(agifile); 01701 ret = pbx_exec(chan, app, s); 01702 } else { 01703 ast_log(LOG_WARNING, "Could not find application (agi)\n"); 01704 ret = -2; 01705 } 01706 if (user->zapchannel) { 01707 /* Remove CONFMUTE mode on Zap channel */ 01708 x = 0; 01709 ast_channel_setoption(chan, AST_OPTION_TONE_VERIFY, &x, sizeof(char), 0); 01710 } 01711 } else { 01712 if (user->zapchannel && (confflags & CONFFLAG_STARMENU)) { 01713 /* Set CONFMUTE mode on Zap channel to mute DTMF tones when the menu is enabled */ 01714 x = 1; 01715 ast_channel_setoption(chan, AST_OPTION_TONE_VERIFY, &x, sizeof(char), 0); 01716 } 01717 if (confflags & (CONFFLAG_MONITORTALKER | CONFFLAG_OPTIMIZETALKER) && !(dsp = ast_dsp_new())) { 01718 ast_log(LOG_WARNING, "Unable to allocate DSP!\n"); 01719 res = -1; 01720 } 01721 for(;;) { 01722 int menu_was_active = 0; 01723 01724 outfd = -1; 01725 ms = -1; 01726 01727 if (timeout && time(NULL) >= timeout) 01728 break; 01729 01730 /* if we have just exited from the menu, and the user had a channel-driver 01731 volume adjustment, restore it 01732 */ 01733 if (!menu_active && menu_was_active && user->listen.desired && !user->listen.actual) 01734 set_talk_volume(user, user->listen.desired); 01735 01736 menu_was_active = menu_active; 01737 01738 currentmarked = conf->markedusers; 01739 if (!(confflags & CONFFLAG_QUIET) && 01740 (confflags & CONFFLAG_MARKEDUSER) && 01741 (confflags & CONFFLAG_WAITMARKED) && 01742 lastmarked == 0) { 01743 if (currentmarked == 1 && conf->users > 1) { 01744 ast_say_number(chan, conf->users - 1, AST_DIGIT_ANY, chan->language, (char *) NULL); 01745 if (conf->users - 1 == 1) { 01746 if (!ast_streamfile(chan, "conf-userwilljoin", chan->language)) 01747 ast_waitstream(chan, ""); 01748 } else { 01749 if (!ast_streamfile(chan, "conf-userswilljoin", chan->language)) 01750 ast_waitstream(chan, ""); 01751 } 01752 } 01753 if (conf->users == 1 && ! (confflags & CONFFLAG_MARKEDUSER)) 01754 if (!ast_streamfile(chan, "conf-onlyperson", chan->language)) 01755 ast_waitstream(chan, ""); 01756 } 01757 01758 c = ast_waitfor_nandfds(&chan, 1, &fd, nfds, NULL, &outfd, &ms); 01759 01760 01761 /* Update the struct with the actual confflags */ 01762 user->userflags = confflags; 01763 01764 if (confflags & CONFFLAG_WAITMARKED) { 01765 if(currentmarked == 0) { 01766 if (lastmarked != 0) { 01767 if (!(confflags & CONFFLAG_QUIET)) 01768 if (!ast_streamfile(chan, "conf-leaderhasleft", chan->language)) 01769 ast_waitstream(chan, ""); 01770 if(confflags & CONFFLAG_MARKEDEXIT) 01771 break; 01772 else { 01773 ztc.confmode = ZT_CONF_CONF; 01774 if (ioctl(fd, ZT_SETCONF, &ztc)) { 01775 ast_log(LOG_WARNING, "Error setting conference\n"); 01776 close(fd); 01777 goto outrun; 01778 } 01779 } 01780 } 01781 if (musiconhold == 0 && (confflags & CONFFLAG_MOH)) { 01782 ast_moh_start(chan, NULL, NULL); 01783 musiconhold = 1; 01784 } else { 01785 ztc.confmode = ZT_CONF_CONF; 01786 if (ioctl(fd, ZT_SETCONF, &ztc)) { 01787 ast_log(LOG_WARNING, "Error setting conference\n"); 01788 close(fd); 01789 goto outrun; 01790 } 01791 } 01792 } else if(currentmarked >= 1 && lastmarked == 0) { 01793 /* Marked user entered, so cancel timeout */ 01794 timeout = 0; 01795 if (confflags & CONFFLAG_MONITOR) 01796 ztc.confmode = ZT_CONF_CONFMON | ZT_CONF_LISTENER; 01797 else if (confflags & CONFFLAG_TALKER) 01798 ztc.confmode = ZT_CONF_CONF | ZT_CONF_TALKER; 01799 else 01800 ztc.confmode = ZT_CONF_CONF | ZT_CONF_TALKER | ZT_CONF_LISTENER; 01801 if (ioctl(fd, ZT_SETCONF, &ztc)) { 01802 ast_log(LOG_WARNING, "Error setting conference\n"); 01803 close(fd); 01804 goto outrun; 01805 } 01806 if (musiconhold && (confflags & CONFFLAG_MOH)) { 01807 ast_moh_stop(chan); 01808 musiconhold = 0; 01809 } 01810 if ( !(confflags & CONFFLAG_QUIET) && !(confflags & CONFFLAG_MARKEDUSER)) { 01811 if (!ast_streamfile(chan, "conf-placeintoconf", chan->language)) 01812 ast_waitstream(chan, ""); 01813 conf_play(chan, conf, ENTER); 01814 } 01815 } 01816 } 01817 01818 /* trying to add moh for single person conf */ 01819 if ((confflags & CONFFLAG_MOH) && !(confflags & CONFFLAG_WAITMARKED)) { 01820 if (conf->users == 1) { 01821 if (musiconhold == 0) { 01822 ast_moh_start(chan, NULL, NULL); 01823 musiconhold = 1; 01824 } 01825 } else { 01826 if (musiconhold) { 01827 ast_moh_stop(chan); 01828 musiconhold = 0; 01829 } 01830 } 01831 } 01832 01833 /* Leave if the last marked user left */ 01834 if (currentmarked == 0 && lastmarked != 0 && (confflags & CONFFLAG_MARKEDEXIT)) { 01835 ret = -1; 01836 break; 01837 } 01838 01839 /* Check if my modes have changed */ 01840 01841 /* If I should be muted but am still talker, mute me */ 01842 if ((user->adminflags & (ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED)) && (ztc.confmode & ZT_CONF_TALKER)) { 01843 ztc.confmode ^= ZT_CONF_TALKER; 01844 if (ioctl(fd, ZT_SETCONF, &ztc)) { 01845 ast_log(LOG_WARNING, "Error setting conference - Un/Mute \n"); 01846 ret = -1; 01847 break; 01848 } 01849 01850 manager_event(EVENT_FLAG_CALL, "MeetmeMute", 01851 "Channel: %s\r\n" 01852 "Uniqueid: %s\r\n" 01853 "Meetme: %s\r\n" 01854 "Usernum: %i\r\n" 01855 "Status: on\r\n", 01856 chan->name, chan->uniqueid, conf->confno, user->user_no); 01857 } 01858 01859 /* If I should be un-muted but am not talker, un-mute me */ 01860 if (!(user->adminflags & (ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED)) && !(confflags & CONFFLAG_MONITOR) && !(ztc.confmode & ZT_CONF_TALKER)) { 01861 ztc.confmode |= ZT_CONF_TALKER; 01862 if (ioctl(fd, ZT_SETCONF, &ztc)) { 01863 ast_log(LOG_WARNING, "Error setting conference - Un/Mute \n"); 01864 ret = -1; 01865 break; 01866 } 01867 01868 manager_event(EVENT_FLAG_CALL, "MeetmeMute", 01869 "Channel: %s\r\n" 01870 "Uniqueid: %s\r\n" 01871 "Meetme: %s\r\n" 01872 "Usernum: %i\r\n" 01873 "Status: off\r\n", 01874 chan->name, chan->uniqueid, conf->confno, user->user_no); 01875 } 01876 01877 /* If I have been kicked, exit the conference */ 01878 if (user->adminflags & ADMINFLAG_KICKME) { 01879 //You have been kicked. 01880 if (!(confflags & CONFFLAG_QUIET) && 01881 !ast_streamfile(chan, "conf-kicked", chan->language)) { 01882 ast_waitstream(chan, ""); 01883 } 01884 ret = 0; 01885 break; 01886 } 01887 01888 /* Perform an extra hangup check just in case */ 01889 if (ast_check_hangup(chan)) 01890 break; 01891 01892 if (c) { 01893 if (c->fds[0] != origfd) { 01894 if (using_pseudo) { 01895 /* Kill old pseudo */ 01896 close(fd); 01897 using_pseudo = 0; 01898 } 01899 ast_log(LOG_DEBUG, "Ooh, something swapped out under us, starting over\n"); 01900 retryzap = strcasecmp(c->tech->type, "Zap"); 01901 user->zapchannel = !retryzap; 01902 goto zapretry; 01903 } 01904 if ((confflags & CONFFLAG_MONITOR) || (user->adminflags & (ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED))) 01905 f = ast_read_noaudio(c); 01906 else 01907 f = ast_read(c); 01908 if (!f) 01909 break; 01910 if ((f->frametype == AST_FRAME_VOICE) && (f->subclass == AST_FORMAT_SLINEAR)) { 01911 if (user->talk.actual) 01912 ast_frame_adjust_volume(f, user->talk.actual); 01913 01914 if (confflags & (CONFFLAG_MONITORTALKER | CONFFLAG_OPTIMIZETALKER)) { 01915 int totalsilence; 01916 01917 if (user->talking == -1) 01918 user->talking = 0; 01919 01920 res = ast_dsp_silence(dsp, f, &totalsilence); 01921 if (!user->talking && totalsilence < MEETME_DELAYDETECTTALK) { 01922 user->talking = 1; 01923 if (confflags & CONFFLAG_MONITORTALKER) 01924 manager_event(EVENT_FLAG_CALL, "MeetmeTalking", 01925 "Channel: %s\r\n" 01926 "Uniqueid: %s\r\n" 01927 "Meetme: %s\r\n" 01928 "Usernum: %d\r\n" 01929 "Status: on\r\n", 01930 chan->name, chan->uniqueid, conf->confno, user->user_no); 01931 } 01932 if (user->talking && totalsilence > MEETME_DELAYDETECTENDTALK) { 01933 user->talking = 0; 01934 if (confflags & CONFFLAG_MONITORTALKER) 01935 manager_event(EVENT_FLAG_CALL, "MeetmeTalking", 01936 "Channel: %s\r\n" 01937 "Uniqueid: %s\r\n" 01938 "Meetme: %s\r\n" 01939 "Usernum: %d\r\n" 01940 "Status: off\r\n", 01941 chan->name, chan->uniqueid, conf->confno, user->user_no); 01942 } 01943 } 01944 if (using_pseudo) { 01945 /* Absolutely do _not_ use careful_write here... 01946 it is important that we read data from the channel 01947 as fast as it arrives, and feed it into the conference. 01948 The buffering in the pseudo channel will take care of any 01949 timing differences, unless they are so drastic as to lose 01950 audio frames (in which case carefully writing would only 01951 have delayed the audio even further). 01952 */ 01953 /* As it turns out, we do want to use careful write. We just 01954 don't want to block, but we do want to at least *try* 01955 to write out all the samples. 01956 */ 01957 if (user->talking || !(confflags & CONFFLAG_OPTIMIZETALKER)) 01958 careful_write(fd, f->data, f->datalen, 0); 01959 } 01960 } else if ((f->frametype == AST_FRAME_DTMF) && (confflags & CONFFLAG_EXIT_CONTEXT)) { 01961 char tmp[2]; 01962 01963 tmp[0] = f->subclass; 01964 tmp[1] = '\0'; 01965 if (!ast_goto_if_exists(chan, exitcontext, tmp, 1)) { 01966 ast_log(LOG_DEBUG, "Got DTMF %c, goto context %s\n", tmp[0], exitcontext); 01967 ret = 0; 01968 ast_frfree(f); 01969 break; 01970 } else if (option_debug > 1) 01971 ast_log(LOG_DEBUG, "Exit by single digit did not work in meetme. Extension %s does not exist in context %s\n", tmp, exitcontext); 01972 } else if ((f->frametype == AST_FRAME_DTMF) && (f->subclass == '#') && (confflags & CONFFLAG_POUNDEXIT)) { 01973 ret = 0; 01974 ast_frfree(f); 01975 break; 01976 } else if (((f->frametype == AST_FRAME_DTMF) && (f->subclass == '*') && (confflags & CONFFLAG_STARMENU)) || ((f->frametype == AST_FRAME_DTMF) && menu_active)) { 01977 if (ioctl(fd, ZT_SETCONF, &ztc_empty)) { 01978 ast_log(LOG_WARNING, "Error setting conference\n"); 01979 close(fd); 01980 ast_frfree(f); 01981 goto outrun; 01982 } 01983 01984 /* if we are entering the menu, and the user has a channel-driver 01985 volume adjustment, clear it 01986 */ 01987 if (!menu_active && user->talk.desired && !user->talk.actual) 01988 set_talk_volume(user, 0); 01989 01990 if (musiconhold) { 01991 ast_moh_stop(chan); 01992 } 01993 if ((confflags & CONFFLAG_ADMIN)) { 01994 /* Admin menu */ 01995 if (!menu_active) { 01996 menu_active = 1; 01997 /* Record this sound! */ 01998 if (!ast_streamfile(chan, "conf-adminmenu", chan->language)) { 01999 dtmf = ast_waitstream(chan, AST_DIGIT_ANY); 02000 ast_stopstream(chan); 02001 } else 02002 dtmf = 0; 02003 } else 02004 dtmf = f->subclass; 02005 if (dtmf) { 02006 switch(dtmf) { 02007 case '1': /* Un/Mute */ 02008 menu_active = 0; 02009 02010 /* for admin, change both admin and use flags */ 02011 if (user->adminflags & (ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED)) 02012 user->adminflags &= ~(ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED); 02013 else 02014 user->adminflags |= (ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED); 02015 02016 if ((confflags & CONFFLAG_MONITOR) || (user->adminflags & (ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED))) { 02017 if (!ast_streamfile(chan, "conf-muted", chan->language)) 02018 ast_waitstream(chan, ""); 02019 } else { 02020 if (!ast_streamfile(chan, "conf-unmuted", chan->language)) 02021 ast_waitstream(chan, ""); 02022 } 02023 break; 02024 case '2': /* Un/Lock the Conference */ 02025 menu_active = 0; 02026 if (conf->locked) { 02027 conf->locked = 0; 02028 if (!ast_streamfile(chan, "conf-unlockednow", chan->language)) 02029 ast_waitstream(chan, ""); 02030 } else { 02031 conf->locked = 1; 02032 if (!ast_streamfile(chan, "conf-lockednow", chan->language)) 02033 ast_waitstream(chan, ""); 02034 } 02035 break; 02036 case '3': /* Eject last user */ 02037 menu_active = 0; 02038 usr = AST_LIST_LAST(&conf->userlist); 02039 if ((usr->chan->name == chan->name)||(usr->userflags & CONFFLAG_ADMIN)) { 02040 if(!ast_streamfile(chan, "conf-errormenu", chan->language)) 02041 ast_waitstream(chan, ""); 02042 } else 02043 usr->adminflags |= ADMINFLAG_KICKME; 02044 ast_stopstream(chan); 02045 break; 02046 case '4': 02047 tweak_listen_volume(user, VOL_DOWN); 02048 break; 02049 case '6': 02050 tweak_listen_volume(user, VOL_UP); 02051 break; 02052 case '7': 02053 tweak_talk_volume(user, VOL_DOWN); 02054 break; 02055 case '8': 02056 menu_active = 0; 02057 break; 02058 case '9': 02059 tweak_talk_volume(user, VOL_UP); 02060 break; 02061 default: 02062 menu_active = 0; 02063 /* Play an error message! */ 02064 if (!ast_streamfile(chan, "conf-errormenu", chan->language)) 02065 ast_waitstream(chan, ""); 02066 break; 02067 } 02068 } 02069 } else { 02070 /* User menu */ 02071 if (!menu_active) { 02072 menu_active = 1; 02073 if (!ast_streamfile(chan, "conf-usermenu", chan->language)) { 02074 dtmf = ast_waitstream(chan, AST_DIGIT_ANY); 02075 ast_stopstream(chan); 02076 } else 02077 dtmf = 0; 02078 } else 02079 dtmf = f->subclass; 02080 if (dtmf) { 02081 switch(dtmf) { 02082 case '1': /* Un/Mute */ 02083 menu_active = 0; 02084 02085 /* user can only toggle the self-muted state */ 02086 user->adminflags ^= ADMINFLAG_SELFMUTED; 02087 02088 /* they can't override the admin mute state */ 02089 if ((confflags & CONFFLAG_MONITOR) || (user->adminflags & (ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED))) { 02090 if (!ast_streamfile(chan, "conf-muted", chan->language)) 02091 ast_waitstream(chan, ""); 02092 } else { 02093 if (!ast_streamfile(chan, "conf-unmuted", chan->language)) 02094 ast_waitstream(chan, ""); 02095 } 02096 break; 02097 case '4': 02098 tweak_listen_volume(user, VOL_DOWN); 02099 break; 02100 case '6': 02101 tweak_listen_volume(user, VOL_UP); 02102 break; 02103 case '7': 02104 tweak_talk_volume(user, VOL_DOWN); 02105 break; 02106 case '8': 02107 menu_active = 0; 02108 break; 02109 case '9': 02110 tweak_talk_volume(user, VOL_UP); 02111 break; 02112 default: 02113 menu_active = 0; 02114 if (!ast_streamfile(chan, "conf-errormenu", chan->language)) 02115 ast_waitstream(chan, ""); 02116 break; 02117 } 02118 } 02119 } 02120 if (musiconhold) 02121 ast_moh_start(chan, NULL, NULL); 02122 02123 if (ioctl(fd, ZT_SETCONF, &ztc)) { 02124 ast_log(LOG_WARNING, "Error setting conference\n"); 02125 close(fd); 02126 ast_frfree(f); 02127 goto outrun; 02128 } 02129 02130 conf_flush(fd, chan); 02131 } else if ((f->frametype == AST_FRAME_DTMF_BEGIN || f->frametype == AST_FRAME_DTMF_END) 02132 && confflags & CONFFLAG_PASS_DTMF) { 02133 conf_queue_dtmf(conf, user, f); 02134 } else if ((confflags & CONFFLAG_SLA_STATION) && f->frametype == AST_FRAME_CONTROL) { 02135 switch (f->subclass) { 02136 case AST_CONTROL_HOLD: 02137 sla_queue_event_conf(SLA_EVENT_HOLD, chan, conf); 02138 break; 02139 default: 02140 break; 02141 } 02142 } else if (f->frametype == AST_FRAME_NULL) { 02143 /* Ignore NULL frames. It is perfectly normal to get these if the person is muted. */ 02144 } else if (option_debug) { 02145 ast_log(LOG_DEBUG, 02146 "Got unrecognized frame on channel %s, f->frametype=%d,f->subclass=%d\n", 02147 chan->name, f->frametype, f->subclass); 02148 } 02149 ast_frfree(f); 02150 } else if (outfd > -1) { 02151 res = read(outfd, buf, CONF_SIZE); 02152 if (res > 0) { 02153 memset(&fr, 0, sizeof(fr)); 02154 fr.frametype = AST_FRAME_VOICE; 02155 fr.subclass = AST_FORMAT_SLINEAR; 02156 fr.datalen = res; 02157 fr.samples = res/2; 02158 fr.data = buf; 02159 fr.offset = AST_FRIENDLY_OFFSET; 02160 if (!user->listen.actual && 02161 ((confflags & CONFFLAG_MONITOR) || 02162 (user->adminflags & (ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED)) || 02163 (!user->talking && (confflags & CONFFLAG_OPTIMIZETALKER)) 02164 )) { 02165 int index; 02166 for (index=0;index<AST_FRAME_BITS;index++) 02167 if (chan->rawwriteformat & (1 << index)) 02168 break; 02169 if (index >= AST_FRAME_BITS) 02170 goto bailoutandtrynormal; 02171 ast_mutex_lock(&conf->listenlock); 02172 if (!conf->transframe[index]) { 02173 if (conf->origframe) { 02174 if (!conf->transpath[index]) 02175 conf->transpath[index] = ast_translator_build_path((1 << index), AST_FORMAT_SLINEAR); 02176 if (conf->transpath[index]) { 02177 conf->transframe[index] = ast_translate(conf->transpath[index], conf->origframe, 0); 02178 if (!conf->transframe[index]) 02179 conf->transframe[index] = &ast_null_frame; 02180 } 02181 } 02182 } 02183 if (conf->transframe[index]) { 02184 if (conf->transframe[index]->frametype != AST_FRAME_NULL) { 02185 if (ast_write(chan, conf->transframe[index])) 02186 ast_log(LOG_WARNING, "Unable to write frame to channel %s\n", chan->name); 02187 } 02188 } else { 02189 ast_mutex_unlock(&conf->listenlock); 02190 goto bailoutandtrynormal; 02191 } 02192 ast_mutex_unlock(&conf->listenlock); 02193 } else { 02194 bailoutandtrynormal: 02195 if (user->listen.actual) 02196 ast_frame_adjust_volume(&fr, user->listen.actual); 02197 if (ast_write(chan, &fr) < 0) { 02198 ast_log(LOG_WARNING, "Unable to write frame to channel %s\n", chan->name); 02199 } 02200 } 02201 } else 02202 ast_log(LOG_WARNING, "Failed to read frame: %s\n", strerror(errno)); 02203 } 02204 lastmarked = currentmarked; 02205 } 02206 } 02207 02208 if (musiconhold) 02209 ast_moh_stop(chan); 02210 02211 if (using_pseudo) 02212 close(fd); 02213 else { 02214 /* Take out of conference */ 02215 ztc.chan = 0; 02216 ztc.confno = 0; 02217 ztc.confmode = 0; 02218 if (ioctl(fd, ZT_SETCONF, &ztc)) { 02219 ast_log(LOG_WARNING, "Error setting conference\n"); 02220 } 02221 } 02222 02223 reset_volumes(user); 02224 02225 AST_LIST_LOCK(&confs); 02226 if (!(confflags & CONFFLAG_QUIET) && !(confflags & CONFFLAG_MONITOR) && !(confflags & CONFFLAG_ADMIN)) 02227 conf_play(chan, conf, LEAVE); 02228 02229 if (!(confflags & CONFFLAG_QUIET) && ((confflags & CONFFLAG_INTROUSER) || (confflags & CONFFLAG_INTROUSERNOREVIEW))) { 02230 if (ast_fileexists(user->namerecloc, NULL, NULL)) { 02231 if ((conf->chan) && (conf->users > 1)) { 02232 if (!ast_streamfile(conf->chan, user->namerecloc, chan->language)) 02233 ast_waitstream(conf->chan, ""); 02234 if (!ast_streamfile(conf->chan, "conf-hasleft", chan->language)) 02235 ast_waitstream(conf->chan, ""); 02236 } 02237 ast_filedelete(user->namerecloc, NULL); 02238 } 02239 } 02240 AST_LIST_UNLOCK(&confs); 02241 02242 outrun: 02243 AST_LIST_LOCK(&confs); 02244 02245 if (dsp) 02246 ast_dsp_free(dsp); 02247 02248 if (user->user_no) { /* Only cleanup users who really joined! */ 02249 now = time(NULL); 02250 hr = (now - user->jointime) / 3600; 02251 min = ((now - user->jointime) % 3600) / 60; 02252 sec = (now - user->jointime) % 60; 02253 02254 if (sent_event) { 02255 manager_event(EVENT_FLAG_CALL, "MeetmeLeave", 02256 "Channel: %s\r\n" 02257 "Uniqueid: %s\r\n" 02258 "Meetme: %s\r\n" 02259 "Usernum: %d\r\n" 02260 "CallerIDnum: %s\r\n" 02261 "CallerIDname: %s\r\n" 02262 "Duration: %ld\r\n", 02263 chan->name, chan->uniqueid, conf->confno, 02264 user->user_no, 02265 S_OR(user->chan->cid.cid_num, "<unknown>"), 02266 S_OR(user->chan->cid.cid_name, "<unknown>"), 02267 (long)(now - user->jointime)); 02268 } 02269 02270 conf->users--; 02271 /* Update table */ 02272 snprintf(members, sizeof(members), "%d", conf->users); 02273 ast_update_realtime("meetme", "confno", conf->confno, "members", members, NULL); 02274 if (confflags & CONFFLAG_MARKEDUSER) 02275 conf->markedusers--; 02276 /* Remove ourselves from the list */ 02277 AST_LIST_REMOVE(&conf->userlist, user, list); 02278 02279 /* Change any states */ 02280 if (!conf->users) 02281 ast_device_state_changed("meetme:%s", conf->confno); 02282 02283 /* Return the number of seconds the user was in the conf */ 02284 snprintf(meetmesecs, sizeof(meetmesecs), "%d", (int) (time(NULL) - user->jointime)); 02285 pbx_builtin_setvar_helper(chan, "MEETMESECS", meetmesecs); 02286 } 02287 free(user); 02288 AST_LIST_UNLOCK(&confs); 02289 02290 return ret; 02291 }
static int count_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
The MeetmeCount application.
Definition at line 2444 of file app_meetme.c.
References ast_channel::_state, ast_answer(), AST_APP_ARG, AST_DECLARE_APP_ARGS, ast_log(), ast_module_user_add, ast_module_user_remove, ast_say_number(), AST_STANDARD_APP_ARGS, AST_STATE_UP, ast_strdupa, ast_strlen_zero(), ast_conference::confno, dispose_conf(), find_conf(), LOG_WARNING, pbx_builtin_setvar_helper(), and ast_conference::users.
Referenced by load_module().
02445 { 02446 struct ast_module_user *u; 02447 int res = 0; 02448 struct ast_conference *conf; 02449 int count; 02450 char *localdata; 02451 char val[80] = "0"; 02452 AST_DECLARE_APP_ARGS(args, 02453 AST_APP_ARG(confno); 02454 AST_APP_ARG(varname); 02455 ); 02456 02457 if (ast_strlen_zero(data)) { 02458 ast_log(LOG_WARNING, "MeetMeCount requires an argument (conference number)\n"); 02459 return -1; 02460 } 02461 02462 u = ast_module_user_add(chan); 02463 02464 if (!(localdata = ast_strdupa(data))) { 02465 ast_module_user_remove(u); 02466 return -1; 02467 } 02468 02469 AST_STANDARD_APP_ARGS(args, localdata); 02470 02471 conf = find_conf(chan, args.confno, 0, 0, NULL, 0, 1, NULL); 02472 02473 if (conf) { 02474 count = conf->users; 02475 dispose_conf(conf); 02476 conf = NULL; 02477 } else 02478 count = 0; 02479 02480 if (!ast_strlen_zero(args.varname)){ 02481 /* have var so load it and exit */ 02482 snprintf(val, sizeof(val), "%d",count); 02483 pbx_builtin_setvar_helper(chan, args.varname, val); 02484 } else { 02485 if (chan->_state != AST_STATE_UP) 02486 ast_answer(chan); 02487 res = ast_say_number(chan, count, "", chan->language, (char *) NULL); /* Needs gender */ 02488 } 02489 ast_module_user_remove(u); 02490 02491 return res; 02492 }
static struct sla_trunk_ref* create_trunk_ref | ( | struct sla_trunk * | trunk | ) | [static, read] |
Definition at line 4239 of file app_meetme.c.
References ast_calloc.
Referenced by sla_add_trunk_to_station().
04240 { 04241 struct sla_trunk_ref *trunk_ref; 04242 04243 if (!(trunk_ref = ast_calloc(1, sizeof(*trunk_ref)))) 04244 return NULL; 04245 04246 trunk_ref->trunk = trunk; 04247 04248 return trunk_ref; 04249 }
static void destroy_station | ( | struct sla_station * | station | ) | [static] |
Definition at line 4406 of file app_meetme.c.
References ast_context_remove_extension(), AST_LIST_REMOVE_HEAD, AST_LIST_TRAVERSE, AST_MAX_APP, AST_MAX_EXTENSION, AST_RWLIST_RDLOCK, AST_RWLIST_UNLOCK, ast_string_field_free_all, ast_strlen_zero(), exten, free, PRIORITY_HINT, and sla_registrar.
Referenced by sla_build_station(), and sla_destroy().
04407 { 04408 struct sla_trunk_ref *trunk_ref; 04409 04410 if (!ast_strlen_zero(station->autocontext)) { 04411 AST_RWLIST_RDLOCK(&sla_trunks); 04412 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) { 04413 char exten[AST_MAX_EXTENSION]; 04414 char hint[AST_MAX_APP]; 04415 snprintf(exten, sizeof(exten), "%s_%s", station->name, trunk_ref->trunk->name); 04416 snprintf(hint, sizeof(hint), "SLA:%s", exten); 04417 ast_context_remove_extension(station->autocontext, exten, 04418 1, sla_registrar); 04419 ast_context_remove_extension(station->autocontext, hint, 04420 PRIORITY_HINT, sla_registrar); 04421 } 04422 AST_RWLIST_UNLOCK(&sla_trunks); 04423 } 04424 04425 while ((trunk_ref = AST_LIST_REMOVE_HEAD(&station->trunks, entry))) 04426 free(trunk_ref); 04427 04428 ast_string_field_free_all(station); 04429 free(station); 04430 }
static void destroy_trunk | ( | struct sla_trunk * | trunk | ) | [static] |
Definition at line 4392 of file app_meetme.c.
References ast_context_remove_extension(), AST_LIST_REMOVE_HEAD, ast_string_field_free_all, ast_strlen_zero(), free, and sla_registrar.
Referenced by sla_build_trunk(), and sla_destroy().
04393 { 04394 struct sla_station_ref *station_ref; 04395 04396 if (!ast_strlen_zero(trunk->autocontext)) 04397 ast_context_remove_extension(trunk->autocontext, "s", 1, sla_registrar); 04398 04399 while ((station_ref = AST_LIST_REMOVE_HEAD(&trunk->stations, entry))) 04400 free(station_ref); 04401 04402 ast_string_field_free_all(trunk); 04403 free(trunk); 04404 }
static void* dial_trunk | ( | void * | data | ) | [static] |
Definition at line 3981 of file app_meetme.c.
References ALL_TRUNK_REFS, ast_cond_signal(), 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_mutex_lock(), ast_mutex_unlock(), ast_set_flag, ast_strdup, ast_strdupa, ast_strlen_zero(), build_conf(), cid_name, cid_num, dial_trunk_args::cond, dial_trunk_args::cond_lock, conf_run(), CONFFLAG_MARKEDEXIT, CONFFLAG_MARKEDUSER, CONFFLAG_PASS_DTMF, CONFFLAG_QUIET, CONFFLAG_SLA_TRUNK, dispose_conf(), ast_flags::flags, free, MAX_CONFNUM, sla, sla_change_trunk_state(), SLA_TRUNK_STATE_IDLE, strsep(), and dial_trunk_args::trunk_ref.
Referenced by sla_station_exec().
03982 { 03983 struct dial_trunk_args *args = data; 03984 struct ast_dial *dial; 03985 char *tech, *tech_data; 03986 enum ast_dial_result dial_res; 03987 char conf_name[MAX_CONFNUM]; 03988 struct ast_conference *conf; 03989 struct ast_flags conf_flags = { 0 }; 03990 struct sla_trunk_ref *trunk_ref = args->trunk_ref; 03991 const char *cid_name = NULL, *cid_num = NULL; 03992 03993 if (!(dial = ast_dial_create())) { 03994 ast_mutex_lock(args->cond_lock); 03995 ast_cond_signal(args->cond); 03996 ast_mutex_unlock(args->cond_lock); 03997 return NULL; 03998 } 03999 04000 tech_data = ast_strdupa(trunk_ref->trunk->device); 04001 tech = strsep(&tech_data, "/"); 04002 if (ast_dial_append(dial, tech, tech_data) == -1) { 04003 ast_mutex_lock(args->cond_lock); 04004 ast_cond_signal(args->cond); 04005 ast_mutex_unlock(args->cond_lock); 04006 ast_dial_destroy(dial); 04007 return NULL; 04008 } 04009 04010 if (!sla.attempt_callerid && !ast_strlen_zero(trunk_ref->chan->cid.cid_name)) { 04011 cid_name = ast_strdupa(trunk_ref->chan->cid.cid_name); 04012 free(trunk_ref->chan->cid.cid_name); 04013 trunk_ref->chan->cid.cid_name = NULL; 04014 } 04015 if (!sla.attempt_callerid && !ast_strlen_zero(trunk_ref->chan->cid.cid_num)) { 04016 cid_num = ast_strdupa(trunk_ref->chan->cid.cid_num); 04017 free(trunk_ref->chan->cid.cid_num); 04018 trunk_ref->chan->cid.cid_num = NULL; 04019 } 04020 04021 dial_res = ast_dial_run(dial, trunk_ref->chan, 1); 04022 04023 if (cid_name) 04024 trunk_ref->chan->cid.cid_name = ast_strdup(cid_name); 04025 if (cid_num) 04026 trunk_ref->chan->cid.cid_num = ast_strdup(cid_num); 04027 04028 if (dial_res != AST_DIAL_RESULT_TRYING) { 04029 ast_mutex_lock(args->cond_lock); 04030 ast_cond_signal(args->cond); 04031 ast_mutex_unlock(args->cond_lock); 04032 ast_dial_destroy(dial); 04033 return NULL; 04034 } 04035 04036 for (;;) { 04037 unsigned int done = 0; 04038 switch ((dial_res = ast_dial_state(dial))) { 04039 case AST_DIAL_RESULT_ANSWERED: 04040 trunk_ref->trunk->chan = ast_dial_answered(dial); 04041 case AST_DIAL_RESULT_HANGUP: 04042 case AST_DIAL_RESULT_INVALID: 04043 case AST_DIAL_RESULT_FAILED: 04044 case AST_DIAL_RESULT_TIMEOUT: 04045 case AST_DIAL_RESULT_UNANSWERED: 04046 done = 1; 04047 case AST_DIAL_RESULT_TRYING: 04048 case AST_DIAL_RESULT_RINGING: 04049 case AST_DIAL_RESULT_PROGRESS: 04050 case AST_DIAL_RESULT_PROCEEDING: 04051 break; 04052 } 04053 if (done) 04054 break; 04055 } 04056 04057 if (!trunk_ref->trunk->chan) { 04058 ast_mutex_lock(args->cond_lock); 04059 ast_cond_signal(args->cond); 04060 ast_mutex_unlock(args->cond_lock); 04061 ast_dial_join(dial); 04062 ast_dial_destroy(dial); 04063 return NULL; 04064 } 04065 04066 snprintf(conf_name, sizeof(conf_name), "SLA_%s", trunk_ref->trunk->name); 04067 ast_set_flag(&conf_flags, 04068 CONFFLAG_QUIET | CONFFLAG_MARKEDEXIT | CONFFLAG_MARKEDUSER | 04069 CONFFLAG_PASS_DTMF | CONFFLAG_SLA_TRUNK); 04070 conf = build_conf(conf_name, "", "", 1, 1, 1); 04071 04072 ast_mutex_lock(args->cond_lock); 04073 ast_cond_signal(args->cond); 04074 ast_mutex_unlock(args->cond_lock); 04075 04076 if (conf) { 04077 conf_run(trunk_ref->trunk->chan, conf, conf_flags.flags, NULL); 04078 dispose_conf(conf); 04079 conf = NULL; 04080 } 04081 04082 /* If the trunk is going away, it is definitely now IDLE. */ 04083 sla_change_trunk_state(trunk_ref->trunk, SLA_TRUNK_STATE_IDLE, ALL_TRUNK_REFS, NULL); 04084 04085 trunk_ref->trunk->chan = NULL; 04086 trunk_ref->trunk->on_hold = 0; 04087 04088 ast_dial_join(dial); 04089 ast_dial_destroy(dial); 04090 04091 return NULL; 04092 }
static int dispose_conf | ( | struct ast_conference * | conf | ) | [static] |
Definition at line 1344 of file app_meetme.c.
References AST_LIST_LOCK, AST_LIST_UNLOCK, conf_free(), conf_map, ast_conference::confno, and ast_conference::refcount.
Referenced by admin_exec(), conf_exec(), count_exec(), dial_trunk(), run_station(), sla_station_exec(), and sla_trunk_exec().
01345 { 01346 int res = 0; 01347 int confno_int = 0; 01348 01349 AST_LIST_LOCK(&confs); 01350 if (ast_atomic_dec_and_test(&conf->refcount)) { 01351 /* Take the conference room number out of an inuse state */ 01352 if ((sscanf(conf->confno, "%d", &confno_int) == 1) && (confno_int >= 0 && confno_int < 1024)) 01353 conf_map[confno_int] = 0; 01354 conf_free(conf); 01355 res = 1; 01356 } 01357 AST_LIST_UNLOCK(&confs); 01358 01359 return res; 01360 }
static struct ast_conference* find_conf | ( | struct ast_channel * | chan, | |
char * | confno, | |||
int | make, | |||
int | dynamic, | |||
char * | dynamic_pin, | |||
size_t | pin_buf_len, | |||
int | refcount, | |||
struct ast_flags * | confflags | |||
) | [static, read] |
Definition at line 2350 of file app_meetme.c.
References AST_APP_ARG, ast_app_getdata(), ast_clear_flag, ast_config_destroy(), ast_config_load(), AST_DECLARE_APP_ARGS, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), AST_NONSTANDARD_APP_ARGS, ast_strdupa, ast_test_flag, ast_variable_browse(), build_conf(), ast_conference::chan, CONFFLAG_INTROUSER, CONFFLAG_QUIET, CONFFLAG_RECORDCONF, CONFIG_FILE_NAME, ast_conference::confno, LOG_DEBUG, LOG_WARNING, ast_variable::name, ast_variable::next, parse(), ast_conference::pin, ast_conference::pinadmin, ast_conference::refcount, S_OR, ast_variable::value, and var.
Referenced by conf_exec(), and count_exec().
02352 { 02353 struct ast_config *cfg; 02354 struct ast_variable *var; 02355 struct ast_conference *cnf; 02356 char *parse; 02357 AST_DECLARE_APP_ARGS(args, 02358 AST_APP_ARG(confno); 02359 AST_APP_ARG(pin); 02360 AST_APP_ARG(pinadmin); 02361 ); 02362 02363 /* Check first in the conference list */ 02364 AST_LIST_LOCK(&confs); 02365 AST_LIST_TRAVERSE(&confs, cnf, list) { 02366 if (!strcmp(confno, cnf->confno)) 02367 break; 02368 } 02369 if (cnf){ 02370 cnf->refcount += refcount; 02371 } 02372 AST_LIST_UNLOCK(&confs); 02373 02374 if (!cnf) { 02375 if (dynamic) { 02376 /* No need to parse meetme.conf */ 02377 ast_log(LOG_DEBUG, "Building dynamic conference '%s'\n", confno); 02378 if (dynamic_pin) { 02379 if (dynamic_pin[0] == 'q') { 02380 /* Query the user to enter a PIN */ 02381 if (ast_app_getdata(chan, "conf-getpin", dynamic_pin, pin_buf_len - 1, 0) < 0) 02382 return NULL; 02383 } 02384 cnf = build_conf(confno, dynamic_pin, "", make, dynamic, refcount); 02385 } else { 02386 cnf = build_conf(confno, "", "", make, dynamic, refcount); 02387 } 02388 } else { 02389 /* Check the config */ 02390 cfg = ast_config_load(CONFIG_FILE_NAME); 02391 if (!cfg) { 02392 ast_log(LOG_WARNING, "No %s file :(\n", CONFIG_FILE_NAME); 02393 return NULL; 02394 } 02395 for (var = ast_variable_browse(cfg, "rooms"); var; var = var->next) { 02396 if (strcasecmp(var->name, "conf")) 02397 continue; 02398 02399 if (!(parse = ast_strdupa(var->value))) 02400 return NULL; 02401 02402 AST_NONSTANDARD_APP_ARGS(args, parse, ','); 02403 if (!strcasecmp(args.confno, confno)) { 02404 /* Bingo it's a valid conference */ 02405 cnf = build_conf(args.confno, 02406 S_OR(args.pin, ""), 02407 S_OR(args.pinadmin, ""), 02408 make, dynamic, refcount); 02409 break; 02410 } 02411 } 02412 if (!var) { 02413 ast_log(LOG_DEBUG, "%s isn't a valid conference\n", confno); 02414 } 02415 ast_config_destroy(cfg); 02416 } 02417 } else if (dynamic_pin) { 02418 /* Correct for the user selecting 'D' instead of 'd' to have 02419 someone join into a conference that has already been created 02420 with a pin. */ 02421 if (dynamic_pin[0] == 'q') 02422 dynamic_pin[0] = '\0'; 02423 } 02424 02425 if (cnf) { 02426 if (confflags && !cnf->chan && 02427 !ast_test_flag(confflags, CONFFLAG_QUIET) && 02428 ast_test_flag(confflags, CONFFLAG_INTROUSER)) { 02429 ast_log(LOG_WARNING, "No Zap channel available for conference, user introduction disabled (is chan_zap loaded?)\n"); 02430 ast_clear_flag(confflags, CONFFLAG_INTROUSER); 02431 } 02432 02433 if (confflags && !cnf->chan && 02434 ast_test_flag(confflags, CONFFLAG_RECORDCONF)) { 02435 ast_log(LOG_WARNING, "No Zap channel available for conference, conference recording disabled (is chan_zap loaded?)\n"); 02436 ast_clear_flag(confflags, CONFFLAG_RECORDCONF); 02437 } 02438 } 02439 02440 return cnf; 02441 }
static struct ast_conference* find_conf_realtime | ( | struct ast_channel * | chan, | |
char * | confno, | |||
int | make, | |||
int | dynamic, | |||
char * | dynamic_pin, | |||
size_t | pin_buf_len, | |||
int | refcount, | |||
struct ast_flags * | confflags | |||
) | [static, read] |
Definition at line 2293 of file app_meetme.c.
References ast_clear_flag, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_load_realtime(), ast_log(), ast_strdupa, ast_test_flag, ast_variables_destroy(), build_conf(), ast_conference::chan, CONFFLAG_INTROUSER, CONFFLAG_QUIET, CONFFLAG_RECORDCONF, ast_conference::confno, LOG_WARNING, ast_variable::name, ast_variable::next, ast_conference::pin, ast_conference::pinadmin, ast_conference::refcount, ast_variable::value, and var.
Referenced by conf_exec().
02295 { 02296 struct ast_variable *var; 02297 struct ast_conference *cnf; 02298 02299 /* Check first in the conference list */ 02300 AST_LIST_LOCK(&confs); 02301 AST_LIST_TRAVERSE(&confs, cnf, list) { 02302 if (!strcmp(confno, cnf->confno)) 02303 break; 02304 } 02305 if (cnf) { 02306 cnf->refcount += refcount; 02307 } 02308 AST_LIST_UNLOCK(&confs); 02309 02310 if (!cnf) { 02311 char *pin = NULL, *pinadmin = NULL; /* For temp use */ 02312 02313 var = ast_load_realtime("meetme", "confno", confno, NULL); 02314 02315 if (!var) 02316 return NULL; 02317 02318 while (var) { 02319 if (!strcasecmp(var->name, "pin")) { 02320 pin = ast_strdupa(var->value); 02321 } else if (!strcasecmp(var->name, "adminpin")) { 02322 pinadmin = ast_strdupa(var->value); 02323 } 02324 var = var->next; 02325 } 02326 ast_variables_destroy(var); 02327 02328 cnf = build_conf(confno, pin ? pin : "", pinadmin ? pinadmin : "", make, dynamic, refcount); 02329 } 02330 02331 if (cnf) { 02332 if (confflags && !cnf->chan && 02333 !ast_test_flag(confflags, CONFFLAG_QUIET) && 02334 ast_test_flag(confflags, CONFFLAG_INTROUSER)) { 02335 ast_log(LOG_WARNING, "No Zap channel available for conference, user introduction disabled (is chan_zap loaded?)\n"); 02336 ast_clear_flag(confflags, CONFFLAG_INTROUSER); 02337 } 02338 02339 if (confflags && !cnf->chan && 02340 ast_test_flag(confflags, CONFFLAG_RECORDCONF)) { 02341 ast_log(LOG_WARNING, "No Zap channel available for conference, conference recording disabled (is chan_zap loaded?)\n"); 02342 ast_clear_flag(confflags, CONFFLAG_RECORDCONF); 02343 } 02344 } 02345 02346 return cnf; 02347 }
static struct ast_conf_user* find_user | ( | struct ast_conference * | conf, | |
char * | callerident | |||
) | [static, read] |
Definition at line 2741 of file app_meetme.c.
References AST_LIST_TRAVERSE, and ast_conf_user::user_no.
02742 { 02743 struct ast_conf_user *user = NULL; 02744 int cid; 02745 02746 sscanf(callerident, "%i", &cid); 02747 if (conf && callerident) { 02748 AST_LIST_TRAVERSE(&conf->userlist, user, list) { 02749 if (cid == user->user_no) 02750 return user; 02751 } 02752 } 02753 return NULL; 02754 }
static char* istalking | ( | int | x | ) | [static] |
Definition at line 564 of file app_meetme.c.
Referenced by meetme_cmd().
00565 { 00566 if (x > 0) 00567 return "(talking)"; 00568 else if (x < 0) 00569 return "(unmonitored)"; 00570 else 00571 return "(not talking)"; 00572 }
static int load_config | ( | int | reload | ) | [static] |
Definition at line 4757 of file app_meetme.c.
References load_config_meetme(), and sla_load_config().
04758 { 04759 int res = 0; 04760 04761 load_config_meetme(); 04762 if (!reload) 04763 res = sla_load_config(); 04764 04765 return res; 04766 }
static void load_config_meetme | ( | void | ) | [static] |
Definition at line 3069 of file app_meetme.c.
References ast_config_destroy(), ast_config_load(), ast_log(), ast_variable_retrieve(), CONFIG_FILE_NAME, DEFAULT_AUDIO_BUFFERS, LOG_NOTICE, and LOG_WARNING.
Referenced by load_config().
03070 { 03071 struct ast_config *cfg; 03072 const char *val; 03073 03074 audio_buffers = DEFAULT_AUDIO_BUFFERS; 03075 03076 if (!(cfg = ast_config_load(CONFIG_FILE_NAME))) 03077 return; 03078 03079 if ((val = ast_variable_retrieve(cfg, "general", "audiobuffers"))) { 03080 if ((sscanf(val, "%d", &audio_buffers) != 1)) { 03081 ast_log(LOG_WARNING, "audiobuffers setting must be a number, not '%s'\n", val); 03082 audio_buffers = DEFAULT_AUDIO_BUFFERS; 03083 } else if ((audio_buffers < ZT_DEFAULT_NUM_BUFS) || (audio_buffers > ZT_MAX_NUM_BUFS)) { 03084 ast_log(LOG_WARNING, "audiobuffers setting must be between %d and %d\n", 03085 ZT_DEFAULT_NUM_BUFS, ZT_MAX_NUM_BUFS); 03086 audio_buffers = DEFAULT_AUDIO_BUFFERS; 03087 } 03088 if (audio_buffers != DEFAULT_AUDIO_BUFFERS) 03089 ast_log(LOG_NOTICE, "Audio buffers per channel set to %d\n", audio_buffers); 03090 } 03091 03092 ast_config_destroy(cfg); 03093 }
static int load_module | ( | void | ) | [static] |
Definition at line 4791 of file app_meetme.c.
References action_meetmemute(), action_meetmeunmute(), admin_exec(), ARRAY_LEN, ast_cli_register_multiple(), ast_devstate_prov_add(), ast_manager_register, ast_register_application(), conf_exec(), count_exec(), EVENT_FLAG_CALL, load_config(), meetmestate(), sla_state(), sla_station_exec(), and sla_trunk_exec().
04792 { 04793 int res = 0; 04794 04795 res |= load_config(0); 04796 04797 ast_cli_register_multiple(cli_meetme, ARRAY_LEN(cli_meetme)); 04798 res |= ast_manager_register("MeetmeMute", EVENT_FLAG_CALL, 04799 action_meetmemute, "Mute a Meetme user"); 04800 res |= ast_manager_register("MeetmeUnmute", EVENT_FLAG_CALL, 04801 action_meetmeunmute, "Unmute a Meetme user"); 04802 res |= ast_register_application(app3, admin_exec, synopsis3, descrip3); 04803 res |= ast_register_application(app2, count_exec, synopsis2, descrip2); 04804 res |= ast_register_application(app, conf_exec, synopsis, descrip); 04805 res |= ast_register_application(slastation_app, sla_station_exec, 04806 slastation_synopsis, slastation_desc); 04807 res |= ast_register_application(slatrunk_app, sla_trunk_exec, 04808 slatrunk_synopsis, slatrunk_desc); 04809 04810 res |= ast_devstate_prov_add("Meetme", meetmestate); 04811 res |= ast_devstate_prov_add("SLA", sla_state); 04812 04813 return res; 04814 }
static int meetme_cmd | ( | int | fd, | |
int | argc, | |||
char ** | argv | |||
) | [static] |
Definition at line 820 of file app_meetme.c.
References admin_exec(), ADMINFLAG_MUTED, ADMINFLAG_SELFMUTED, ast_conf_user::adminflags, ast_cli(), AST_LIST_EMPTY, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_conf_user::chan, ast_channel::cid, ast_callerid::cid_name, ast_callerid::cid_num, CONFFLAG_ADMIN, CONFFLAG_MONITOR, ast_conference::confno, ast_conference::isdynamic, istalking(), ast_conf_user::jointime, LOG_DEBUG, ast_conference::markedusers, RESULT_SHOWUSAGE, RESULT_SUCCESS, S_OR, ast_conference::start, ast_conf_user::talking, total, ast_conf_user::user_no, ast_conf_user::userflags, and ast_conference::users.
00821 { 00822 /* Process the command */ 00823 struct ast_conference *cnf; 00824 struct ast_conf_user *user; 00825 int hr, min, sec; 00826 int i = 0, total = 0; 00827 time_t now; 00828 char *header_format = "%-14s %-14s %-10s %-8s %-8s\n"; 00829 char *data_format = "%-12.12s %4.4d %4.4s %02d:%02d:%02d %-8s\n"; 00830 char cmdline[1024] = ""; 00831 00832 if (argc > 8) 00833 ast_cli(fd, "Invalid Arguments.\n"); 00834 /* Check for length so no buffer will overflow... */ 00835 for (i = 0; i < argc; i++) { 00836 if (strlen(argv[i]) > 100) 00837 ast_cli(fd, "Invalid Arguments.\n"); 00838 } 00839 if (argc == 1) { 00840 /* 'MeetMe': List all the conferences */ 00841 now = time(NULL); 00842 AST_LIST_LOCK(&confs); 00843 if (AST_LIST_EMPTY(&confs)) { 00844 ast_cli(fd, "No active MeetMe conferences.\n"); 00845 AST_LIST_UNLOCK(&confs); 00846 return RESULT_SUCCESS; 00847 } 00848 ast_cli(fd, header_format, "Conf Num", "Parties", "Marked", "Activity", "Creation"); 00849 AST_LIST_TRAVERSE(&confs, cnf, list) { 00850 if (cnf->markedusers == 0) 00851 strcpy(cmdline, "N/A "); 00852 else 00853 snprintf(cmdline, sizeof(cmdline), "%4.4d", cnf->markedusers); 00854 hr = (now - cnf->start) / 3600; 00855 min = ((now - cnf->start) % 3600) / 60; 00856 sec = (now - cnf->start) % 60; 00857 00858 ast_cli(fd, data_format, cnf->confno, cnf->users, cmdline, hr, min, sec, cnf->isdynamic ? "Dynamic" : "Static"); 00859 00860 total += cnf->users; 00861 } 00862 AST_LIST_UNLOCK(&confs); 00863 ast_cli(fd, "* Total number of MeetMe users: %d\n", total); 00864 return RESULT_SUCCESS; 00865 } 00866 if (argc < 3) 00867 return RESULT_SHOWUSAGE; 00868 ast_copy_string(cmdline, argv[2], sizeof(cmdline)); /* Argv 2: conference number */ 00869 if (strstr(argv[1], "lock")) { 00870 if (strcmp(argv[1], "lock") == 0) { 00871 /* Lock */ 00872 strncat(cmdline, "|L", sizeof(cmdline) - strlen(cmdline) - 1); 00873 } else { 00874 /* Unlock */ 00875 strncat(cmdline, "|l", sizeof(cmdline) - strlen(cmdline) - 1); 00876 } 00877 } else if (strstr(argv[1], "mute")) { 00878 if (argc < 4) 00879 return RESULT_SHOWUSAGE; 00880 if (strcmp(argv[1], "mute") == 0) { 00881 /* Mute */ 00882 if (strcmp(argv[3], "all") == 0) { 00883 strncat(cmdline, "|N", sizeof(cmdline) - strlen(cmdline) - 1); 00884 } else { 00885 strncat(cmdline, "|M|", sizeof(cmdline) - strlen(cmdline) - 1); 00886 strncat(cmdline, argv[3], sizeof(cmdline) - strlen(cmdline) - 1); 00887 } 00888 } else { 00889 /* Unmute */ 00890 if (strcmp(argv[3], "all") == 0) { 00891 strncat(cmdline, "|n", sizeof(cmdline) - strlen(cmdline) - 1); 00892 } else { 00893 strncat(cmdline, "|m|", sizeof(cmdline) - strlen(cmdline) - 1); 00894 strncat(cmdline, argv[3], sizeof(cmdline) - strlen(cmdline) - 1); 00895 } 00896 } 00897 } else if (strcmp(argv[1], "kick") == 0) { 00898 if (argc < 4) 00899 return RESULT_SHOWUSAGE; 00900 if (strcmp(argv[3], "all") == 0) { 00901 /* Kick all */ 00902 strncat(cmdline, "|K", sizeof(cmdline) - strlen(cmdline) - 1); 00903 } else { 00904 /* Kick a single user */ 00905 strncat(cmdline, "|k|", sizeof(cmdline) - strlen(cmdline) - 1); 00906 strncat(cmdline, argv[3], sizeof(cmdline) - strlen(cmdline) - 1); 00907 } 00908 } else if(strcmp(argv[1], "list") == 0) { 00909 int concise = ( 4 == argc && ( !strcasecmp(argv[3], "concise") ) ); 00910 /* List all the users in a conference */ 00911 if (AST_LIST_EMPTY(&confs)) { 00912 if ( !concise ) 00913 ast_cli(fd, "No active conferences.\n"); 00914 return RESULT_SUCCESS; 00915 } 00916 /* Find the right conference */ 00917 AST_LIST_LOCK(&confs); 00918 AST_LIST_TRAVERSE(&confs, cnf, list) { 00919 if (strcmp(cnf->confno, argv[2]) == 0) 00920 break; 00921 } 00922 if (!cnf) { 00923 if ( !concise ) 00924 ast_cli(fd, "No such conference: %s.\n",argv[2]); 00925 AST_LIST_UNLOCK(&confs); 00926 return RESULT_SUCCESS; 00927 } 00928 /* Show all the users */ 00929 time(&now); 00930 AST_LIST_TRAVERSE(&cnf->userlist, user, list) { 00931 hr = (now - user->jointime) / 3600; 00932 min = ((now - user->jointime) % 3600) / 60; 00933 sec = (now - user->jointime) % 60; 00934 if ( !concise ) 00935 ast_cli(fd, "User #: %-2.2d %12.12s %-20.20s Channel: %s %s %s %s %s %02d:%02d:%02d\n", 00936 user->user_no, 00937 S_OR(user->chan->cid.cid_num, "<unknown>"), 00938 S_OR(user->chan->cid.cid_name, "<no name>"), 00939 user->chan->name, 00940 user->userflags & CONFFLAG_ADMIN ? "(Admin)" : "", 00941 user->userflags & CONFFLAG_MONITOR ? "(Listen only)" : "", 00942 user->adminflags & ADMINFLAG_MUTED ? "(Admin Muted)" : user->adminflags & ADMINFLAG_SELFMUTED ? "(Muted)" : "", 00943 istalking(user->talking), hr, min, sec); 00944 else 00945 ast_cli(fd, "%d!%s!%s!%s!%s!%s!%s!%d!%02d:%02d:%02d\n", 00946 user->user_no, 00947 S_OR(user->chan->cid.cid_num, ""), 00948 S_OR(user->chan->cid.cid_name, ""), 00949 user->chan->name, 00950 user->userflags & CONFFLAG_ADMIN ? "1" : "", 00951 user->userflags & CONFFLAG_MONITOR ? "1" : "", 00952 user->adminflags & (ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED) ? "1" : "", 00953 user->talking, hr, min, sec); 00954 00955 } 00956 if ( !concise ) 00957 ast_cli(fd,"%d users in that conference.\n",cnf->users); 00958 AST_LIST_UNLOCK(&confs); 00959 return RESULT_SUCCESS; 00960 } else 00961 return RESULT_SHOWUSAGE; 00962 ast_log(LOG_DEBUG, "Cmdline: %s\n", cmdline); 00963 admin_exec(NULL, cmdline); 00964 00965 return 0; 00966 }
static int meetmemute | ( | struct mansession * | s, | |
const struct message * | m, | |||
int | mute | |||
) | [static] |
Definition at line 2911 of file app_meetme.c.
References ADMINFLAG_MUTED, ADMINFLAG_SELFMUTED, ast_conf_user::adminflags, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_strdupa, ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), ast_conf_user::chan, ast_conference::confno, LOG_NOTICE, and ast_conf_user::user_no.
Referenced by action_meetmemute(), and action_meetmeunmute().
02912 { 02913 struct ast_conference *conf; 02914 struct ast_conf_user *user; 02915 const char *confid = astman_get_header(m, "Meetme"); 02916 char *userid = ast_strdupa(astman_get_header(m, "Usernum")); 02917 int userno; 02918 02919 if (ast_strlen_zero(confid)) { 02920 astman_send_error(s, m, "Meetme conference not specified"); 02921 return 0; 02922 } 02923 02924 if (ast_strlen_zero(userid)) { 02925 astman_send_error(s, m, "Meetme user number not specified"); 02926 return 0; 02927 } 02928 02929 userno = strtoul(userid, &userid, 10); 02930 02931 if (*userid) { 02932 astman_send_error(s, m, "Invalid user number"); 02933 return 0; 02934 } 02935 02936 /* Look in the conference list */ 02937 AST_LIST_LOCK(&confs); 02938 AST_LIST_TRAVERSE(&confs, conf, list) { 02939 if (!strcmp(confid, conf->confno)) 02940 break; 02941 } 02942 02943 if (!conf) { 02944 AST_LIST_UNLOCK(&confs); 02945 astman_send_error(s, m, "Meetme conference does not exist"); 02946 return 0; 02947 } 02948 02949 AST_LIST_TRAVERSE(&conf->userlist, user, list) 02950 if (user->user_no == userno) 02951 break; 02952 02953 if (!user) { 02954 AST_LIST_UNLOCK(&confs); 02955 astman_send_error(s, m, "User number not found"); 02956 return 0; 02957 } 02958 02959 if (mute) 02960 user->adminflags |= ADMINFLAG_MUTED; /* request user muting */ 02961 else 02962 user->adminflags &= ~(ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED); /* request user unmuting */ 02963 02964 AST_LIST_UNLOCK(&confs); 02965 02966 ast_log(LOG_NOTICE, "Requested to %smute conf %s user %d userchan %s uniqueid %s\n", mute ? "" : "un", conf->confno, user->user_no, user->chan->name, user->chan->uniqueid); 02967 02968 astman_send_ack(s, m, mute ? "User muted" : "User unmuted"); 02969 return 0; 02970 }
static int meetmestate | ( | const char * | data | ) | [static] |
Callback for devicestate providers.
Definition at line 3047 of file app_meetme.c.
References AST_DEVICE_INUSE, AST_DEVICE_INVALID, AST_DEVICE_NOT_INUSE, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_conference::confno, and ast_conference::users.
Referenced by load_module().
03048 { 03049 struct ast_conference *conf; 03050 03051 /* Find conference */ 03052 AST_LIST_LOCK(&confs); 03053 AST_LIST_TRAVERSE(&confs, conf, list) { 03054 if (!strcmp(data, conf->confno)) 03055 break; 03056 } 03057 AST_LIST_UNLOCK(&confs); 03058 if (!conf) 03059 return AST_DEVICE_INVALID; 03060 03061 03062 /* SKREP to fill */ 03063 if (!conf->users) 03064 return AST_DEVICE_NOT_INUSE; 03065 03066 return AST_DEVICE_INUSE; 03067 }
static struct sla_ringing_trunk* queue_ringing_trunk | ( | struct sla_trunk * | trunk | ) | [static, read] |
Definition at line 4251 of file app_meetme.c.
References ALL_TRUNK_REFS, ast_calloc, AST_LIST_INSERT_HEAD, ast_mutex_lock(), ast_mutex_unlock(), 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().
04252 { 04253 struct sla_ringing_trunk *ringing_trunk; 04254 04255 if (!(ringing_trunk = ast_calloc(1, sizeof(*ringing_trunk)))) 04256 return NULL; 04257 04258 ringing_trunk->trunk = trunk; 04259 ringing_trunk->ring_begin = ast_tvnow(); 04260 04261 sla_change_trunk_state(trunk, SLA_TRUNK_STATE_RINGING, ALL_TRUNK_REFS, NULL); 04262 04263 ast_mutex_lock(&sla.lock); 04264 AST_LIST_INSERT_HEAD(&sla.ringing_trunks, ringing_trunk, entry); 04265 ast_mutex_unlock(&sla.lock); 04266 04267 sla_queue_event(SLA_EVENT_RINGING_TRUNK); 04268 04269 return ringing_trunk; 04270 }
static void * recordthread | ( | void * | args | ) | [static] |
Definition at line 2982 of file app_meetme.c.
References ast_closestream(), AST_FRAME_BITS, AST_FRAME_VOICE, ast_frdup(), ast_frfree(), AST_LIST_LOCK, AST_LIST_UNLOCK, ast_mutex_lock(), ast_mutex_unlock(), ast_read(), ast_stopstream(), ast_waitfor(), ast_writefile(), ast_writestream(), f, ast_frame::frametype, ast_conference::lchan, ast_conference::listenlock, MEETME_RECORD_ACTIVE, MEETME_RECORD_OFF, MEETME_RECORD_TERMINATE, ast_conference::origframe, ast_conference::recordingfilename, ast_conference::recordingformat, s, and ast_conference::transframe.
02983 { 02984 struct ast_conference *cnf = args; 02985 struct ast_frame *f=NULL; 02986 int flags; 02987 struct ast_filestream *s=NULL; 02988 int res=0; 02989 int x; 02990 const char *oldrecordingfilename = NULL; 02991 02992 if (!cnf || !cnf->lchan) { 02993 pthread_exit(0); 02994 } 02995 02996 ast_stopstream(cnf->lchan); 02997 flags = O_CREAT|O_TRUNC|O_WRONLY; 02998 02999 03000 cnf->recording = MEETME_RECORD_ACTIVE; 03001 while (ast_waitfor(cnf->lchan, -1) > -1) { 03002 if (cnf->recording == MEETME_RECORD_TERMINATE) { 03003 AST_LIST_LOCK(&confs); 03004 AST_LIST_UNLOCK(&confs); 03005 break; 03006 } 03007 if (!s && cnf->recordingfilename && (cnf->recordingfilename != oldrecordingfilename)) { 03008 s = ast_writefile(cnf->recordingfilename, cnf->recordingformat, NULL, flags, 0, 0644); 03009 oldrecordingfilename = cnf->recordingfilename; 03010 } 03011 03012 f = ast_read(cnf->lchan); 03013 if (!f) { 03014 res = -1; 03015 break; 03016 } 03017 if (f->frametype == AST_FRAME_VOICE) { 03018 ast_mutex_lock(&cnf->listenlock); 03019 for (x=0;x<AST_FRAME_BITS;x++) { 03020 /* Free any translations that have occured */ 03021 if (cnf->transframe[x]) { 03022 ast_frfree(cnf->transframe[x]); 03023 cnf->transframe[x] = NULL; 03024 } 03025 } 03026 if (cnf->origframe) 03027 ast_frfree(cnf->origframe); 03028 cnf->origframe = ast_frdup(f); 03029 ast_mutex_unlock(&cnf->listenlock); 03030 if (s) 03031 res = ast_writestream(s, f); 03032 if (res) { 03033 ast_frfree(f); 03034 break; 03035 } 03036 } 03037 ast_frfree(f); 03038 } 03039 cnf->recording = MEETME_RECORD_OFF; 03040 if (s) 03041 ast_closestream(s); 03042 03043 pthread_exit(0); 03044 }
static int reload | ( | void | ) | [static] |
Definition at line 4816 of file app_meetme.c.
References load_config().
04817 { 04818 return load_config(1); 04819 }
static void reset_volumes | ( | struct ast_conf_user * | user | ) | [static] |
Definition at line 684 of file app_meetme.c.
References ast_channel_setoption(), AST_OPTION_RXGAIN, AST_OPTION_TXGAIN, and ast_conf_user::chan.
Referenced by admin_exec(), and conf_run().
00685 { 00686 signed char zero_volume = 0; 00687 00688 ast_channel_setoption(user->chan, AST_OPTION_TXGAIN, &zero_volume, sizeof(zero_volume), 0); 00689 ast_channel_setoption(user->chan, AST_OPTION_RXGAIN, &zero_volume, sizeof(zero_volume), 0); 00690 }
static void* run_station | ( | void * | data | ) | [static] |
Definition at line 3228 of file app_meetme.c.
References admin_exec(), ALL_TRUNK_REFS, ast_answer(), ast_cond_signal(), ast_dial_destroy(), ast_dial_join(), ast_mutex_lock(), ast_mutex_unlock(), ast_set_flag, build_conf(), run_station_args::cond, run_station_args::cond_lock, conf_run(), CONFFLAG_MARKEDEXIT, CONFFLAG_PASS_DTMF, CONFFLAG_QUIET, CONFFLAG_SLA_STATION, dispose_conf(), ast_flags::flags, MAX_CONFNUM, sla_change_trunk_state(), SLA_TRUNK_STATE_IDLE, SLA_TRUNK_STATE_ONHOLD_BYME, run_station_args::station, and run_station_args::trunk_ref.
Referenced by sla_handle_dial_state_event().
03229 { 03230 struct sla_station *station; 03231 struct sla_trunk_ref *trunk_ref; 03232 char conf_name[MAX_CONFNUM]; 03233 struct ast_flags conf_flags = { 0 }; 03234 struct ast_conference *conf; 03235 03236 { 03237 struct run_station_args *args = data; 03238 station = args->station; 03239 trunk_ref = args->trunk_ref; 03240 ast_mutex_lock(args->cond_lock); 03241 ast_cond_signal(args->cond); 03242 ast_mutex_unlock(args->cond_lock); 03243 /* args is no longer valid here. */ 03244 } 03245 03246 ast_atomic_fetchadd_int((int *) &trunk_ref->trunk->active_stations, 1); 03247 snprintf(conf_name, sizeof(conf_name), "SLA_%s", trunk_ref->trunk->name); 03248 ast_set_flag(&conf_flags, 03249 CONFFLAG_QUIET | CONFFLAG_MARKEDEXIT | CONFFLAG_PASS_DTMF | CONFFLAG_SLA_STATION); 03250 ast_answer(trunk_ref->chan); 03251 conf = build_conf(conf_name, "", "", 0, 0, 1); 03252 if (conf) { 03253 conf_run(trunk_ref->chan, conf, conf_flags.flags, NULL); 03254 dispose_conf(conf); 03255 conf = NULL; 03256 } 03257 trunk_ref->chan = NULL; 03258 if (ast_atomic_dec_and_test((int *) &trunk_ref->trunk->active_stations) && 03259 trunk_ref->state != SLA_TRUNK_STATE_ONHOLD_BYME) { 03260 strncat(conf_name, "|K", sizeof(conf_name) - strlen(conf_name) - 1); 03261 admin_exec(NULL, conf_name); 03262 trunk_ref->trunk->hold_stations = 0; 03263 sla_change_trunk_state(trunk_ref->trunk, SLA_TRUNK_STATE_IDLE, ALL_TRUNK_REFS, NULL); 03264 } 03265 03266 ast_dial_join(station->dial); 03267 ast_dial_destroy(station->dial); 03268 station->dial = NULL; 03269 03270 return NULL; 03271 }
static int set_listen_volume | ( | struct ast_conf_user * | user, | |
int | volume | |||
) | [static] |
Definition at line 613 of file app_meetme.c.
References ast_channel_setoption(), AST_OPTION_TXGAIN, and ast_conf_user::chan.
Referenced by tweak_listen_volume().
00614 { 00615 char gain_adjust; 00616 00617 /* attempt to make the adjustment in the channel driver; 00618 if successful, don't adjust in the frame reading routine 00619 */ 00620 gain_adjust = gain_map[volume + 5]; 00621 00622 return ast_channel_setoption(user->chan, AST_OPTION_TXGAIN, &gain_adjust, sizeof(gain_adjust), 0); 00623 }
static int set_talk_volume | ( | struct ast_conf_user * | user, | |
int | volume | |||
) | [static] |
Definition at line 601 of file app_meetme.c.
References ast_channel_setoption(), AST_OPTION_RXGAIN, and ast_conf_user::chan.
Referenced by conf_run(), and tweak_talk_volume().
00602 { 00603 char gain_adjust; 00604 00605 /* attempt to make the adjustment in the channel driver; 00606 if successful, don't adjust in the frame reading routine 00607 */ 00608 gain_adjust = gain_map[volume + 5]; 00609 00610 return ast_channel_setoption(user->chan, AST_OPTION_RXGAIN, &gain_adjust, sizeof(gain_adjust), 0); 00611 }
static void sla_add_trunk_to_station | ( | struct sla_station * | station, | |
struct ast_variable * | var | |||
) | [static] |
Definition at line 4550 of file app_meetme.c.
References AST_LIST_INSERT_TAIL, ast_log(), AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_strdupa, create_trunk_ref(), free, LOG_ERROR, LOG_WARNING, name, sla_create_station_ref(), SLA_TRUNK_STATE_IDLE, strsep(), and ast_variable::value.
Referenced by sla_build_station().
04551 { 04552 struct sla_trunk *trunk; 04553 struct sla_trunk_ref *trunk_ref; 04554 struct sla_station_ref *station_ref; 04555 char *trunk_name, *options, *cur; 04556 04557 options = ast_strdupa(var->value); 04558 trunk_name = strsep(&options, ","); 04559 04560 AST_RWLIST_RDLOCK(&sla_trunks); 04561 AST_RWLIST_TRAVERSE(&sla_trunks, trunk, entry) { 04562 if (!strcasecmp(trunk->name, trunk_name)) 04563 break; 04564 } 04565 04566 AST_RWLIST_UNLOCK(&sla_trunks); 04567 if (!trunk) { 04568 ast_log(LOG_ERROR, "Trunk '%s' not found!\n", var->value); 04569 return; 04570 } 04571 if (!(trunk_ref = create_trunk_ref(trunk))) 04572 return; 04573 trunk_ref->state = SLA_TRUNK_STATE_IDLE; 04574 04575 while ((cur = strsep(&options, ","))) { 04576 char *name, *value = cur; 04577 name = strsep(&value, "="); 04578 if (!strcasecmp(name, "ringtimeout")) { 04579 if (sscanf(value, "%u", &trunk_ref->ring_timeout) != 1) { 04580 ast_log(LOG_WARNING, "Invalid ringtimeout value '%s' for " 04581 "trunk '%s' on station '%s'\n", value, trunk->name, station->name); 04582 trunk_ref->ring_timeout = 0; 04583 } 04584 } else if (!strcasecmp(name, "ringdelay")) { 04585 if (sscanf(value, "%u", &trunk_ref->ring_delay) != 1) { 04586 ast_log(LOG_WARNING, "Invalid ringdelay value '%s' for " 04587 "trunk '%s' on station '%s'\n", value, trunk->name, station->name); 04588 trunk_ref->ring_delay = 0; 04589 } 04590 } else { 04591 ast_log(LOG_WARNING, "Invalid option '%s' for " 04592 "trunk '%s' on station '%s'\n", name, trunk->name, station->name); 04593 } 04594 } 04595 04596 if (!(station_ref = sla_create_station_ref(station))) { 04597 free(trunk_ref); 04598 return; 04599 } 04600 ast_atomic_fetchadd_int((int *) &trunk->num_stations, 1); 04601 AST_RWLIST_WRLOCK(&sla_trunks); 04602 AST_LIST_INSERT_TAIL(&trunk->stations, station_ref, entry); 04603 AST_RWLIST_UNLOCK(&sla_trunks); 04604 AST_LIST_INSERT_TAIL(&station->trunks, trunk_ref, entry); 04605 }
static int sla_build_station | ( | struct ast_config * | cfg, | |
const char * | cat | |||
) | [static] |
Definition at line 4607 of file app_meetme.c.
References ast_add_extension2(), ast_calloc, ast_context_find_or_create(), ast_free, AST_LIST_TRAVERSE, ast_log(), AST_MAX_APP, AST_MAX_EXTENSION, AST_RWLIST_INSERT_TAIL, AST_RWLIST_RDLOCK, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_strdup, ast_string_field_init, ast_string_field_set, ast_strlen_zero(), ast_variable_browse(), ast_variable_retrieve(), context, destroy_station(), exten, free, ast_variable::lineno, LOG_ERROR, LOG_WARNING, ast_variable::name, name, ast_variable::next, PRIORITY_HINT, sla_add_trunk_to_station(), SLA_CONFIG_FILE, SLA_HOLD_OPEN, SLA_HOLD_PRIVATE, sla_registrar, ast_variable::value, and var.
Referenced by sla_load_config().
04608 { 04609 struct sla_station *station; 04610 struct ast_variable *var; 04611 const char *dev; 04612 04613 if (!(dev = ast_variable_retrieve(cfg, cat, "device"))) { 04614 ast_log(LOG_ERROR, "SLA Station '%s' defined with no device!\n", cat); 04615 return -1; 04616 } 04617 04618 if (!(station = ast_calloc(1, sizeof(*station)))) 04619 return -1; 04620 if (ast_string_field_init(station, 32)) { 04621 free(station); 04622 return -1; 04623 } 04624 04625 ast_string_field_set(station, name, cat); 04626 ast_string_field_set(station, device, dev); 04627 04628 for (var = ast_variable_browse(cfg, cat); var; var = var->next) { 04629 if (!strcasecmp(var->name, "trunk")) 04630 sla_add_trunk_to_station(station, var); 04631 else if (!strcasecmp(var->name, "autocontext")) 04632 ast_string_field_set(station, autocontext, var->value); 04633 else if (!strcasecmp(var->name, "ringtimeout")) { 04634 if (sscanf(var->value, "%u", &station->ring_timeout) != 1) { 04635 ast_log(LOG_WARNING, "Invalid ringtimeout '%s' specified for station '%s'\n", 04636 var->value, station->name); 04637 station->ring_timeout = 0; 04638 } 04639 } else if (!strcasecmp(var->name, "ringdelay")) { 04640 if (sscanf(var->value, "%u", &station->ring_delay) != 1) { 04641 ast_log(LOG_WARNING, "Invalid ringdelay '%s' specified for station '%s'\n", 04642 var->value, station->name); 04643 station->ring_delay = 0; 04644 } 04645 } else if (!strcasecmp(var->name, "hold")) { 04646 if (!strcasecmp(var->value, "private")) 04647 station->hold_access = SLA_HOLD_PRIVATE; 04648 else if (!strcasecmp(var->value, "open")) 04649 station->hold_access = SLA_HOLD_OPEN; 04650 else { 04651 ast_log(LOG_WARNING, "Invalid value '%s' for hold on station %s\n", 04652 var->value, station->name); 04653 } 04654 04655 } else if (strcasecmp(var->name, "type") && strcasecmp(var->name, "device")) { 04656 ast_log(LOG_ERROR, "Invalid option '%s' specified at line %d of %s!\n", 04657 var->name, var->lineno, SLA_CONFIG_FILE); 04658 } 04659 } 04660 04661 if (!ast_strlen_zero(station->autocontext)) { 04662 struct ast_context *context; 04663 struct sla_trunk_ref *trunk_ref; 04664 context = ast_context_find_or_create(NULL, station->autocontext, sla_registrar); 04665 if (!context) { 04666 ast_log(LOG_ERROR, "Failed to automatically find or create " 04667 "context '%s' for SLA!\n", station->autocontext); 04668 destroy_station(station); 04669 return -1; 04670 } 04671 /* The extension for when the handset goes off-hook. 04672 * exten => station1,1,SLAStation(station1) */ 04673 if (ast_add_extension2(context, 0 /* don't replace */, station->name, 1, 04674 NULL, NULL, slastation_app, ast_strdup(station->name), ast_free, sla_registrar)) { 04675 ast_log(LOG_ERROR, "Failed to automatically create extension " 04676 "for trunk '%s'!\n", station->name); 04677 destroy_station(station); 04678 return -1; 04679 } 04680 AST_RWLIST_RDLOCK(&sla_trunks); 04681 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) { 04682 char exten[AST_MAX_EXTENSION]; 04683 char hint[AST_MAX_APP]; 04684 snprintf(exten, sizeof(exten), "%s_%s", station->name, trunk_ref->trunk->name); 04685 snprintf(hint, sizeof(hint), "SLA:%s", exten); 04686 /* Extension for this line button 04687 * exten => station1_line1,1,SLAStation(station1_line1) */ 04688 if (ast_add_extension2(context, 0 /* don't replace */, exten, 1, 04689 NULL, NULL, slastation_app, ast_strdup(exten), ast_free, sla_registrar)) { 04690 ast_log(LOG_ERROR, "Failed to automatically create extension " 04691 "for trunk '%s'!\n", station->name); 04692 destroy_station(station); 04693 return -1; 04694 } 04695 /* Hint for this line button 04696 * exten => station1_line1,hint,SLA:station1_line1 */ 04697 if (ast_add_extension2(context, 0 /* don't replace */, exten, PRIORITY_HINT, 04698 NULL, NULL, hint, NULL, NULL, sla_registrar)) { 04699 ast_log(LOG_ERROR, "Failed to automatically create hint " 04700 "for trunk '%s'!\n", station->name); 04701 destroy_station(station); 04702 return -1; 04703 } 04704 } 04705 AST_RWLIST_UNLOCK(&sla_trunks); 04706 } 04707 04708 AST_RWLIST_WRLOCK(&sla_stations); 04709 AST_RWLIST_INSERT_TAIL(&sla_stations, station, entry); 04710 AST_RWLIST_UNLOCK(&sla_stations); 04711 04712 return 0; 04713 }
static int sla_build_trunk | ( | struct ast_config * | cfg, | |
const char * | cat | |||
) | [static] |
Definition at line 4472 of file app_meetme.c.
References ast_add_extension2(), ast_calloc, ast_context_find_or_create(), ast_false(), ast_free, ast_log(), AST_RWLIST_INSERT_TAIL, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_strdup, ast_string_field_init, ast_string_field_set, ast_strlen_zero(), ast_variable_browse(), ast_variable_retrieve(), context, destroy_trunk(), free, ast_variable::lineno, LOG_ERROR, LOG_WARNING, ast_variable::name, name, ast_variable::next, sla_check_device(), SLA_CONFIG_FILE, SLA_HOLD_OPEN, SLA_HOLD_PRIVATE, sla_registrar, ast_variable::value, and var.
Referenced by sla_load_config().
04473 { 04474 struct sla_trunk *trunk; 04475 struct ast_variable *var; 04476 const char *dev; 04477 04478 if (!(dev = ast_variable_retrieve(cfg, cat, "device"))) { 04479 ast_log(LOG_ERROR, "SLA Trunk '%s' defined with no device!\n", cat); 04480 return -1; 04481 } 04482 04483 if (sla_check_device(dev)) { 04484 ast_log(LOG_ERROR, "SLA Trunk '%s' define with invalid device '%s'!\n", 04485 cat, dev); 04486 return -1; 04487 } 04488 04489 if (!(trunk = ast_calloc(1, sizeof(*trunk)))) 04490 return -1; 04491 if (ast_string_field_init(trunk, 32)) { 04492 free(trunk); 04493 return -1; 04494 } 04495 04496 ast_string_field_set(trunk, name, cat); 04497 ast_string_field_set(trunk, device, dev); 04498 04499 for (var = ast_variable_browse(cfg, cat); var; var = var->next) { 04500 if (!strcasecmp(var->name, "autocontext")) 04501 ast_string_field_set(trunk, autocontext, var->value); 04502 else if (!strcasecmp(var->name, "ringtimeout")) { 04503 if (sscanf(var->value, "%u", &trunk->ring_timeout) != 1) { 04504 ast_log(LOG_WARNING, "Invalid ringtimeout '%s' specified for trunk '%s'\n", 04505 var->value, trunk->name); 04506 trunk->ring_timeout = 0; 04507 } 04508 } else if (!strcasecmp(var->name, "barge")) 04509 trunk->barge_disabled = ast_false(var->value); 04510 else if (!strcasecmp(var->name, "hold")) { 04511 if (!strcasecmp(var->value, "private")) 04512 trunk->hold_access = SLA_HOLD_PRIVATE; 04513 else if (!strcasecmp(var->value, "open")) 04514 trunk->hold_access = SLA_HOLD_OPEN; 04515 else { 04516 ast_log(LOG_WARNING, "Invalid value '%s' for hold on trunk %s\n", 04517 var->value, trunk->name); 04518 } 04519 } else if (strcasecmp(var->name, "type") && strcasecmp(var->name, "device")) { 04520 ast_log(LOG_ERROR, "Invalid option '%s' specified at line %d of %s!\n", 04521 var->name, var->lineno, SLA_CONFIG_FILE); 04522 } 04523 } 04524 04525 if (!ast_strlen_zero(trunk->autocontext)) { 04526 struct ast_context *context; 04527 context = ast_context_find_or_create(NULL, trunk->autocontext, sla_registrar); 04528 if (!context) { 04529 ast_log(LOG_ERROR, "Failed to automatically find or create " 04530 "context '%s' for SLA!\n", trunk->autocontext); 04531 destroy_trunk(trunk); 04532 return -1; 04533 } 04534 if (ast_add_extension2(context, 0 /* don't replace */, "s", 1, 04535 NULL, NULL, slatrunk_app, ast_strdup(trunk->name), ast_free, sla_registrar)) { 04536 ast_log(LOG_ERROR, "Failed to automatically create extension " 04537 "for trunk '%s'!\n", trunk->name); 04538 destroy_trunk(trunk); 04539 return -1; 04540 } 04541 } 04542 04543 AST_RWLIST_WRLOCK(&sla_trunks); 04544 AST_RWLIST_INSERT_TAIL(&sla_trunks, trunk, entry); 04545 AST_RWLIST_UNLOCK(&sla_trunks); 04546 04547 return 0; 04548 }
static int sla_calc_station_delays | ( | unsigned int * | timeout | ) | [static] |
Calculate the ring delay for a station.
Definition at line 3845 of file app_meetme.c.
References AST_LIST_TRAVERSE, sla_check_inuse_station(), sla_check_ringing_station(), sla_check_station_delay(), and sla_choose_ringing_trunk().
Referenced by sla_process_timers().
03846 { 03847 struct sla_station *station; 03848 int res = 0; 03849 03850 AST_LIST_TRAVERSE(&sla_stations, station, entry) { 03851 struct sla_ringing_trunk *ringing_trunk; 03852 int time_left; 03853 03854 /* Ignore stations already ringing */ 03855 if (sla_check_ringing_station(station)) 03856 continue; 03857 03858 /* Ignore stations already on a call */ 03859 if (sla_check_inuse_station(station)) 03860 continue; 03861 03862 /* Ignore stations that don't have one of their trunks ringing */ 03863 if (!(ringing_trunk = sla_choose_ringing_trunk(station, NULL, 0))) 03864 continue; 03865 03866 if ((time_left = sla_check_station_delay(station, ringing_trunk)) == INT_MAX) 03867 continue; 03868 03869 /* If there is no time left, then the station needs to start ringing. 03870 * Return non-zero so that an event will be queued up an event to 03871 * make that happen. */ 03872 if (time_left <= 0) { 03873 res = 1; 03874 continue; 03875 } 03876 03877 if (time_left < *timeout) 03878 *timeout = time_left; 03879 } 03880 03881 return res; 03882 }
static int sla_calc_station_timeouts | ( | unsigned int * | timeout | ) | [static] |
Process station ring timeouts.
Definition at line 3762 of file app_meetme.c.
References AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, sla_ringing_station::ring_begin, sla_ringing_trunk::ring_begin, sla, SLA_STATION_HANGUP_TIMEOUT, sla_stop_ringing_station(), sla_ringing_station::station, and sla_ringing_trunk::trunk.
Referenced by sla_process_timers().
03763 { 03764 struct sla_ringing_trunk *ringing_trunk; 03765 struct sla_ringing_station *ringing_station; 03766 int res = 0; 03767 03768 AST_LIST_TRAVERSE_SAFE_BEGIN(&sla.ringing_stations, ringing_station, entry) { 03769 unsigned int ring_timeout = 0; 03770 int time_elapsed, time_left = INT_MAX, final_trunk_time_left = INT_MIN; 03771 struct sla_trunk_ref *trunk_ref; 03772 03773 /* If there are any ring timeouts specified for a specific trunk 03774 * on the station, then use the highest per-trunk ring timeout. 03775 * Otherwise, use the ring timeout set for the entire station. */ 03776 AST_LIST_TRAVERSE(&ringing_station->station->trunks, trunk_ref, entry) { 03777 struct sla_station_ref *station_ref; 03778 int trunk_time_elapsed, trunk_time_left; 03779 03780 AST_LIST_TRAVERSE(&sla.ringing_trunks, ringing_trunk, entry) { 03781 if (ringing_trunk->trunk == trunk_ref->trunk) 03782 break; 03783 } 03784 if (!ringing_trunk) 03785 continue; 03786 03787 /* If there is a trunk that is ringing without a timeout, then the 03788 * only timeout that could matter is a global station ring timeout. */ 03789 if (!trunk_ref->ring_timeout) 03790 break; 03791 03792 /* This trunk on this station is ringing and has a timeout. 03793 * However, make sure this trunk isn't still ringing from a 03794 * previous timeout. If so, don't consider it. */ 03795 AST_LIST_TRAVERSE(&ringing_trunk->timed_out_stations, station_ref, entry) { 03796 if (station_ref->station == ringing_station->station) 03797 break; 03798 } 03799 if (station_ref) 03800 continue; 03801 03802 trunk_time_elapsed = ast_tvdiff_ms(ast_tvnow(), ringing_trunk->ring_begin); 03803 trunk_time_left = (trunk_ref->ring_timeout * 1000) - trunk_time_elapsed; 03804 if (trunk_time_left > final_trunk_time_left) 03805 final_trunk_time_left = trunk_time_left; 03806 } 03807 03808 /* No timeout was found for ringing trunks, and no timeout for the entire station */ 03809 if (final_trunk_time_left == INT_MIN && !ringing_station->station->ring_timeout) 03810 continue; 03811 03812 /* Compute how much time is left for a global station timeout */ 03813 if (ringing_station->station->ring_timeout) { 03814 ring_timeout = ringing_station->station->ring_timeout; 03815 time_elapsed = ast_tvdiff_ms(ast_tvnow(), ringing_station->ring_begin); 03816 time_left = (ring_timeout * 1000) - time_elapsed; 03817 } 03818 03819 /* If the time left based on the per-trunk timeouts is smaller than the 03820 * global station ring timeout, use that. */ 03821 if (final_trunk_time_left > INT_MIN && final_trunk_time_left < time_left) 03822 time_left = final_trunk_time_left; 03823 03824 /* If there is no time left, the station needs to stop ringing */ 03825 if (time_left <= 0) { 03826 AST_LIST_REMOVE_CURRENT(&sla.ringing_stations, entry); 03827 sla_stop_ringing_station(ringing_station, SLA_STATION_HANGUP_TIMEOUT); 03828 res = 1; 03829 continue; 03830 } 03831 03832 /* There is still some time left for this station to ring, so save that 03833 * timeout if it is the first event scheduled to occur */ 03834 if (time_left < *timeout) 03835 *timeout = time_left; 03836 } 03837 AST_LIST_TRAVERSE_SAFE_END 03838 03839 return res; 03840 }
static int sla_calc_trunk_timeouts | ( | unsigned int * | timeout | ) | [static] |
Process trunk ring timeouts.
Definition at line 3732 of file app_meetme.c.
References AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, pbx_builtin_setvar_helper(), sla_ringing_trunk::ring_begin, sla, sla_stop_ringing_trunk(), and sla_ringing_trunk::trunk.
Referenced by sla_process_timers().
03733 { 03734 struct sla_ringing_trunk *ringing_trunk; 03735 int res = 0; 03736 03737 AST_LIST_TRAVERSE_SAFE_BEGIN(&sla.ringing_trunks, ringing_trunk, entry) { 03738 int time_left, time_elapsed; 03739 if (!ringing_trunk->trunk->ring_timeout) 03740 continue; 03741 time_elapsed = ast_tvdiff_ms(ast_tvnow(), ringing_trunk->ring_begin); 03742 time_left = (ringing_trunk->trunk->ring_timeout * 1000) - time_elapsed; 03743 if (time_left <= 0) { 03744 pbx_builtin_setvar_helper(ringing_trunk->trunk->chan, "SLATRUNK_STATUS", "RINGTIMEOUT"); 03745 AST_LIST_REMOVE_CURRENT(&sla.ringing_trunks, entry); 03746 sla_stop_ringing_trunk(ringing_trunk); 03747 res = 1; 03748 continue; 03749 } 03750 if (time_left < *timeout) 03751 *timeout = time_left; 03752 } 03753 AST_LIST_TRAVERSE_SAFE_END 03754 03755 return res; 03756 }
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 3203 of file app_meetme.c.
References ast_device_state_changed(), and AST_LIST_TRAVERSE.
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().
03205 { 03206 struct sla_station *station; 03207 struct sla_trunk_ref *trunk_ref; 03208 03209 AST_LIST_TRAVERSE(&sla_stations, station, entry) { 03210 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) { 03211 if (trunk_ref->trunk != trunk || (inactive_only ? trunk_ref->chan : 0) 03212 || trunk_ref == exclude) 03213 continue; 03214 trunk_ref->state = state; 03215 ast_device_state_changed("SLA:%s_%s", station->name, trunk->name); 03216 break; 03217 } 03218 } 03219 }
static int sla_check_device | ( | const char * | device | ) | [static] |
Definition at line 4459 of file app_meetme.c.
References ast_strdupa, ast_strlen_zero(), and strsep().
Referenced by sla_build_trunk().
04460 { 04461 char *tech, *tech_data; 04462 04463 tech_data = ast_strdupa(device); 04464 tech = strsep(&tech_data, "/"); 04465 04466 if (ast_strlen_zero(tech) || ast_strlen_zero(tech_data)) 04467 return -1; 04468 04469 return 0; 04470 }
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.
Definition at line 3480 of file app_meetme.c.
References AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, free, sla_failed_station::last_try, sla, and sla_failed_station::station.
Referenced by sla_ring_stations().
03481 { 03482 struct sla_failed_station *failed_station; 03483 int res = 0; 03484 03485 AST_LIST_TRAVERSE_SAFE_BEGIN(&sla.failed_stations, failed_station, entry) { 03486 if (station != failed_station->station) 03487 continue; 03488 if (ast_tvdiff_ms(ast_tvnow(), failed_station->last_try) > 1000) { 03489 AST_LIST_REMOVE_CURRENT(&sla.failed_stations, entry); 03490 free(failed_station); 03491 break; 03492 } 03493 res = 1; 03494 } 03495 AST_LIST_TRAVERSE_SAFE_END 03496 03497 return res; 03498 }
static int sla_check_inuse_station | ( | const struct sla_station * | station | ) | [static] |
Check to see if a station is in use.
Definition at line 3566 of file app_meetme.c.
References AST_LIST_TRAVERSE.
Referenced by sla_calc_station_delays(), and sla_ring_stations().
03567 { 03568 struct sla_trunk_ref *trunk_ref; 03569 03570 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) { 03571 if (trunk_ref->chan) 03572 return 1; 03573 } 03574 03575 return 0; 03576 }
static int sla_check_ringing_station | ( | const struct sla_station * | station | ) | [static] |
Check to see if this station is already ringing.
Definition at line 3465 of file app_meetme.c.
References AST_LIST_TRAVERSE, sla, and sla_ringing_station::station.
Referenced by sla_calc_station_delays(), and sla_ring_stations().
03466 { 03467 struct sla_ringing_station *ringing_station; 03468 03469 AST_LIST_TRAVERSE(&sla.ringing_stations, ringing_station, entry) { 03470 if (station == ringing_station->station) 03471 return 1; 03472 } 03473 03474 return 0; 03475 }
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.
station | the station | |
trunk | the trunk. If NULL, the highest priority ringing trunk will be used |
Definition at line 3596 of file app_meetme.c.
References sla_ringing_trunk::ring_begin, sla_choose_ringing_trunk(), sla_find_trunk_ref(), and sla_ringing_trunk::trunk.
Referenced by sla_calc_station_delays(), and sla_ring_stations().
03598 { 03599 struct sla_trunk_ref *trunk_ref; 03600 unsigned int delay = UINT_MAX; 03601 int time_left, time_elapsed; 03602 03603 if (!ringing_trunk) 03604 ringing_trunk = sla_choose_ringing_trunk(station, &trunk_ref, 0); 03605 else 03606 trunk_ref = sla_find_trunk_ref(station, ringing_trunk->trunk); 03607 03608 if (!ringing_trunk || !trunk_ref) 03609 return delay; 03610 03611 /* If this station has a ring delay specific to the highest priority 03612 * ringing trunk, use that. Otherwise, use the ring delay specified 03613 * globally for the station. */ 03614 delay = trunk_ref->ring_delay; 03615 if (!delay) 03616 delay = station->ring_delay; 03617 if (!delay) 03618 return INT_MAX; 03619 03620 time_elapsed = ast_tvdiff_ms(ast_tvnow(), ringing_trunk->ring_begin); 03621 time_left = (delay * 1000) - time_elapsed; 03622 03623 return time_left; 03624 }
static int sla_check_station_hold_access | ( | const struct sla_trunk * | trunk, | |
const struct sla_station * | station | |||
) | [static] |
Definition at line 3125 of file app_meetme.c.
References AST_LIST_TRAVERSE, SLA_HOLD_PRIVATE, and SLA_TRUNK_STATE_ONHOLD_BYME.
Referenced by sla_find_trunk_ref_byname().
03127 { 03128 struct sla_station_ref *station_ref; 03129 struct sla_trunk_ref *trunk_ref; 03130 03131 /* For each station that has this call on hold, check for private hold. */ 03132 AST_LIST_TRAVERSE(&trunk->stations, station_ref, entry) { 03133 AST_LIST_TRAVERSE(&station_ref->station->trunks, trunk_ref, entry) { 03134 if (trunk_ref->trunk != trunk || station_ref->station == station) 03135 continue; 03136 if (trunk_ref->state == SLA_TRUNK_STATE_ONHOLD_BYME && 03137 station_ref->station->hold_access == SLA_HOLD_PRIVATE) 03138 return 1; 03139 return 0; 03140 } 03141 } 03142 03143 return 0; 03144 }
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.
Definition at line 3331 of file app_meetme.c.
References AST_LIST_TRAVERSE.
Referenced by sla_choose_ringing_trunk(), and sla_ring_stations().
03333 { 03334 struct sla_station_ref *timed_out_station; 03335 03336 AST_LIST_TRAVERSE(&ringing_trunk->timed_out_stations, timed_out_station, entry) { 03337 if (station == timed_out_station->station) 03338 return 1; 03339 } 03340 03341 return 0; 03342 }
static struct sla_trunk_ref* sla_choose_idle_trunk | ( | const struct sla_station * | station | ) | [static, read] |
For a given station, choose the highest priority idle trunk.
Definition at line 4096 of file app_meetme.c.
References AST_LIST_TRAVERSE, and SLA_TRUNK_STATE_IDLE.
Referenced by sla_station_exec().
04097 { 04098 struct sla_trunk_ref *trunk_ref = NULL; 04099 04100 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) { 04101 if (trunk_ref->state == SLA_TRUNK_STATE_IDLE) 04102 break; 04103 } 04104 04105 return trunk_ref; 04106 }
static struct sla_ringing_trunk* sla_choose_ringing_trunk | ( | struct sla_station * | station, | |
struct sla_trunk_ref ** | trunk_ref, | |||
int | remove | |||
) | [static, read] |
Choose the highest priority ringing trunk for a station.
station | the station | |
remove | remove the ringing trunk once selected | |
trunk_ref | a place to store the pointer to this stations reference to the selected trunk |
Definition at line 3352 of file app_meetme.c.
References AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, sla, sla_check_timed_out_station(), and sla_ringing_trunk::trunk.
Referenced by sla_calc_station_delays(), sla_check_station_delay(), and sla_handle_dial_state_event().
03354 { 03355 struct sla_trunk_ref *s_trunk_ref; 03356 struct sla_ringing_trunk *ringing_trunk = NULL; 03357 03358 AST_LIST_TRAVERSE(&station->trunks, s_trunk_ref, entry) { 03359 AST_LIST_TRAVERSE_SAFE_BEGIN(&sla.ringing_trunks, ringing_trunk, entry) { 03360 /* Make sure this is the trunk we're looking for */ 03361 if (s_trunk_ref->trunk != ringing_trunk->trunk) 03362 continue; 03363 03364 /* This trunk on the station is ringing. But, make sure this station 03365 * didn't already time out while this trunk was ringing. */ 03366 if (sla_check_timed_out_station(ringing_trunk, station)) 03367 continue; 03368 03369 if (remove) 03370 AST_LIST_REMOVE_CURRENT(&sla.ringing_trunks, entry); 03371 03372 if (trunk_ref) 03373 *trunk_ref = s_trunk_ref; 03374 03375 break; 03376 } 03377 AST_LIST_TRAVERSE_SAFE_END 03378 03379 if (ringing_trunk) 03380 break; 03381 } 03382 03383 return ringing_trunk; 03384 }
static struct sla_ringing_station* sla_create_ringing_station | ( | struct sla_station * | station | ) | [static, read] |
Definition at line 3190 of file app_meetme.c.
References ast_calloc, sla_ringing_station::ring_begin, and sla_ringing_station::station.
Referenced by sla_ring_station().
03191 { 03192 struct sla_ringing_station *ringing_station; 03193 03194 if (!(ringing_station = ast_calloc(1, sizeof(*ringing_station)))) 03195 return NULL; 03196 03197 ringing_station->station = station; 03198 ringing_station->ring_begin = ast_tvnow(); 03199 03200 return ringing_station; 03201 }
static struct sla_station_ref* sla_create_station_ref | ( | struct sla_station * | station | ) | [static, read] |
Definition at line 3178 of file app_meetme.c.
References ast_calloc.
Referenced by sla_add_trunk_to_station(), and sla_stop_ringing_station().
03179 { 03180 struct sla_station_ref *station_ref; 03181 03182 if (!(station_ref = ast_calloc(1, sizeof(*station_ref)))) 03183 return NULL; 03184 03185 station_ref->station = station; 03186 03187 return station_ref; 03188 }
static void sla_destroy | ( | void | ) | [static] |
Definition at line 4432 of file app_meetme.c.
References ast_cond_destroy(), ast_cond_signal(), ast_mutex_destroy(), ast_mutex_lock(), ast_mutex_unlock(), AST_PTHREADT_NULL, AST_RWLIST_REMOVE_HEAD, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, destroy_station(), destroy_trunk(), and sla.
Referenced by unload_module().
04433 { 04434 struct sla_trunk *trunk; 04435 struct sla_station *station; 04436 04437 AST_RWLIST_WRLOCK(&sla_trunks); 04438 while ((trunk = AST_RWLIST_REMOVE_HEAD(&sla_trunks, entry))) 04439 destroy_trunk(trunk); 04440 AST_RWLIST_UNLOCK(&sla_trunks); 04441 04442 AST_RWLIST_WRLOCK(&sla_stations); 04443 while ((station = AST_RWLIST_REMOVE_HEAD(&sla_stations, entry))) 04444 destroy_station(station); 04445 AST_RWLIST_UNLOCK(&sla_stations); 04446 04447 if (sla.thread != AST_PTHREADT_NULL) { 04448 ast_mutex_lock(&sla.lock); 04449 sla.stop = 1; 04450 ast_cond_signal(&sla.cond); 04451 ast_mutex_unlock(&sla.lock); 04452 pthread_join(sla.thread, NULL); 04453 } 04454 04455 ast_mutex_destroy(&sla.lock); 04456 ast_cond_destroy(&sla.cond); 04457 }
static void sla_dial_state_callback | ( | struct ast_dial * | dial | ) | [static] |
Definition at line 3323 of file app_meetme.c.
References SLA_EVENT_DIAL_STATE, and sla_queue_event().
Referenced by sla_ring_station().
03324 { 03325 sla_queue_event(SLA_EVENT_DIAL_STATE); 03326 }
static struct sla_station* sla_find_station | ( | const char * | name | ) | [static, read] |
Find an SLA station by name.
Definition at line 3113 of file app_meetme.c.
References AST_RWLIST_TRAVERSE.
Referenced by sla_station_exec().
03114 { 03115 struct sla_station *station = NULL; 03116 03117 AST_RWLIST_TRAVERSE(&sla_stations, station, entry) { 03118 if (!strcasecmp(station->name, name)) 03119 break; 03120 } 03121 03122 return station; 03123 }
static struct sla_trunk* sla_find_trunk | ( | const char * | name | ) | [static, read] |
Find an SLA trunk by name.
Definition at line 3098 of file app_meetme.c.
References AST_RWLIST_TRAVERSE.
Referenced by sla_trunk_exec().
03099 { 03100 struct sla_trunk *trunk = NULL; 03101 03102 AST_RWLIST_TRAVERSE(&sla_trunks, trunk, entry) { 03103 if (!strcasecmp(trunk->name, name)) 03104 break; 03105 } 03106 03107 return trunk; 03108 }
static struct sla_trunk_ref* sla_find_trunk_ref | ( | const struct sla_station * | station, | |
const struct sla_trunk * | trunk | |||
) | [static, read] |
Definition at line 3578 of file app_meetme.c.
References AST_LIST_TRAVERSE.
Referenced by sla_check_station_delay().
03580 { 03581 struct sla_trunk_ref *trunk_ref = NULL; 03582 03583 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) { 03584 if (trunk_ref->trunk == trunk) 03585 break; 03586 } 03587 03588 return trunk_ref; 03589 }
static struct sla_trunk_ref* sla_find_trunk_ref_byname | ( | const struct sla_station * | station, | |
const char * | name | |||
) | [static, read] |
Find a trunk reference on a station by name.
station | the station | |
name | the trunk's name |
Definition at line 3153 of file app_meetme.c.
References AST_LIST_TRAVERSE, sla_check_station_hold_access(), SLA_HOLD_PRIVATE, SLA_TRUNK_STATE_ONHOLD_BYME, and SLA_TRUNK_STATE_UP.
Referenced by sla_station_exec().
03155 { 03156 struct sla_trunk_ref *trunk_ref = NULL; 03157 03158 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) { 03159 if (strcasecmp(trunk_ref->trunk->name, name)) 03160 continue; 03161 03162 if ( (trunk_ref->trunk->barge_disabled 03163 && trunk_ref->state == SLA_TRUNK_STATE_UP) || 03164 (trunk_ref->trunk->hold_stations 03165 && trunk_ref->trunk->hold_access == SLA_HOLD_PRIVATE 03166 && trunk_ref->state != SLA_TRUNK_STATE_ONHOLD_BYME) || 03167 sla_check_station_hold_access(trunk_ref->trunk, station) ) 03168 { 03169 trunk_ref = NULL; 03170 } 03171 03172 break; 03173 } 03174 03175 return trunk_ref; 03176 }
static void sla_handle_dial_state_event | ( | void | ) | [static] |
Definition at line 3386 of file app_meetme.c.
References ALL_TRUNK_REFS, ast_answer(), ast_cond_destroy(), ast_cond_init(), ast_cond_wait(), ast_dial_answered(), 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_log(), ast_mutex_destroy(), ast_mutex_init(), ast_mutex_lock(), ast_mutex_unlock(), ast_pthread_create_background, ast_conference::attr, run_station_args::cond, run_station_args::cond_lock, free, LOG_DEBUG, run_station(), sla, sla_change_trunk_state(), sla_choose_ringing_trunk(), SLA_EVENT_DIAL_STATE, SLA_EVENT_RINGING_TRUNK, sla_queue_event(), SLA_STATION_HANGUP_NORMAL, sla_stop_ringing_station(), SLA_TRUNK_STATE_UP, run_station_args::station, sla_ringing_station::station, sla_ringing_trunk::trunk, and run_station_args::trunk_ref.
Referenced by sla_thread().
03387 { 03388 struct sla_ringing_station *ringing_station; 03389 03390 AST_LIST_TRAVERSE_SAFE_BEGIN(&sla.ringing_stations, ringing_station, entry) { 03391 struct sla_trunk_ref *s_trunk_ref = NULL; 03392 struct sla_ringing_trunk *ringing_trunk = NULL; 03393 struct run_station_args args; 03394 enum ast_dial_result dial_res; 03395 pthread_attr_t attr; 03396 pthread_t dont_care; 03397 ast_mutex_t cond_lock; 03398 ast_cond_t cond; 03399 03400 switch ((dial_res = ast_dial_state(ringing_station->station->dial))) { 03401 case AST_DIAL_RESULT_HANGUP: 03402 case AST_DIAL_RESULT_INVALID: 03403 case AST_DIAL_RESULT_FAILED: 03404 case AST_DIAL_RESULT_TIMEOUT: 03405 case AST_DIAL_RESULT_UNANSWERED: 03406 AST_LIST_REMOVE_CURRENT(&sla.ringing_stations, entry); 03407 sla_stop_ringing_station(ringing_station, SLA_STATION_HANGUP_NORMAL); 03408 break; 03409 case AST_DIAL_RESULT_ANSWERED: 03410 AST_LIST_REMOVE_CURRENT(&sla.ringing_stations, entry); 03411 /* Find the appropriate trunk to answer. */ 03412 ast_mutex_lock(&sla.lock); 03413 ringing_trunk = sla_choose_ringing_trunk(ringing_station->station, &s_trunk_ref, 1); 03414 ast_mutex_unlock(&sla.lock); 03415 if (!ringing_trunk) { 03416 ast_log(LOG_DEBUG, "Found no ringing trunk for station '%s' to answer!\n", 03417 ringing_station->station->name); 03418 break; 03419 } 03420 /* Track the channel that answered this trunk */ 03421 s_trunk_ref->chan = ast_dial_answered(ringing_station->station->dial); 03422 /* Actually answer the trunk */ 03423 ast_answer(ringing_trunk->trunk->chan); 03424 sla_change_trunk_state(ringing_trunk->trunk, SLA_TRUNK_STATE_UP, ALL_TRUNK_REFS, NULL); 03425 /* Now, start a thread that will connect this station to the trunk. The rest of 03426 * the code here sets up the thread and ensures that it is able to save the arguments 03427 * before they are no longer valid since they are allocated on the stack. */ 03428 args.trunk_ref = s_trunk_ref; 03429 args.station = ringing_station->station; 03430 args.cond = &cond; 03431 args.cond_lock = &cond_lock; 03432 free(ringing_trunk); 03433 free(ringing_station); 03434 ast_mutex_init(&cond_lock); 03435 ast_cond_init(&cond, NULL); 03436 pthread_attr_init(&attr); 03437 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 03438 ast_mutex_lock(&cond_lock); 03439 ast_pthread_create_background(&dont_care, &attr, run_station, &args); 03440 ast_cond_wait(&cond, &cond_lock); 03441 ast_mutex_unlock(&cond_lock); 03442 ast_mutex_destroy(&cond_lock); 03443 ast_cond_destroy(&cond); 03444 pthread_attr_destroy(&attr); 03445 break; 03446 case AST_DIAL_RESULT_TRYING: 03447 case AST_DIAL_RESULT_RINGING: 03448 case AST_DIAL_RESULT_PROGRESS: 03449 case AST_DIAL_RESULT_PROCEEDING: 03450 break; 03451 } 03452 if (dial_res == AST_DIAL_RESULT_ANSWERED) { 03453 /* Queue up reprocessing ringing trunks, and then ringing stations again */ 03454 sla_queue_event(SLA_EVENT_RINGING_TRUNK); 03455 sla_queue_event(SLA_EVENT_DIAL_STATE); 03456 break; 03457 } 03458 } 03459 AST_LIST_TRAVERSE_SAFE_END 03460 }
static void sla_handle_hold_event | ( | struct sla_event * | event | ) | [static] |
Definition at line 3708 of file app_meetme.c.
References AST_CAUSE_NORMAL, AST_CONTROL_HOLD, ast_device_state_changed(), ast_indicate(), ast_softhangup(), INACTIVE_TRUNK_REFS, sla_change_trunk_state(), SLA_TRUNK_STATE_ONHOLD, SLA_TRUNK_STATE_ONHOLD_BYME, sla_event::station, and sla_event::trunk_ref.
Referenced by sla_thread().
03709 { 03710 ast_atomic_fetchadd_int((int *) &event->trunk_ref->trunk->hold_stations, 1); 03711 event->trunk_ref->state = SLA_TRUNK_STATE_ONHOLD_BYME; 03712 ast_device_state_changed("SLA:%s_%s", 03713 event->station->name, event->trunk_ref->trunk->name); 03714 sla_change_trunk_state(event->trunk_ref->trunk, SLA_TRUNK_STATE_ONHOLD, 03715 INACTIVE_TRUNK_REFS, event->trunk_ref); 03716 03717 if (event->trunk_ref->trunk->active_stations == 1) { 03718 /* The station putting it on hold is the only one on the call, so start 03719 * Music on hold to the trunk. */ 03720 event->trunk_ref->trunk->on_hold = 1; 03721 ast_indicate(event->trunk_ref->trunk->chan, AST_CONTROL_HOLD); 03722 } 03723 03724 ast_softhangup(event->trunk_ref->chan, AST_CAUSE_NORMAL); 03725 event->trunk_ref->chan = NULL; 03726 }
static void sla_handle_ringing_trunk_event | ( | void | ) | [static] |
Definition at line 3698 of file app_meetme.c.
References ast_mutex_lock(), ast_mutex_unlock(), sla, sla_hangup_stations(), and sla_ring_stations().
Referenced by sla_thread().
03699 { 03700 ast_mutex_lock(&sla.lock); 03701 sla_ring_stations(); 03702 ast_mutex_unlock(&sla.lock); 03703 03704 /* Find stations that shouldn't be ringing anymore. */ 03705 sla_hangup_stations(); 03706 }
static void sla_hangup_stations | ( | void | ) | [static] |
Definition at line 3670 of file app_meetme.c.
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(), free, sla, sla_ringing_station::station, and sla_ringing_trunk::trunk.
Referenced by sla_handle_ringing_trunk_event().
03671 { 03672 struct sla_trunk_ref *trunk_ref; 03673 struct sla_ringing_station *ringing_station; 03674 03675 AST_LIST_TRAVERSE_SAFE_BEGIN(&sla.ringing_stations, ringing_station, entry) { 03676 AST_LIST_TRAVERSE(&ringing_station->station->trunks, trunk_ref, entry) { 03677 struct sla_ringing_trunk *ringing_trunk; 03678 ast_mutex_lock(&sla.lock); 03679 AST_LIST_TRAVERSE(&sla.ringing_trunks, ringing_trunk, entry) { 03680 if (trunk_ref->trunk == ringing_trunk->trunk) 03681 break; 03682 } 03683 ast_mutex_unlock(&sla.lock); 03684 if (ringing_trunk) 03685 break; 03686 } 03687 if (!trunk_ref) { 03688 AST_LIST_REMOVE_CURRENT(&sla.ringing_stations, entry); 03689 ast_dial_join(ringing_station->station->dial); 03690 ast_dial_destroy(ringing_station->station->dial); 03691 ringing_station->station->dial = NULL; 03692 free(ringing_station); 03693 } 03694 } 03695 AST_LIST_TRAVERSE_SAFE_END 03696 }
static const char* sla_hold_str | ( | unsigned int | hold_access | ) | [static] |
Definition at line 1034 of file app_meetme.c.
References SLA_HOLD_OPEN, and SLA_HOLD_PRIVATE.
Referenced by sla_show_stations(), and sla_show_trunks().
01035 { 01036 const char *hold = "Unknown"; 01037 01038 switch (hold_access) { 01039 case SLA_HOLD_OPEN: 01040 hold = "Open"; 01041 break; 01042 case SLA_HOLD_PRIVATE: 01043 hold = "Private"; 01044 default: 01045 break; 01046 } 01047 01048 return hold; 01049 }
static int sla_load_config | ( | void | ) | [static] |
Definition at line 4715 of file app_meetme.c.
References ast_category_browse(), ast_cond_init(), ast_config_destroy(), ast_config_load(), ast_log(), ast_mutex_init(), ast_pthread_create, ast_true(), ast_variable_retrieve(), LOG_WARNING, sla, sla_build_station(), sla_build_trunk(), SLA_CONFIG_FILE, sla_thread(), and type.
Referenced by load_config().
04716 { 04717 struct ast_config *cfg; 04718 const char *cat = NULL; 04719 int res = 0; 04720 const char *val; 04721 04722 ast_mutex_init(&sla.lock); 04723 ast_cond_init(&sla.cond, NULL); 04724 04725 if (!(cfg = ast_config_load(SLA_CONFIG_FILE))) 04726 return 0; /* Treat no config as normal */ 04727 04728 if ((val = ast_variable_retrieve(cfg, "general", "attemptcallerid"))) 04729 sla.attempt_callerid = ast_true(val); 04730 04731 while ((cat = ast_category_browse(cfg, cat)) && !res) { 04732 const char *type; 04733 if (!strcasecmp(cat, "general")) 04734 continue; 04735 if (!(type = ast_variable_retrieve(cfg, cat, "type"))) { 04736 ast_log(LOG_WARNING, "Invalid entry in %s defined with no type!\n", 04737 SLA_CONFIG_FILE); 04738 continue; 04739 } 04740 if (!strcasecmp(type, "trunk")) 04741 res = sla_build_trunk(cfg, cat); 04742 else if (!strcasecmp(type, "station")) 04743 res = sla_build_station(cfg, cat); 04744 else { 04745 ast_log(LOG_WARNING, "Entry in %s defined with invalid type '%s'!\n", 04746 SLA_CONFIG_FILE, type); 04747 } 04748 } 04749 04750 ast_config_destroy(cfg); 04751 04752 ast_pthread_create(&sla.thread, NULL, sla_thread, NULL); 04753 04754 return res; 04755 }
static int sla_process_timers | ( | struct timespec * | ts | ) | [static] |
Calculate the time until the next known event.
Definition at line 3886 of file app_meetme.c.
References ast_tvadd(), 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().
03887 { 03888 unsigned int timeout = UINT_MAX; 03889 struct timeval tv; 03890 unsigned int change_made = 0; 03891 03892 /* Check for ring timeouts on ringing trunks */ 03893 if (sla_calc_trunk_timeouts(&timeout)) 03894 change_made = 1; 03895 03896 /* Check for ring timeouts on ringing stations */ 03897 if (sla_calc_station_timeouts(&timeout)) 03898 change_made = 1; 03899 03900 /* Check for station ring delays */ 03901 if (sla_calc_station_delays(&timeout)) 03902 change_made = 1; 03903 03904 /* queue reprocessing of ringing trunks */ 03905 if (change_made) 03906 sla_queue_event_nolock(SLA_EVENT_RINGING_TRUNK); 03907 03908 /* No timeout */ 03909 if (timeout == UINT_MAX) 03910 return 0; 03911 03912 if (ts) { 03913 tv = ast_tvadd(ast_tvnow(), ast_samp2tv(timeout, 1000)); 03914 ts->tv_sec = tv.tv_sec; 03915 ts->tv_nsec = tv.tv_usec * 1000; 03916 } 03917 03918 return 1; 03919 }
static void sla_queue_event | ( | enum sla_event_type | type | ) | [static] |
Definition at line 1304 of file app_meetme.c.
References sla_queue_event_full().
Referenced by queue_ringing_trunk(), sla_dial_state_callback(), sla_handle_dial_state_event(), and sla_trunk_exec().
01305 { 01306 sla_queue_event_full(type, NULL, NULL, 1); 01307 }
static void sla_queue_event_conf | ( | enum sla_event_type | type, | |
struct ast_channel * | chan, | |||
struct ast_conference * | conf | |||
) | [static] |
Queue a SLA event from the conference.
Definition at line 1310 of file app_meetme.c.
References AST_LIST_TRAVERSE, ast_log(), AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_strdupa, ast_strlen_zero(), ast_conference::confno, LOG_DEBUG, LOG_ERROR, sla_queue_event_full(), and strsep().
Referenced by conf_run().
01312 { 01313 struct sla_station *station; 01314 struct sla_trunk_ref *trunk_ref = NULL; 01315 char *trunk_name; 01316 01317 trunk_name = ast_strdupa(conf->confno); 01318 strsep(&trunk_name, "_"); 01319 if (ast_strlen_zero(trunk_name)) { 01320 ast_log(LOG_ERROR, "Invalid conference name for SLA - '%s'!\n", conf->confno); 01321 return; 01322 } 01323 01324 AST_RWLIST_RDLOCK(&sla_stations); 01325 AST_RWLIST_TRAVERSE(&sla_stations, station, entry) { 01326 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) { 01327 if (trunk_ref->chan == chan && !strcmp(trunk_ref->trunk->name, trunk_name)) 01328 break; 01329 } 01330 if (trunk_ref) 01331 break; 01332 } 01333 AST_RWLIST_UNLOCK(&sla_stations); 01334 01335 if (!trunk_ref) { 01336 ast_log(LOG_DEBUG, "Trunk not found for event!\n"); 01337 return; 01338 } 01339 01340 sla_queue_event_full(type, trunk_ref, station, 1); 01341 }
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 1276 of file app_meetme.c.
References ast_calloc, ast_cond_signal(), AST_LIST_INSERT_TAIL, ast_mutex_lock(), ast_mutex_unlock(), event, and sla.
Referenced by sla_queue_event(), sla_queue_event_conf(), and sla_queue_event_nolock().
01278 { 01279 struct sla_event *event; 01280 01281 if (!(event = ast_calloc(1, sizeof(*event)))) 01282 return; 01283 01284 event->type = type; 01285 event->trunk_ref = trunk_ref; 01286 event->station = station; 01287 01288 if (!lock) { 01289 AST_LIST_INSERT_TAIL(&sla.event_q, event, entry); 01290 return; 01291 } 01292 01293 ast_mutex_lock(&sla.lock); 01294 AST_LIST_INSERT_TAIL(&sla.event_q, event, entry); 01295 ast_cond_signal(&sla.cond); 01296 ast_mutex_unlock(&sla.lock); 01297 }
static void sla_queue_event_nolock | ( | enum sla_event_type | type | ) | [static] |
Definition at line 1299 of file app_meetme.c.
References sla_queue_event_full().
Referenced by sla_process_timers().
01300 { 01301 sla_queue_event_full(type, NULL, NULL, 0); 01302 }
static int sla_ring_station | ( | struct sla_ringing_trunk * | ringing_trunk, | |
struct sla_station * | station | |||
) | [static] |
Ring a station.
Definition at line 3503 of file app_meetme.c.
References ast_calloc, 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_strdup, ast_strdupa, ast_strlen_zero(), cid_name, cid_num, free, sla_failed_station::last_try, sla, sla_create_ringing_station(), sla_dial_state_callback(), sla_failed_station::station, strsep(), and sla_ringing_trunk::trunk.
Referenced by sla_ring_stations().
03504 { 03505 char *tech, *tech_data; 03506 struct ast_dial *dial; 03507 struct sla_ringing_station *ringing_station; 03508 const char *cid_name = NULL, *cid_num = NULL; 03509 enum ast_dial_result res; 03510 03511 if (!(dial = ast_dial_create())) 03512 return -1; 03513 03514 ast_dial_set_state_callback(dial, sla_dial_state_callback); 03515 tech_data = ast_strdupa(station->device); 03516 tech = strsep(&tech_data, "/"); 03517 03518 if (ast_dial_append(dial, tech, tech_data) == -1) { 03519 ast_dial_destroy(dial); 03520 return -1; 03521 } 03522 03523 if (!sla.attempt_callerid && !ast_strlen_zero(ringing_trunk->trunk->chan->cid.cid_name)) { 03524 cid_name = ast_strdupa(ringing_trunk->trunk->chan->cid.cid_name); 03525 free(ringing_trunk->trunk->chan->cid.cid_name); 03526 ringing_trunk->trunk->chan->cid.cid_name = NULL; 03527 } 03528 if (!sla.attempt_callerid && !ast_strlen_zero(ringing_trunk->trunk->chan->cid.cid_num)) { 03529 cid_num = ast_strdupa(ringing_trunk->trunk->chan->cid.cid_num); 03530 free(ringing_trunk->trunk->chan->cid.cid_num); 03531 ringing_trunk->trunk->chan->cid.cid_num = NULL; 03532 } 03533 03534 res = ast_dial_run(dial, ringing_trunk->trunk->chan, 1); 03535 03536 if (cid_name) 03537 ringing_trunk->trunk->chan->cid.cid_name = ast_strdup(cid_name); 03538 if (cid_num) 03539 ringing_trunk->trunk->chan->cid.cid_num = ast_strdup(cid_num); 03540 03541 if (res != AST_DIAL_RESULT_TRYING) { 03542 struct sla_failed_station *failed_station; 03543 ast_dial_destroy(dial); 03544 if (!(failed_station = ast_calloc(1, sizeof(*failed_station)))) 03545 return -1; 03546 failed_station->station = station; 03547 failed_station->last_try = ast_tvnow(); 03548 AST_LIST_INSERT_HEAD(&sla.failed_stations, failed_station, entry); 03549 return -1; 03550 } 03551 if (!(ringing_station = sla_create_ringing_station(station))) { 03552 ast_dial_join(dial); 03553 ast_dial_destroy(dial); 03554 return -1; 03555 } 03556 03557 station->dial = dial; 03558 03559 AST_LIST_INSERT_HEAD(&sla.ringing_stations, ringing_station, entry); 03560 03561 return 0; 03562 }
static void sla_ring_stations | ( | void | ) | [static] |
Ring stations based on current set of ringing trunks.
Definition at line 3629 of file app_meetme.c.
References AST_LIST_TRAVERSE, 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(), and sla_ringing_trunk::trunk.
Referenced by sla_handle_ringing_trunk_event().
03630 { 03631 struct sla_station_ref *station_ref; 03632 struct sla_ringing_trunk *ringing_trunk; 03633 03634 /* Make sure that every station that uses at least one of the ringing 03635 * trunks, is ringing. */ 03636 AST_LIST_TRAVERSE(&sla.ringing_trunks, ringing_trunk, entry) { 03637 AST_LIST_TRAVERSE(&ringing_trunk->trunk->stations, station_ref, entry) { 03638 int time_left; 03639 03640 /* Is this station already ringing? */ 03641 if (sla_check_ringing_station(station_ref->station)) 03642 continue; 03643 03644 /* Is this station already in a call? */ 03645 if (sla_check_inuse_station(station_ref->station)) 03646 continue; 03647 03648 /* Did we fail to dial this station earlier? If so, has it been 03649 * a minute since we tried? */ 03650 if (sla_check_failed_station(station_ref->station)) 03651 continue; 03652 03653 /* If this station already timed out while this trunk was ringing, 03654 * do not dial it again for this ringing trunk. */ 03655 if (sla_check_timed_out_station(ringing_trunk, station_ref->station)) 03656 continue; 03657 03658 /* Check for a ring delay in progress */ 03659 time_left = sla_check_station_delay(station_ref->station, ringing_trunk); 03660 if (time_left != INT_MAX && time_left > 0) 03661 continue; 03662 03663 /* It is time to make this station begin to ring. Do it! */ 03664 sla_ring_station(ringing_trunk, station_ref->station); 03665 } 03666 } 03667 /* Now, all of the stations that should be ringing, are ringing. */ 03668 }
static int sla_show_stations | ( | int | fd, | |
int | argc, | |||
char ** | argv | |||
) | [static] |
Definition at line 1111 of file app_meetme.c.
References ast_cli(), AST_LIST_TRAVERSE, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, RESULT_SUCCESS, S_OR, sla_hold_str(), and trunkstate2str().
01112 { 01113 const struct sla_station *station; 01114 01115 ast_cli(fd, "\n" 01116 "=============================================================\n" 01117 "=== Configured SLA Stations =================================\n" 01118 "=============================================================\n" 01119 "===\n"); 01120 AST_RWLIST_RDLOCK(&sla_stations); 01121 AST_RWLIST_TRAVERSE(&sla_stations, station, entry) { 01122 struct sla_trunk_ref *trunk_ref; 01123 char ring_timeout[16] = "(none)"; 01124 char ring_delay[16] = "(none)"; 01125 if (station->ring_timeout) { 01126 snprintf(ring_timeout, sizeof(ring_timeout), 01127 "%u", station->ring_timeout); 01128 } 01129 if (station->ring_delay) { 01130 snprintf(ring_delay, sizeof(ring_delay), 01131 "%u", station->ring_delay); 01132 } 01133 ast_cli(fd, "=== ---------------------------------------------------------\n" 01134 "=== Station Name: %s\n" 01135 "=== ==> Device: %s\n" 01136 "=== ==> AutoContext: %s\n" 01137 "=== ==> RingTimeout: %s\n" 01138 "=== ==> RingDelay: %s\n" 01139 "=== ==> HoldAccess: %s\n" 01140 "=== ==> Trunks ...\n", 01141 station->name, station->device, 01142 S_OR(station->autocontext, "(none)"), 01143 ring_timeout, ring_delay, 01144 sla_hold_str(station->hold_access)); 01145 AST_RWLIST_RDLOCK(&sla_trunks); 01146 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) { 01147 if (trunk_ref->ring_timeout) { 01148 snprintf(ring_timeout, sizeof(ring_timeout), 01149 "%u", trunk_ref->ring_timeout); 01150 } else 01151 strcpy(ring_timeout, "(none)"); 01152 if (trunk_ref->ring_delay) { 01153 snprintf(ring_delay, sizeof(ring_delay), 01154 "%u", trunk_ref->ring_delay); 01155 } else 01156 strcpy(ring_delay, "(none)"); 01157 ast_cli(fd, "=== ==> Trunk Name: %s\n" 01158 "=== ==> State: %s\n" 01159 "=== ==> RingTimeout: %s\n" 01160 "=== ==> RingDelay: %s\n", 01161 trunk_ref->trunk->name, 01162 trunkstate2str(trunk_ref->state), 01163 ring_timeout, ring_delay); 01164 } 01165 AST_RWLIST_UNLOCK(&sla_trunks); 01166 ast_cli(fd, "=== ---------------------------------------------------------\n" 01167 "===\n"); 01168 } 01169 AST_RWLIST_UNLOCK(&sla_stations); 01170 ast_cli(fd, "============================================================\n" 01171 "\n"); 01172 01173 return RESULT_SUCCESS; 01174 }
static int sla_show_trunks | ( | int | fd, | |
int | argc, | |||
char ** | argv | |||
) | [static] |
Definition at line 1051 of file app_meetme.c.
References ast_cli(), AST_LIST_TRAVERSE, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, RESULT_SUCCESS, S_OR, and sla_hold_str().
01052 { 01053 const struct sla_trunk *trunk; 01054 01055 ast_cli(fd, "\n" 01056 "=============================================================\n" 01057 "=== Configured SLA Trunks ===================================\n" 01058 "=============================================================\n" 01059 "===\n"); 01060 AST_RWLIST_RDLOCK(&sla_trunks); 01061 AST_RWLIST_TRAVERSE(&sla_trunks, trunk, entry) { 01062 struct sla_station_ref *station_ref; 01063 char ring_timeout[16] = "(none)"; 01064 if (trunk->ring_timeout) 01065 snprintf(ring_timeout, sizeof(ring_timeout), "%u Seconds", trunk->ring_timeout); 01066 ast_cli(fd, "=== ---------------------------------------------------------\n" 01067 "=== Trunk Name: %s\n" 01068 "=== ==> Device: %s\n" 01069 "=== ==> AutoContext: %s\n" 01070 "=== ==> RingTimeout: %s\n" 01071 "=== ==> BargeAllowed: %s\n" 01072 "=== ==> HoldAccess: %s\n" 01073 "=== ==> Stations ...\n", 01074 trunk->name, trunk->device, 01075 S_OR(trunk->autocontext, "(none)"), 01076 ring_timeout, 01077 trunk->barge_disabled ? "No" : "Yes", 01078 sla_hold_str(trunk->hold_access)); 01079 AST_RWLIST_RDLOCK(&sla_stations); 01080 AST_LIST_TRAVERSE(&trunk->stations, station_ref, entry) 01081 ast_cli(fd, "=== ==> Station name: %s\n", station_ref->station->name); 01082 AST_RWLIST_UNLOCK(&sla_stations); 01083 ast_cli(fd, "=== ---------------------------------------------------------\n" 01084 "===\n"); 01085 } 01086 AST_RWLIST_UNLOCK(&sla_trunks); 01087 ast_cli(fd, "=============================================================\n" 01088 "\n"); 01089 01090 return RESULT_SUCCESS; 01091 }
static int sla_state | ( | const char * | data | ) | [static] |
Definition at line 4342 of file app_meetme.c.
References AST_DEVICE_INUSE, AST_DEVICE_INVALID, AST_DEVICE_NOT_INUSE, AST_DEVICE_ONHOLD, AST_DEVICE_RINGING, AST_LIST_TRAVERSE, ast_log(), AST_RWLIST_RDLOCK, AST_RWLIST_UNLOCK, ast_strdupa, LOG_ERROR, SLA_TRUNK_STATE_IDLE, SLA_TRUNK_STATE_ONHOLD, SLA_TRUNK_STATE_ONHOLD_BYME, SLA_TRUNK_STATE_RINGING, SLA_TRUNK_STATE_UP, and strsep().
Referenced by load_module().
04343 { 04344 char *buf, *station_name, *trunk_name; 04345 struct sla_station *station; 04346 struct sla_trunk_ref *trunk_ref; 04347 int res = AST_DEVICE_INVALID; 04348 04349 trunk_name = buf = ast_strdupa(data); 04350 station_name = strsep(&trunk_name, "_"); 04351 04352 AST_RWLIST_RDLOCK(&sla_stations); 04353 AST_LIST_TRAVERSE(&sla_stations, station, entry) { 04354 if (strcasecmp(station_name, station->name)) 04355 continue; 04356 AST_RWLIST_RDLOCK(&sla_trunks); 04357 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) { 04358 if (!strcasecmp(trunk_name, trunk_ref->trunk->name)) 04359 break; 04360 } 04361 if (!trunk_ref) { 04362 AST_RWLIST_UNLOCK(&sla_trunks); 04363 break; 04364 } 04365 switch (trunk_ref->state) { 04366 case SLA_TRUNK_STATE_IDLE: 04367 res = AST_DEVICE_NOT_INUSE; 04368 break; 04369 case SLA_TRUNK_STATE_RINGING: 04370 res = AST_DEVICE_RINGING; 04371 break; 04372 case SLA_TRUNK_STATE_UP: 04373 res = AST_DEVICE_INUSE; 04374 break; 04375 case SLA_TRUNK_STATE_ONHOLD: 04376 case SLA_TRUNK_STATE_ONHOLD_BYME: 04377 res = AST_DEVICE_ONHOLD; 04378 break; 04379 } 04380 AST_RWLIST_UNLOCK(&sla_trunks); 04381 } 04382 AST_RWLIST_UNLOCK(&sla_stations); 04383 04384 if (res == AST_DEVICE_INVALID) { 04385 ast_log(LOG_ERROR, "Could not determine state for trunk %s on station %s!\n", 04386 trunk_name, station_name); 04387 } 04388 04389 return res; 04390 }
static int sla_station_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Definition at line 4108 of file app_meetme.c.
References admin_exec(), ALL_TRUNK_REFS, ast_answer(), ast_autoservice_start(), ast_autoservice_stop(), ast_cond_destroy(), ast_cond_init(), ast_cond_wait(), AST_CONTROL_UNHOLD, ast_device_state_changed(), ast_indicate(), ast_log(), ast_mutex_destroy(), ast_mutex_init(), ast_mutex_lock(), ast_mutex_unlock(), ast_pthread_create_background, AST_RWLIST_RDLOCK, AST_RWLIST_UNLOCK, ast_set_flag, ast_strdupa, ast_strlen_zero(), ast_conference::attr, build_conf(), conf_run(), CONFFLAG_MARKEDEXIT, CONFFLAG_PASS_DTMF, CONFFLAG_QUIET, CONFFLAG_SLA_STATION, dial_trunk(), dispose_conf(), ast_flags::flags, LOG_DEBUG, LOG_NOTICE, LOG_WARNING, MAX_CONFNUM, pbx_builtin_setvar_helper(), sla_change_trunk_state(), sla_choose_idle_trunk(), sla_find_station(), sla_find_trunk_ref_byname(), SLA_TRUNK_STATE_IDLE, SLA_TRUNK_STATE_ONHOLD_BYME, SLA_TRUNK_STATE_UP, strsep(), and dial_trunk_args::trunk_ref.
Referenced by load_module().
04109 { 04110 char *station_name, *trunk_name; 04111 struct sla_station *station; 04112 struct sla_trunk_ref *trunk_ref = NULL; 04113 char conf_name[MAX_CONFNUM]; 04114 struct ast_flags conf_flags = { 0 }; 04115 struct ast_conference *conf; 04116 04117 if (ast_strlen_zero(data)) { 04118 ast_log(LOG_WARNING, "Invalid Arguments to SLAStation!\n"); 04119 pbx_builtin_setvar_helper(chan, "SLASTATION_STATUS", "FAILURE"); 04120 return 0; 04121 } 04122 04123 trunk_name = ast_strdupa(data); 04124 station_name = strsep(&trunk_name, "_"); 04125 04126 if (ast_strlen_zero(station_name)) { 04127 ast_log(LOG_WARNING, "Invalid Arguments to SLAStation!\n"); 04128 pbx_builtin_setvar_helper(chan, "SLASTATION_STATUS", "FAILURE"); 04129 return 0; 04130 } 04131 04132 AST_RWLIST_RDLOCK(&sla_stations); 04133 station = sla_find_station(station_name); 04134 AST_RWLIST_UNLOCK(&sla_stations); 04135 04136 if (!station) { 04137 ast_log(LOG_WARNING, "Station '%s' not found!\n", station_name); 04138 pbx_builtin_setvar_helper(chan, "SLASTATION_STATUS", "FAILURE"); 04139 return 0; 04140 } 04141 04142 AST_RWLIST_RDLOCK(&sla_trunks); 04143 if (!ast_strlen_zero(trunk_name)) { 04144 trunk_ref = sla_find_trunk_ref_byname(station, trunk_name); 04145 } else 04146 trunk_ref = sla_choose_idle_trunk(station); 04147 AST_RWLIST_UNLOCK(&sla_trunks); 04148 04149 if (!trunk_ref) { 04150 if (ast_strlen_zero(trunk_name)) 04151 ast_log(LOG_NOTICE, "No trunks available for call.\n"); 04152 else { 04153 ast_log(LOG_NOTICE, "Can't join existing call on trunk " 04154 "'%s' due to access controls.\n", trunk_name); 04155 } 04156 pbx_builtin_setvar_helper(chan, "SLASTATION_STATUS", "CONGESTION"); 04157 return 0; 04158 } 04159 04160 if (trunk_ref->state == SLA_TRUNK_STATE_ONHOLD_BYME) { 04161 if (ast_atomic_dec_and_test((int *) &trunk_ref->trunk->hold_stations) == 1) 04162 sla_change_trunk_state(trunk_ref->trunk, SLA_TRUNK_STATE_UP, ALL_TRUNK_REFS, NULL); 04163 else { 04164 trunk_ref->state = SLA_TRUNK_STATE_UP; 04165 ast_device_state_changed("SLA:%s_%s", station->name, trunk_ref->trunk->name); 04166 } 04167 } 04168 04169 trunk_ref->chan = chan; 04170 04171 if (!trunk_ref->trunk->chan) { 04172 ast_mutex_t cond_lock; 04173 ast_cond_t cond; 04174 pthread_t dont_care; 04175 pthread_attr_t attr; 04176 struct dial_trunk_args args = { 04177 .trunk_ref = trunk_ref, 04178 .station = station, 04179 .cond_lock = &cond_lock, 04180 .cond = &cond, 04181 }; 04182 sla_change_trunk_state(trunk_ref->trunk, SLA_TRUNK_STATE_UP, ALL_TRUNK_REFS, NULL); 04183 /* Create a thread to dial the trunk and dump it into the conference. 04184 * However, we want to wait until the trunk has been dialed and the 04185 * conference is created before continuing on here. */ 04186 ast_autoservice_start(chan); 04187 ast_mutex_init(&cond_lock); 04188 ast_cond_init(&cond, NULL); 04189 pthread_attr_init(&attr); 04190 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 04191 ast_mutex_lock(&cond_lock); 04192 ast_pthread_create_background(&dont_care, &attr, dial_trunk, &args); 04193 ast_cond_wait(&cond, &cond_lock); 04194 ast_mutex_unlock(&cond_lock); 04195 ast_mutex_destroy(&cond_lock); 04196 ast_cond_destroy(&cond); 04197 pthread_attr_destroy(&attr); 04198 ast_autoservice_stop(chan); 04199 if (!trunk_ref->trunk->chan) { 04200 ast_log(LOG_DEBUG, "Trunk didn't get created. chan: %lx\n", (long) trunk_ref->trunk->chan); 04201 pbx_builtin_setvar_helper(chan, "SLASTATION_STATUS", "CONGESTION"); 04202 sla_change_trunk_state(trunk_ref->trunk, SLA_TRUNK_STATE_IDLE, ALL_TRUNK_REFS, NULL); 04203 trunk_ref->chan = NULL; 04204 return 0; 04205 } 04206 } 04207 04208 if (ast_atomic_fetchadd_int((int *) &trunk_ref->trunk->active_stations, 1) == 0 && 04209 trunk_ref->trunk->on_hold) { 04210 trunk_ref->trunk->on_hold = 0; 04211 ast_indicate(trunk_ref->trunk->chan, AST_CONTROL_UNHOLD); 04212 sla_change_trunk_state(trunk_ref->trunk, SLA_TRUNK_STATE_UP, ALL_TRUNK_REFS, NULL); 04213 } 04214 04215 snprintf(conf_name, sizeof(conf_name), "SLA_%s", trunk_ref->trunk->name); 04216 ast_set_flag(&conf_flags, 04217 CONFFLAG_QUIET | CONFFLAG_MARKEDEXIT | CONFFLAG_PASS_DTMF | CONFFLAG_SLA_STATION); 04218 ast_answer(chan); 04219 conf = build_conf(conf_name, "", "", 0, 0, 1); 04220 if (conf) { 04221 conf_run(chan, conf, conf_flags.flags, NULL); 04222 dispose_conf(conf); 04223 conf = NULL; 04224 } 04225 trunk_ref->chan = NULL; 04226 if (ast_atomic_dec_and_test((int *) &trunk_ref->trunk->active_stations) && 04227 trunk_ref->state != SLA_TRUNK_STATE_ONHOLD_BYME) { 04228 strncat(conf_name, "|K", sizeof(conf_name) - strlen(conf_name) - 1); 04229 admin_exec(NULL, conf_name); 04230 trunk_ref->trunk->hold_stations = 0; 04231 sla_change_trunk_state(trunk_ref->trunk, SLA_TRUNK_STATE_IDLE, ALL_TRUNK_REFS, NULL); 04232 } 04233 04234 pbx_builtin_setvar_helper(chan, "SLASTATION_STATUS", "SUCCESS"); 04235 04236 return 0; 04237 }
static void sla_stop_ringing_station | ( | struct sla_ringing_station * | ringing_station, | |
enum sla_station_hangup | hangup | |||
) | [static] |
Definition at line 3288 of file app_meetme.c.
References ast_dial_destroy(), ast_dial_join(), AST_LIST_INSERT_TAIL, AST_LIST_TRAVERSE, free, sla, sla_create_station_ref(), SLA_STATION_HANGUP_NORMAL, sla_ringing_station::station, and sla_ringing_trunk::trunk.
Referenced by sla_calc_station_timeouts(), and sla_handle_dial_state_event().
03290 { 03291 struct sla_ringing_trunk *ringing_trunk; 03292 struct sla_trunk_ref *trunk_ref; 03293 struct sla_station_ref *station_ref; 03294 03295 ast_dial_join(ringing_station->station->dial); 03296 ast_dial_destroy(ringing_station->station->dial); 03297 ringing_station->station->dial = NULL; 03298 03299 if (hangup == SLA_STATION_HANGUP_NORMAL) 03300 goto done; 03301 03302 /* If the station is being hung up because of a timeout, then add it to the 03303 * list of timed out stations on each of the ringing trunks. This is so 03304 * that when doing further processing to figure out which stations should be 03305 * ringing, which trunk to answer, determining timeouts, etc., we know which 03306 * ringing trunks we should ignore. */ 03307 AST_LIST_TRAVERSE(&sla.ringing_trunks, ringing_trunk, entry) { 03308 AST_LIST_TRAVERSE(&ringing_station->station->trunks, trunk_ref, entry) { 03309 if (ringing_trunk->trunk == trunk_ref->trunk) 03310 break; 03311 } 03312 if (!trunk_ref) 03313 continue; 03314 if (!(station_ref = sla_create_station_ref(ringing_station->station))) 03315 continue; 03316 AST_LIST_INSERT_TAIL(&ringing_trunk->timed_out_stations, station_ref, entry); 03317 } 03318 03319 done: 03320 free(ringing_station); 03321 }
static void sla_stop_ringing_trunk | ( | struct sla_ringing_trunk * | ringing_trunk | ) | [static] |
Definition at line 3273 of file app_meetme.c.
References admin_exec(), ALL_TRUNK_REFS, AST_LIST_REMOVE_HEAD, free, sla_change_trunk_state(), SLA_TRUNK_STATE_IDLE, and sla_ringing_trunk::trunk.
Referenced by sla_calc_trunk_timeouts().
03274 { 03275 char buf[80]; 03276 struct sla_station_ref *station_ref; 03277 03278 snprintf(buf, sizeof(buf), "SLA_%s|K", ringing_trunk->trunk->name); 03279 admin_exec(NULL, buf); 03280 sla_change_trunk_state(ringing_trunk->trunk, SLA_TRUNK_STATE_IDLE, ALL_TRUNK_REFS, NULL); 03281 03282 while ((station_ref = AST_LIST_REMOVE_HEAD(&ringing_trunk->timed_out_stations, entry))) 03283 free(station_ref); 03284 03285 free(ringing_trunk); 03286 }
static void* sla_thread | ( | void * | data | ) | [static] |
Definition at line 3921 of file app_meetme.c.
References ast_cond_timedwait(), ast_cond_wait(), AST_LIST_EMPTY, AST_LIST_REMOVE_HEAD, ast_mutex_lock(), ast_mutex_unlock(), event, free, sla, SLA_EVENT_DIAL_STATE, SLA_EVENT_HOLD, SLA_EVENT_RINGING_TRUNK, sla_handle_dial_state_event(), sla_handle_hold_event(), sla_handle_ringing_trunk_event(), sla_process_timers(), and sla_event::type.
Referenced by sla_load_config().
03922 { 03923 struct sla_failed_station *failed_station; 03924 struct sla_ringing_station *ringing_station; 03925 03926 ast_mutex_lock(&sla.lock); 03927 03928 while (!sla.stop) { 03929 struct sla_event *event; 03930 struct timespec ts = { 0, }; 03931 unsigned int have_timeout = 0; 03932 03933 if (AST_LIST_EMPTY(&sla.event_q)) { 03934 if ((have_timeout = sla_process_timers(&ts))) 03935 ast_cond_timedwait(&sla.cond, &sla.lock, &ts); 03936 else 03937 ast_cond_wait(&sla.cond, &sla.lock); 03938 if (sla.stop) 03939 break; 03940 } 03941 03942 if (have_timeout) 03943 sla_process_timers(NULL); 03944 03945 while ((event = AST_LIST_REMOVE_HEAD(&sla.event_q, entry))) { 03946 ast_mutex_unlock(&sla.lock); 03947 switch (event->type) { 03948 case SLA_EVENT_HOLD: 03949 sla_handle_hold_event(event); 03950 break; 03951 case SLA_EVENT_DIAL_STATE: 03952 sla_handle_dial_state_event(); 03953 break; 03954 case SLA_EVENT_RINGING_TRUNK: 03955 sla_handle_ringing_trunk_event(); 03956 break; 03957 } 03958 free(event); 03959 ast_mutex_lock(&sla.lock); 03960 } 03961 } 03962 03963 ast_mutex_unlock(&sla.lock); 03964 03965 while ((ringing_station = AST_LIST_REMOVE_HEAD(&sla.ringing_stations, entry))) 03966 free(ringing_station); 03967 03968 while ((failed_station = AST_LIST_REMOVE_HEAD(&sla.failed_stations, entry))) 03969 free(failed_station); 03970 03971 return NULL; 03972 }
static int sla_trunk_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Definition at line 4272 of file app_meetme.c.
References ALL_TRUNK_REFS, AST_CONTROL_RINGING, 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_RWLIST_RDLOCK, AST_RWLIST_UNLOCK, ast_set_flag, build_conf(), conf_run(), CONFFLAG_MARKEDEXIT, CONFFLAG_MARKEDUSER, CONFFLAG_PASS_DTMF, CONFFLAG_QUIET, dispose_conf(), ast_flags::flags, free, LOG_ERROR, MAX_CONFNUM, pbx_builtin_getvar_helper(), pbx_builtin_setvar_helper(), queue_ringing_trunk(), sla, sla_change_trunk_state(), SLA_EVENT_RINGING_TRUNK, sla_find_trunk(), sla_queue_event(), SLA_TRUNK_STATE_IDLE, and sla_ringing_trunk::trunk.
Referenced by load_module().
04273 { 04274 const char *trunk_name = data; 04275 char conf_name[MAX_CONFNUM]; 04276 struct ast_conference *conf; 04277 struct ast_flags conf_flags = { 0 }; 04278 struct sla_trunk *trunk; 04279 struct sla_ringing_trunk *ringing_trunk; 04280 04281 AST_RWLIST_RDLOCK(&sla_trunks); 04282 trunk = sla_find_trunk(trunk_name); 04283 AST_RWLIST_UNLOCK(&sla_trunks); 04284 if (!trunk) { 04285 ast_log(LOG_ERROR, "SLA Trunk '%s' not found!\n", trunk_name); 04286 pbx_builtin_setvar_helper(chan, "SLATRUNK_STATUS", "FAILURE"); 04287 return 0; 04288 } 04289 if (trunk->chan) { 04290 ast_log(LOG_ERROR, "Call came in on %s, but the trunk is already in use!\n", 04291 trunk_name); 04292 pbx_builtin_setvar_helper(chan, "SLATRUNK_STATUS", "FAILURE"); 04293 return 0; 04294 } 04295 trunk->chan = chan; 04296 04297 if (!(ringing_trunk = queue_ringing_trunk(trunk))) { 04298 pbx_builtin_setvar_helper(chan, "SLATRUNK_STATUS", "FAILURE"); 04299 return 0; 04300 } 04301 04302 snprintf(conf_name, sizeof(conf_name), "SLA_%s", trunk_name); 04303 conf = build_conf(conf_name, "", "", 1, 1, 1); 04304 if (!conf) { 04305 pbx_builtin_setvar_helper(chan, "SLATRUNK_STATUS", "FAILURE"); 04306 return 0; 04307 } 04308 ast_set_flag(&conf_flags, 04309 CONFFLAG_QUIET | CONFFLAG_MARKEDEXIT | CONFFLAG_MARKEDUSER | CONFFLAG_PASS_DTMF); 04310 ast_indicate(chan, AST_CONTROL_RINGING); 04311 conf_run(chan, conf, conf_flags.flags, NULL); 04312 dispose_conf(conf); 04313 conf = NULL; 04314 trunk->chan = NULL; 04315 trunk->on_hold = 0; 04316 04317 if (!pbx_builtin_getvar_helper(chan, "SLATRUNK_STATUS")) 04318 pbx_builtin_setvar_helper(chan, "SLATRUNK_STATUS", "SUCCESS"); 04319 04320 /* Remove the entry from the list of ringing trunks if it is still there. */ 04321 ast_mutex_lock(&sla.lock); 04322 AST_LIST_TRAVERSE_SAFE_BEGIN(&sla.ringing_trunks, ringing_trunk, entry) { 04323 if (ringing_trunk->trunk == trunk) { 04324 AST_LIST_REMOVE_CURRENT(&sla.ringing_trunks, entry); 04325 break; 04326 } 04327 } 04328 AST_LIST_TRAVERSE_SAFE_END 04329 ast_mutex_unlock(&sla.lock); 04330 if (ringing_trunk) { 04331 sla_change_trunk_state(ringing_trunk->trunk, SLA_TRUNK_STATE_IDLE, ALL_TRUNK_REFS, NULL); 04332 free(ringing_trunk); 04333 pbx_builtin_setvar_helper(chan, "SLATRUNK_STATUS", "UNANSWERED"); 04334 /* Queue reprocessing of ringing trunks to make stations stop ringing 04335 * that shouldn't be ringing after this trunk stopped. */ 04336 sla_queue_event(SLA_EVENT_RINGING_TRUNK); 04337 } 04338 04339 return 0; 04340 }
static const char* trunkstate2str | ( | enum sla_trunk_state | state | ) | [static] |
Definition at line 1093 of file app_meetme.c.
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().
01094 { 01095 #define S(e) case e: return # e; 01096 switch (state) { 01097 S(SLA_TRUNK_STATE_IDLE) 01098 S(SLA_TRUNK_STATE_RINGING) 01099 S(SLA_TRUNK_STATE_UP) 01100 S(SLA_TRUNK_STATE_ONHOLD) 01101 S(SLA_TRUNK_STATE_ONHOLD_BYME) 01102 } 01103 return "Uknown State"; 01104 #undef S 01105 }
static void tweak_listen_volume | ( | struct ast_conf_user * | user, | |
enum volume_action | action | |||
) | [static] |
Definition at line 672 of file app_meetme.c.
References volume::actual, volume::desired, ast_conf_user::listen, set_listen_volume(), and tweak_volume().
Referenced by admin_exec(), and conf_run().
00673 { 00674 tweak_volume(&user->listen, action); 00675 /* attempt to make the adjustment in the channel driver; 00676 if successful, don't adjust in the frame reading routine 00677 */ 00678 if (!set_listen_volume(user, user->listen.desired)) 00679 user->listen.actual = 0; 00680 else 00681 user->listen.actual = user->listen.desired; 00682 }
static void tweak_talk_volume | ( | struct ast_conf_user * | user, | |
enum volume_action | action | |||
) | [static] |
Definition at line 660 of file app_meetme.c.
References volume::actual, volume::desired, set_talk_volume(), ast_conf_user::talk, and tweak_volume().
Referenced by admin_exec(), and conf_run().
00661 { 00662 tweak_volume(&user->talk, action); 00663 /* attempt to make the adjustment in the channel driver; 00664 if successful, don't adjust in the frame reading routine 00665 */ 00666 if (!set_talk_volume(user, user->talk.desired)) 00667 user->talk.actual = 0; 00668 else 00669 user->talk.actual = user->talk.desired; 00670 }
static void tweak_volume | ( | struct volume * | vol, | |
enum volume_action | action | |||
) | [static] |
Definition at line 625 of file app_meetme.c.
References volume::desired, VOL_DOWN, and VOL_UP.
Referenced by tweak_listen_volume(), and tweak_talk_volume().
00626 { 00627 switch (action) { 00628 case VOL_UP: 00629 switch (vol->desired) { 00630 case 5: 00631 break; 00632 case 0: 00633 vol->desired = 2; 00634 break; 00635 case -2: 00636 vol->desired = 0; 00637 break; 00638 default: 00639 vol->desired++; 00640 break; 00641 } 00642 break; 00643 case VOL_DOWN: 00644 switch (vol->desired) { 00645 case -5: 00646 break; 00647 case 2: 00648 vol->desired = 0; 00649 break; 00650 case 0: 00651 vol->desired = -2; 00652 break; 00653 default: 00654 vol->desired--; 00655 break; 00656 } 00657 } 00658 }
static int unload_module | ( | void | ) | [static] |
Definition at line 4768 of file app_meetme.c.
References ARRAY_LEN, ast_cli_unregister_multiple(), ast_devstate_prov_del(), ast_manager_unregister(), ast_module_user_hangup_all, ast_unregister_application(), and sla_destroy().
04769 { 04770 int res = 0; 04771 04772 ast_cli_unregister_multiple(cli_meetme, ARRAY_LEN(cli_meetme)); 04773 res = ast_manager_unregister("MeetmeMute"); 04774 res |= ast_manager_unregister("MeetmeUnmute"); 04775 res |= ast_unregister_application(app3); 04776 res |= ast_unregister_application(app2); 04777 res |= ast_unregister_application(app); 04778 res |= ast_unregister_application(slastation_app); 04779 res |= ast_unregister_application(slatrunk_app); 04780 04781 ast_devstate_prov_del("Meetme"); 04782 ast_devstate_prov_del("SLA"); 04783 04784 ast_module_user_hangup_all(); 04785 04786 sla_destroy(); 04787 04788 return res; 04789 }
const char* app = "MeetMe" [static] |
Definition at line 200 of file app_meetme.c.
const char* app2 = "MeetMeCount" [static] |
Definition at line 201 of file app_meetme.c.
const char* app3 = "MeetMeAdmin" [static] |
Definition at line 202 of file app_meetme.c.
int audio_buffers [static] |
The number of audio buffers to be allocated on pseudo channels when in a conference
Definition at line 538 of file app_meetme.c.
struct ast_cli_entry cli_meetme[] [static] |
Definition at line 1180 of file app_meetme.c.
Definition at line 522 of file app_meetme.c.
Referenced by _macro_exec(), and ast_safe_sleep_conditional().
unsigned int conf_map[1024] = {0, } [static] |
Definition at line 349 of file app_meetme.c.
Referenced by build_conf(), conf_exec(), and dispose_conf().
const char* descrip [static] |
Definition at line 212 of file app_meetme.c.
const char* descrip2 [static] |
Definition at line 261 of file app_meetme.c.
const char* descrip3 [static] |
Definition at line 269 of file app_meetme.c.
char const gain_map[] [static] |
Map 'volume' levels from -5 through +5 into decibel (dB) settings for channel drivers Note: these are not a straight linear-to-dB conversion... the numbers have been modified to give the user a better level of adjustability
Definition at line 546 of file app_meetme.c.
Definition at line 523 of file app_meetme.c.
char meetme_usage[] [static] |
Initial value:
"Usage: meetme (un)lock|(un)mute|kick|list [concise] <confno> <usernumber>\n" " Executes a command for the conference or on a conferee\n"
Definition at line 1030 of file app_meetme.c.
struct { ... } sla [static] |
A structure for data used by the sla thread.
Referenced by dial_trunk(), queue_ringing_trunk(), sla_calc_station_timeouts(), sla_calc_trunk_timeouts(), sla_check_failed_station(), sla_check_ringing_station(), sla_choose_ringing_trunk(), sla_destroy(), sla_handle_dial_state_event(), sla_handle_ringing_trunk_event(), sla_hangup_stations(), sla_load_config(), sla_queue_event_full(), sla_ring_station(), sla_ring_stations(), sla_stop_ringing_station(), sla_thread(), and sla_trunk_exec().
const char sla_registrar[] = "SLA" [static] |
Definition at line 467 of file app_meetme.c.
Referenced by destroy_station(), destroy_trunk(), sla_build_station(), and sla_build_trunk().
const char sla_show_stations_usage[] [static] |
Initial value:
"Usage: sla show stations\n" " This will list all stations defined in sla.conf\n"
Definition at line 1176 of file app_meetme.c.
const char sla_show_trunks_usage[] [static] |
Initial value:
"Usage: sla show trunks\n" " This will list all trunks defined in sla.conf\n"
Definition at line 1107 of file app_meetme.c.
const char* slastation_app = "SLAStation" [static] |
Definition at line 203 of file app_meetme.c.
const char* slastation_desc [static] |
Definition at line 292 of file app_meetme.c.
const char* slastation_synopsis = "Shared Line Appearance Station" [static] |
Definition at line 209 of file app_meetme.c.
const char* slatrunk_app = "SLATrunk" [static] |
Definition at line 204 of file app_meetme.c.
const char* slatrunk_desc [static] |
Definition at line 305 of file app_meetme.c.
const char* slatrunk_synopsis = "Shared Line Appearance Trunk" [static] |
Definition at line 210 of file app_meetme.c.
const char* synopsis = "MeetMe conference bridge" [static] |
Definition at line 206 of file app_meetme.c.
const char* synopsis2 = "MeetMe participant count" [static] |
Definition at line 207 of file app_meetme.c.
const char* synopsis3 = "MeetMe conference Administration" [static] |
Definition at line 208 of file app_meetme.c.
pthread_t thread |
The SLA thread ID
Definition at line 521 of file app_meetme.c.
Referenced by __schedule_action(), __unload_module(), ast_bridge_call_thread_launch(), find_idle_thread(), iax2_process_thread(), iax2_process_thread_cleanup(), iax2_show_threads(), launch_monitor_thread(), load_module(), socket_read(), and start_network_thread().