Meet me conference bridge and Shared Line Appearances. More...
#include "asterisk.h"
#include <dahdi/user.h>
#include "asterisk/lock.h"
#include "asterisk/file.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/config.h"
#include "asterisk/app.h"
#include "asterisk/dsp.h"
#include "asterisk/musiconhold.h"
#include "asterisk/manager.h"
#include "asterisk/cli.h"
#include "asterisk/say.h"
#include "asterisk/utils.h"
#include "asterisk/translate.h"
#include "asterisk/ulaw.h"
#include "asterisk/astobj2.h"
#include "asterisk/devicestate.h"
#include "asterisk/dial.h"
#include "asterisk/causes.h"
#include "asterisk/paths.h"
#include "asterisk/data.h"
#include "asterisk/test.h"
#include "enter.h"
#include "leave.h"
Go to the source code of this file.
Data Structures | |
struct | announce_listitem |
struct | ast_conf_user |
The MeetMe User object. More... | |
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 | CONFFLAG_DONT_DENOISE (1ULL << 33) |
#define | CONFFLAG_INTROMSG (1ULL << 32) |
#define | CONFFLAG_NO_AUDIO_UNTIL_UP (1ULL << 31) |
#define | CONFIG_FILE_NAME "meetme.conf" |
#define | DATE_FORMAT "%Y-%m-%d %H:%M:%S" |
#define | DEFAULT_AUDIO_BUFFERS 32 |
#define | MAX_CONFNUM 80 |
#define | MAX_PIN 80 |
#define | MAX_SETTINGS (MAX_CONFNUM + MAX_PIN + MAX_PIN + 3) |
#define | MC_DATA_FORMAT "%-12.12s %4.4d %4.4s %02d:%02d:%02d %-8s %-6s\n" |
#define | MC_HEADER_FORMAT "%-14s %-14s %-10s %-8s %-8s %-6s\n" |
#define | MEETME_DATA_EXPORT(MEMBER) |
#define | MEETME_DELAYDETECTENDTALK 1000 |
#define | MEETME_DELAYDETECTTALK 300 |
#define | MEETME_USER_DATA_EXPORT(MEMBER) |
#define | OPTIONS_LEN 100 |
#define | S(e) case e: return # e; |
#define | SLA_CONFIG_FILE "sla.conf" |
#define | STR_CONCISE "concise" |
Enumerations | |
enum | { ADMINFLAG_MUTED = (1 << 1), ADMINFLAG_SELFMUTED = (1 << 2), ADMINFLAG_KICKME = (1 << 3), ADMINFLAG_T_REQUEST = (1 << 4) } |
enum | { CONFFLAG_ADMIN = (1 << 0), CONFFLAG_MONITOR = (1 << 1), CONFFLAG_KEYEXIT = (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), CONFFLAG_KICK_CONTINUE = (1 << 28), CONFFLAG_DURATION_STOP = (1 << 29), CONFFLAG_DURATION_LIMIT = (1 << 30) } |
enum | { OPT_ARG_WAITMARKED = 0, OPT_ARG_EXITKEYS = 1, OPT_ARG_DURATION_STOP = 2, OPT_ARG_DURATION_LIMIT = 3, OPT_ARG_MOH_CLASS = 4, OPT_ARG_INTROMSG = 5, OPT_ARG_ARRAY_SIZE = 6 } |
enum | { SLA_TRUNK_OPT_MOH = (1 << 0) } |
enum | { SLA_TRUNK_OPT_ARG_MOH_CLASS = 0, SLA_TRUNK_OPT_ARG_ARRAY_SIZE = 1 } |
enum | announcetypes { CONF_HASJOIN, CONF_HASLEFT } |
enum | entrance_sound { ENTER, LEAVE } |
enum | menu_modes { MENU_DISABLED = 0, MENU_NORMAL, MENU_ADMIN, MENU_ADMIN_EXTENDED } |
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, SLA_EVENT_RELOAD, SLA_EVENT_CHECK_RELOAD } |
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 | acf_meetme_info (struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len) |
static int | acf_meetme_info_eval (const char *keyword, const struct ast_conference *conf) |
static int | action_meetmelist (struct mansession *s, const struct message *m) |
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, const char *data) |
The MeetMeadmin application. | |
static void * | announce_thread (void *data) |
static void | answer_trunk_chan (struct ast_channel *chan) |
AST_APP_OPTIONS (sla_trunk_opts, BEGIN_OPTIONS AST_APP_OPTION_ARG('M', SLA_TRUNK_OPT_MOH, SLA_TRUNK_OPT_ARG_MOH_CLASS), END_OPTIONS) | |
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('C', CONFFLAG_KICK_CONTINUE), 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_ARG('G', CONFFLAG_INTROMSG, OPT_ARG_INTROMSG), AST_APP_OPTION('i', CONFFLAG_INTROUSER), AST_APP_OPTION('I', CONFFLAG_INTROUSERNOREVIEW), AST_APP_OPTION_ARG('M', CONFFLAG_MOH, OPT_ARG_MOH_CLASS), AST_APP_OPTION('m', CONFFLAG_STARTMUTED), AST_APP_OPTION('n', CONFFLAG_DONT_DENOISE), AST_APP_OPTION('o', CONFFLAG_OPTIMIZETALKER), AST_APP_OPTION('P', CONFFLAG_ALWAYSPROMPT), AST_APP_OPTION_ARG('p', CONFFLAG_KEYEXIT, OPT_ARG_EXITKEYS), 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), AST_APP_OPTION_ARG('S', CONFFLAG_DURATION_STOP, OPT_ARG_DURATION_STOP), AST_APP_OPTION_ARG('L', CONFFLAG_DURATION_LIMIT, OPT_ARG_DURATION_LIMIT), END_OPTIONS) | |
AST_DATA_STRUCTURE (ast_conf_user, MEETME_USER_DATA_EXPORT) | |
AST_DATA_STRUCTURE (ast_conference, MEETME_DATA_EXPORT) | |
static | AST_LIST_HEAD_STATIC (confs, ast_conference) |
AST_MODULE_INFO (ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER,"MeetMe conference bridge",.load=load_module,.unload=unload_module,.reload=reload,.load_pri=AST_MODPRI_DEVSTATE_PROVIDER,) | |
static | AST_RWLIST_HEAD_STATIC (sla_trunks, sla_trunk) |
static | AST_RWLIST_HEAD_STATIC (sla_stations, sla_station) |
static struct ast_conference * | build_conf (const char *confno, const char *pin, const char *pinadmin, int make, int dynamic, int refcount, const struct ast_channel *chan, struct ast_test *test) |
Find or create a conference. | |
static int | can_write (struct ast_channel *chan, struct ast_flags64 *confflags) |
static int | careful_write (int fd, unsigned char *data, int len, int block) |
static int | channel_admin_exec (struct ast_channel *chan, const char *data) |
The MeetMeChannelAdmin application MeetMeChannelAdmin(channel, command). | |
static char * | complete_confno (const char *word, int state) |
static char * | complete_meetmecmd_list (const char *line, const char *word, int pos, int state) |
static char * | complete_meetmecmd_lock (const char *word, int pos, int state) |
static char * | complete_meetmecmd_mute_kick (const char *line, const char *word, int pos, int state) |
static char * | complete_userno (struct ast_conference *cnf, const char *word, int state) |
static int | conf_exec (struct ast_channel *chan, const char *data) |
The meetme() application. | |
static void | conf_flush (int fd, struct ast_channel *chan) |
static int | conf_free (struct ast_conference *conf) |
Remove the conference from the list and free it. | |
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, struct ast_flags64 *confflags, char *optargs[]) |
static void | conf_start_moh (struct ast_channel *chan, const char *musicclass) |
static int | count_exec (struct ast_channel *chan, const char *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) |
Decrement reference counts, as incremented by find_conf(). | |
static void | filename_parse (char *filename, char *buffer) |
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_flags64 *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_flags64 *confflags, int *too_early, char **optargs) |
static struct ast_conf_user * | find_user (struct ast_conference *conf, const char *callerident) |
static const char * | get_announce_filename (enum announcetypes type) |
static const char * | istalking (int x) |
static int | load_config (int reload) |
static void | load_config_meetme (void) |
static int | load_module (void) |
static char * | meetme_cmd_helper (struct ast_cli_args *a) |
static int | meetme_data_provider_get (const struct ast_data_search *search, struct ast_data *data_root) |
static char * | meetme_kick_cmd (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | meetme_lock_cmd (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static void | meetme_menu (enum menu_modes *menu_mode, int *dtmf, struct ast_conference *conf, struct ast_flags64 *confflags, struct ast_channel *chan, struct ast_conf_user *user, char *recordingtmp, struct dahdi_confinfo *dahdic) |
static void | meetme_menu_admin (enum menu_modes *menu_mode, int *dtmf, struct ast_conference *conf, struct ast_flags64 *confflags, struct ast_channel *chan, struct ast_conf_user *user) |
static void | meetme_menu_admin_extended (enum menu_modes *menu_mode, int *dtmf, struct ast_conference *conf, struct ast_flags64 *confflags, struct ast_channel *chan, struct ast_conf_user *user, char *recordingtmp, struct dahdi_confinfo *dahdic) |
static void | meetme_menu_normal (enum menu_modes *menu_mode, int *dtmf, struct ast_conference *conf, struct ast_flags64 *confflags, struct ast_channel *chan, struct ast_conf_user *user) |
static char * | meetme_mute_cmd (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | meetme_show_cmd (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static int | meetmemute (struct mansession *s, const struct message *m, int mute) |
static enum ast_device_state | 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 int | rt_extend_conf (const char *confno) |
static void * | run_station (void *data) |
static void | send_talking_event (struct ast_channel *chan, struct ast_conference *conf, struct ast_conf_user *user, int talking) |
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 | set_user_talking (struct ast_channel *chan, struct ast_conference *conf, struct ast_conf_user *user, int talking, int monitor) |
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 void | sla_check_reload (void) |
Check if we can do a reload of SLA, and do it if we can. | |
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 rm) |
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 (int reload) |
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 char * | sla_show_stations (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | sla_show_trunks (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static enum ast_device_state | sla_state (const char *data) |
static enum ast_device_state | sla_state_to_devstate (enum sla_trunk_state state) |
static int | sla_station_exec (struct ast_channel *chan, const char *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, const char *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) |
static int | user_add_provider_cb (void *obj, void *arg, int flags) |
static int | user_chan_cb (void *obj, void *args, int flags) |
static int | user_listen_voldown_cb (void *obj, void *unused, int flags) |
static int | user_listen_volup_cb (void *obj, void *unused, int flags) |
static int | user_max_cmp (void *obj, void *arg, int flags) |
static int | user_no_cmp (void *obj, void *arg, int flags) |
static int | user_reset_vol_cb (void *obj, void *unused, int flags) |
static int | user_set_kickme_cb (void *obj, void *check_admin_arg, int flags) |
static int | user_set_muted_cb (void *obj, void *check_admin_arg, int flags) |
static int | user_set_unmuted_cb (void *obj, void *check_admin_arg, int flags) |
static int | user_talk_voldown_cb (void *obj, void *unused, int flags) |
static int | user_talk_volup_cb (void *obj, void *unused, int flags) |
Variables | |
static const char *const | app = "MeetMe" |
static const char *const | app2 = "MeetMeCount" |
static const char *const | app3 = "MeetMeAdmin" |
static const char *const | app4 = "MeetMeChannelAdmin" |
static int | audio_buffers |
The number of audio buffers to be allocated on pseudo channels when in a conference. | |
static struct ast_cli_entry | cli_meetme [] |
static unsigned int | conf_map [1024] = {0, } |
static int | earlyalert |
static int | endalert |
static int | extendby |
static int | fuzzystart |
static const char | gain_map [] |
Map 'volume' levels from -5 through +5 into decibel (dB) settings for channel drivers. | |
static struct ast_data_handler | meetme_data_provider |
static struct ast_data_entry | meetme_data_providers [] |
static struct ast_custom_function | meetme_info_acf |
static int | rt_log_members |
static int | rt_schedule |
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 *const | slastation_app = "SLAStation" |
static const char *const | slatrunk_app = "SLATrunk" |
Meet me conference bridge and Shared Line Appearances.
Definition in file app_meetme.c.
#define AST_FRAME_BITS 32 |
Definition at line 545 of file app_meetme.c.
Referenced by conf_free(), conf_run(), and recordthread().
#define CONF_SIZE 320 |
Definition at line 564 of file app_meetme.c.
#define CONFFLAG_DONT_DENOISE (1ULL << 33) |
If set, don't enable a denoiser for the channel
Definition at line 630 of file app_meetme.c.
Referenced by conf_run().
#define CONFFLAG_INTROMSG (1ULL << 32) |
If set play an intro announcement at start of conference
Definition at line 628 of file app_meetme.c.
Referenced by conf_run().
#define CONFFLAG_NO_AUDIO_UNTIL_UP (1ULL << 31) |
Do not write any audio to this channel until the state is up.
Definition at line 626 of file app_meetme.c.
Referenced by can_write(), conf_run(), and sla_trunk_exec().
#define CONFIG_FILE_NAME "meetme.conf" |
Definition at line 524 of file app_meetme.c.
Referenced by _dsp_init(), conf_exec(), find_conf(), and load_config_meetme().
#define DATE_FORMAT "%Y-%m-%d %H:%M:%S" |
String format for scheduled conferences
Definition at line 532 of file app_meetme.c.
Referenced by append_date(), build_radius_record(), conf_run(), execute_cb(), find_conf_realtime(), format_date(), get_date(), manager_log(), pgsql_log(), and rt_extend_conf().
#define DEFAULT_AUDIO_BUFFERS 32 |
each buffer is 20ms, so this is 640ms total
Definition at line 529 of file app_meetme.c.
Referenced by load_config_meetme().
#define MAX_CONFNUM 80 |
Definition at line 693 of file app_meetme.c.
Referenced by conf_exec(), dial_trunk(), meetme_cmd_helper(), sla_station_exec(), and sla_trunk_exec().
#define MAX_PIN 80 |
Definition at line 694 of file app_meetme.c.
Referenced by conf_exec().
#define MAX_SETTINGS (MAX_CONFNUM + MAX_PIN + MAX_PIN + 3) |
Definition at line 698 of file app_meetme.c.
Referenced by conf_exec(), and find_conf().
#define MC_DATA_FORMAT "%-12.12s %4.4d %4.4s %02d:%02d:%02d %-8s %-6s\n" |
Referenced by meetme_show_cmd().
#define MC_HEADER_FORMAT "%-14s %-14s %-10s %-8s %-8s %-6s\n" |
Referenced by meetme_show_cmd().
#define MEETME_DATA_EXPORT | ( | MEMBER | ) |
Definition at line 7248 of file app_meetme.c.
#define MEETME_DELAYDETECTENDTALK 1000 |
Definition at line 543 of file app_meetme.c.
Referenced by conf_run().
#define MEETME_DELAYDETECTTALK 300 |
Definition at line 542 of file app_meetme.c.
Referenced by conf_run().
#define MEETME_USER_DATA_EXPORT | ( | MEMBER | ) |
Definition at line 7265 of file app_meetme.c.
#define OPTIONS_LEN 100 |
Definition at line 695 of file app_meetme.c.
Referenced by find_conf_realtime().
#define S | ( | e | ) | case e: return # e; |
Referenced by sms_readfile(), and trunkstate2str().
#define SLA_CONFIG_FILE "sla.conf" |
Definition at line 525 of file app_meetme.c.
Referenced by sla_build_station(), sla_build_trunk(), and sla_load_config().
#define STR_CONCISE "concise" |
Definition at line 526 of file app_meetme.c.
Referenced by complete_meetmecmd_list(), and meetme_show_cmd().
anonymous enum |
ADMINFLAG_MUTED |
User is muted |
ADMINFLAG_SELFMUTED |
User muted self |
ADMINFLAG_KICKME |
User has been kicked |
ADMINFLAG_T_REQUEST |
User has requested to speak |
Definition at line 534 of file app_meetme.c.
00534 { 00535 ADMINFLAG_MUTED = (1 << 1), /*!< User is muted */ 00536 ADMINFLAG_SELFMUTED = (1 << 2), /*!< User muted self */ 00537 ADMINFLAG_KICKME = (1 << 3), /*!< User has been kicked */ 00538 /*! User has requested to speak */ 00539 ADMINFLAG_T_REQUEST = (1 << 4), 00540 };
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_KEYEXIT |
If set asterisk will exit conference when key defined in p() option 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 channel will leave the conference if all marked users leave |
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 | |
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 | |
CONFFLAG_SLA_TRUNK | |
CONFFLAG_KICK_CONTINUE |
If set, the user should continue in the dialplan if kicked out |
CONFFLAG_DURATION_STOP | |
CONFFLAG_DURATION_LIMIT |
Definition at line 566 of file app_meetme.c.
00566 { 00567 /*! user has admin access on the conference */ 00568 CONFFLAG_ADMIN = (1 << 0), 00569 /*! If set the user can only receive audio from the conference */ 00570 CONFFLAG_MONITOR = (1 << 1), 00571 /*! If set asterisk will exit conference when key defined in p() option is pressed */ 00572 CONFFLAG_KEYEXIT = (1 << 2), 00573 /*! If set asterisk will provide a menu to the user when '*' is pressed */ 00574 CONFFLAG_STARMENU = (1 << 3), 00575 /*! If set the use can only send audio to the conference */ 00576 CONFFLAG_TALKER = (1 << 4), 00577 /*! If set there will be no enter or leave sounds */ 00578 CONFFLAG_QUIET = (1 << 5), 00579 /*! If set, when user joins the conference, they will be told the number 00580 * of users that are already in */ 00581 CONFFLAG_ANNOUNCEUSERCOUNT = (1 << 6), 00582 /*! Set to run AGI Script in Background */ 00583 CONFFLAG_AGI = (1 << 7), 00584 /*! Set to have music on hold when user is alone in conference */ 00585 CONFFLAG_MOH = (1 << 8), 00586 /*! If set, the channel will leave the conference if all marked users leave */ 00587 CONFFLAG_MARKEDEXIT = (1 << 9), 00588 /*! If set, the MeetMe will wait until a marked user enters */ 00589 CONFFLAG_WAITMARKED = (1 << 10), 00590 /*! If set, the MeetMe will exit to the specified context */ 00591 CONFFLAG_EXIT_CONTEXT = (1 << 11), 00592 /*! If set, the user will be marked */ 00593 CONFFLAG_MARKEDUSER = (1 << 12), 00594 /*! If set, user will be ask record name on entry of conference */ 00595 CONFFLAG_INTROUSER = (1 << 13), 00596 /*! If set, the MeetMe will be recorded */ 00597 CONFFLAG_RECORDCONF = (1<< 14), 00598 /*! If set, the user will be monitored if the user is talking or not */ 00599 CONFFLAG_MONITORTALKER = (1 << 15), 00600 CONFFLAG_DYNAMIC = (1 << 16), 00601 CONFFLAG_DYNAMICPIN = (1 << 17), 00602 CONFFLAG_EMPTY = (1 << 18), 00603 CONFFLAG_EMPTYNOPIN = (1 << 19), 00604 CONFFLAG_ALWAYSPROMPT = (1 << 20), 00605 /*! If set, treat talking users as muted users */ 00606 CONFFLAG_OPTIMIZETALKER = (1 << 21), 00607 /*! If set, won't speak the extra prompt when the first person 00608 * enters the conference */ 00609 CONFFLAG_NOONLYPERSON = (1 << 22), 00610 /*! If set, user will be asked to record name on entry of conference 00611 * without review */ 00612 CONFFLAG_INTROUSERNOREVIEW = (1 << 23), 00613 /*! If set, the user will be initially self-muted */ 00614 CONFFLAG_STARTMUTED = (1 << 24), 00615 /*! Pass DTMF through the conference */ 00616 CONFFLAG_PASS_DTMF = (1 << 25), 00617 CONFFLAG_SLA_STATION = (1 << 26), 00618 CONFFLAG_SLA_TRUNK = (1 << 27), 00619 /*! If set, the user should continue in the dialplan if kicked out */ 00620 CONFFLAG_KICK_CONTINUE = (1 << 28), 00621 CONFFLAG_DURATION_STOP = (1 << 29), 00622 CONFFLAG_DURATION_LIMIT = (1 << 30), 00623 };
anonymous enum |
OPT_ARG_WAITMARKED | |
OPT_ARG_EXITKEYS | |
OPT_ARG_DURATION_STOP | |
OPT_ARG_DURATION_LIMIT | |
OPT_ARG_MOH_CLASS | |
OPT_ARG_INTROMSG | |
OPT_ARG_ARRAY_SIZE |
Definition at line 632 of file app_meetme.c.
00632 { 00633 OPT_ARG_WAITMARKED = 0, 00634 OPT_ARG_EXITKEYS = 1, 00635 OPT_ARG_DURATION_STOP = 2, 00636 OPT_ARG_DURATION_LIMIT = 3, 00637 OPT_ARG_MOH_CLASS = 4, 00638 OPT_ARG_INTROMSG = 5, 00639 OPT_ARG_ARRAY_SIZE = 6, 00640 };
anonymous enum |
Definition at line 6605 of file app_meetme.c.
06605 { 06606 SLA_TRUNK_OPT_MOH = (1 << 0), 06607 };
anonymous enum |
Definition at line 6609 of file app_meetme.c.
06609 { 06610 SLA_TRUNK_OPT_ARG_MOH_CLASS = 0, 06611 SLA_TRUNK_OPT_ARG_ARRAY_SIZE = 1, 06612 };
enum announcetypes |
Definition at line 700 of file app_meetme.c.
00700 { 00701 CONF_HASJOIN, 00702 CONF_HASLEFT 00703 };
enum entrance_sound |
Definition at line 552 of file app_meetme.c.
enum menu_modes |
Definition at line 2295 of file app_meetme.c.
02295 { 02296 MENU_DISABLED = 0, 02297 MENU_NORMAL, 02298 MENU_ADMIN, 02299 MENU_ADMIN_EXTENDED, 02300 };
enum recording_state |
Definition at line 557 of file app_meetme.c.
00557 { 00558 MEETME_RECORD_OFF, 00559 MEETME_RECORD_STARTED, 00560 MEETME_RECORD_ACTIVE, 00561 MEETME_RECORD_TERMINATE 00562 };
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 |
SLA_EVENT_RELOAD |
A reload of configuration has been requested |
SLA_EVENT_CHECK_RELOAD |
Poke the SLA thread so it can check if it can perform a reload |
Definition at line 894 of file app_meetme.c.
00894 { 00895 /*! A station has put the call on hold */ 00896 SLA_EVENT_HOLD, 00897 /*! The state of a dial has changed */ 00898 SLA_EVENT_DIAL_STATE, 00899 /*! The state of a ringing trunk has changed */ 00900 SLA_EVENT_RINGING_TRUNK, 00901 /*! A reload of configuration has been requested */ 00902 SLA_EVENT_RELOAD, 00903 /*! Poke the SLA thread so it can check if it can perform a reload */ 00904 SLA_EVENT_CHECK_RELOAD, 00905 };
enum sla_hold_access |
Definition at line 804 of file app_meetme.c.
00804 { 00805 /*! This means that any station can put it on hold, and any station 00806 * can retrieve the call from hold. */ 00807 SLA_HOLD_OPEN, 00808 /*! This means that only the station that put the call on hold may 00809 * retrieve it from hold. */ 00810 SLA_HOLD_PRIVATE, 00811 };
enum sla_station_hangup |
Definition at line 931 of file app_meetme.c.
00931 { 00932 SLA_STATION_HANGUP_NORMAL, 00933 SLA_STATION_HANGUP_TIMEOUT, 00934 };
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 796 of file app_meetme.c.
00796 { 00797 SLA_TRUNK_STATE_IDLE, 00798 SLA_TRUNK_STATE_RINGING, 00799 SLA_TRUNK_STATE_UP, 00800 SLA_TRUNK_STATE_ONHOLD, 00801 SLA_TRUNK_STATE_ONHOLD_BYME, 00802 };
enum sla_which_trunk_refs |
Definition at line 791 of file app_meetme.c.
00791 { 00792 ALL_TRUNK_REFS, 00793 INACTIVE_TRUNK_REFS, 00794 };
enum volume_action |
Definition at line 547 of file app_meetme.c.
static int acf_meetme_info | ( | struct ast_channel * | chan, | |
const char * | cmd, | |||
char * | data, | |||
char * | buf, | |||
size_t | len | |||
) | [static] |
Definition at line 7177 of file app_meetme.c.
References acf_meetme_info_eval(), args, AST_APP_ARG, AST_DECLARE_APP_ARGS, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), ast_conference::confno, LOG_ERROR, LOG_NOTICE, and parse().
07178 { 07179 struct ast_conference *conf; 07180 char *parse; 07181 int result = -2; /* only non-negative numbers valid, -1 is used elsewhere */ 07182 AST_DECLARE_APP_ARGS(args, 07183 AST_APP_ARG(keyword); 07184 AST_APP_ARG(confno); 07185 ); 07186 07187 if (ast_strlen_zero(data)) { 07188 ast_log(LOG_ERROR, "Syntax: MEETME_INFO() requires two arguments\n"); 07189 return -1; 07190 } 07191 07192 parse = ast_strdupa(data); 07193 AST_STANDARD_APP_ARGS(args, parse); 07194 07195 if (ast_strlen_zero(args.keyword)) { 07196 ast_log(LOG_ERROR, "Syntax: MEETME_INFO() requires a keyword\n"); 07197 return -1; 07198 } 07199 07200 if (ast_strlen_zero(args.confno)) { 07201 ast_log(LOG_ERROR, "Syntax: MEETME_INFO() requires a conference number\n"); 07202 return -1; 07203 } 07204 07205 AST_LIST_LOCK(&confs); 07206 AST_LIST_TRAVERSE(&confs, conf, list) { 07207 if (!strcmp(args.confno, conf->confno)) { 07208 result = acf_meetme_info_eval(args.keyword, conf); 07209 break; 07210 } 07211 } 07212 AST_LIST_UNLOCK(&confs); 07213 07214 if (result > -1) { 07215 snprintf(buf, len, "%d", result); 07216 } else if (result == -1) { 07217 ast_log(LOG_NOTICE, "Error: invalid keyword: '%s'\n", args.keyword); 07218 snprintf(buf, len, "0"); 07219 } else if (result == -2) { 07220 ast_log(LOG_NOTICE, "Error: conference (%s) not found\n", args.confno); 07221 snprintf(buf, len, "0"); 07222 } 07223 07224 return 0; 07225 }
static int acf_meetme_info_eval | ( | const char * | keyword, | |
const struct ast_conference * | conf | |||
) | [static] |
Definition at line 7159 of file app_meetme.c.
References ast_conference::isdynamic, ast_conference::locked, ast_conference::start, and ast_conference::users.
Referenced by acf_meetme_info().
07160 { 07161 if (!strcasecmp("lock", keyword)) { 07162 return conf->locked; 07163 } else if (!strcasecmp("parties", keyword)) { 07164 return conf->users; 07165 } else if (!strcasecmp("activity", keyword)) { 07166 time_t now; 07167 now = time(NULL); 07168 return (now - conf->start); 07169 } else if (!strcasecmp("dynamic", keyword)) { 07170 return conf->isdynamic; 07171 } else { 07172 return -1; 07173 } 07174 07175 }
static int action_meetmelist | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 5034 of file app_meetme.c.
References ADMINFLAG_MUTED, ADMINFLAG_SELFMUTED, ast_conf_user::adminflags, ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_ref, AST_LIST_EMPTY, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_strlen_zero(), ast_test_flag64, astman_append(), astman_get_header(), astman_send_error(), astman_send_listack(), ast_channel::caller, ast_conf_user::chan, CONFFLAG_ADMIN, CONFFLAG_MARKEDUSER, CONFFLAG_MONITOR, CONFFLAG_TALKER, ast_conference::confno, ast_channel::connected, ast_party_connected_line::id, ast_party_caller::id, ast_party_id::name, ast_party_id::number, S_COR, ast_party_name::str, ast_party_number::str, ast_conf_user::talking, total, ast_conf_user::user_no, ast_conference::usercontainer, ast_conf_user::userflags, ast_party_name::valid, and ast_party_number::valid.
Referenced by load_module().
05035 { 05036 const char *actionid = astman_get_header(m, "ActionID"); 05037 const char *conference = astman_get_header(m, "Conference"); 05038 char idText[80] = ""; 05039 struct ast_conference *cnf; 05040 struct ast_conf_user *user; 05041 struct ao2_iterator user_iter; 05042 int total = 0; 05043 05044 if (!ast_strlen_zero(actionid)) 05045 snprintf(idText, sizeof(idText), "ActionID: %s\r\n", actionid); 05046 05047 if (AST_LIST_EMPTY(&confs)) { 05048 astman_send_error(s, m, "No active conferences."); 05049 return 0; 05050 } 05051 05052 astman_send_listack(s, m, "Meetme user list will follow", "start"); 05053 05054 /* Find the right conference */ 05055 AST_LIST_LOCK(&confs); 05056 AST_LIST_TRAVERSE(&confs, cnf, list) { 05057 /* If we ask for one particular, and this isn't it, skip it */ 05058 if (!ast_strlen_zero(conference) && strcmp(cnf->confno, conference)) 05059 continue; 05060 05061 /* Show all the users */ 05062 user_iter = ao2_iterator_init(cnf->usercontainer, 0); 05063 while ((user = ao2_iterator_next(&user_iter))) { 05064 total++; 05065 astman_append(s, 05066 "Event: MeetmeList\r\n" 05067 "%s" 05068 "Conference: %s\r\n" 05069 "UserNumber: %d\r\n" 05070 "CallerIDNum: %s\r\n" 05071 "CallerIDName: %s\r\n" 05072 "ConnectedLineNum: %s\r\n" 05073 "ConnectedLineName: %s\r\n" 05074 "Channel: %s\r\n" 05075 "Admin: %s\r\n" 05076 "Role: %s\r\n" 05077 "MarkedUser: %s\r\n" 05078 "Muted: %s\r\n" 05079 "Talking: %s\r\n" 05080 "\r\n", 05081 idText, 05082 cnf->confno, 05083 user->user_no, 05084 S_COR(user->chan->caller.id.number.valid, user->chan->caller.id.number.str, "<unknown>"), 05085 S_COR(user->chan->caller.id.name.valid, user->chan->caller.id.name.str, "<no name>"), 05086 S_COR(user->chan->connected.id.number.valid, user->chan->connected.id.number.str, "<unknown>"), 05087 S_COR(user->chan->connected.id.name.valid, user->chan->connected.id.name.str, "<no name>"), 05088 user->chan->name, 05089 ast_test_flag64(&user->userflags, CONFFLAG_ADMIN) ? "Yes" : "No", 05090 ast_test_flag64(&user->userflags, CONFFLAG_MONITOR) ? "Listen only" : ast_test_flag64(&user->userflags, CONFFLAG_TALKER) ? "Talk only" : "Talk and listen", 05091 ast_test_flag64(&user->userflags, CONFFLAG_MARKEDUSER) ? "Yes" : "No", 05092 user->adminflags & ADMINFLAG_MUTED ? "By admin" : user->adminflags & ADMINFLAG_SELFMUTED ? "By self" : "No", 05093 user->talking > 0 ? "Yes" : user->talking == 0 ? "No" : "Not monitored"); 05094 ao2_ref(user, -1); 05095 } 05096 ao2_iterator_destroy(&user_iter); 05097 } 05098 AST_LIST_UNLOCK(&confs); 05099 /* Send final confirmation */ 05100 astman_append(s, 05101 "Event: MeetmeListComplete\r\n" 05102 "EventList: Complete\r\n" 05103 "ListItems: %d\r\n" 05104 "%s" 05105 "\r\n", total, idText); 05106 return 0; 05107 }
static int action_meetmemute | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 5024 of file app_meetme.c.
References meetmemute().
Referenced by load_module().
05025 { 05026 return meetmemute(s, m, 1); 05027 }
static int action_meetmeunmute | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 5029 of file app_meetme.c.
References meetmemute().
Referenced by load_module().
05030 { 05031 return meetmemute(s, m, 0); 05032 }
static int admin_exec | ( | struct ast_channel * | chan, | |
const char * | data | |||
) | [static] |
The MeetMeadmin application.
MeetMeAdmin(confno, command, caller)
Definition at line 4756 of file app_meetme.c.
References ADMINFLAG_KICKME, ADMINFLAG_MUTED, ADMINFLAG_SELFMUTED, ADMINFLAG_T_REQUEST, ast_conf_user::adminflags, ao2_callback, ao2_find, ao2_ref, args, AST_APP_ARG, ast_atomic_fetchadd_int(), AST_DECLARE_APP_ARGS, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), ast_test_flag64, CONFFLAG_ADMIN, ast_conference::confno, dispose_conf(), find_user(), ast_conference::locked, LOG_NOTICE, LOG_WARNING, OBJ_NODATA, pbx_builtin_setvar_helper(), ast_conference::refcount, reset_volumes(), rt_extend_conf(), tweak_listen_volume(), tweak_talk_volume(), user_listen_voldown_cb(), user_listen_volup_cb(), user_max_cmp(), user_reset_vol_cb(), user_set_kickme_cb(), user_set_muted_cb(), user_set_unmuted_cb(), user_talk_voldown_cb(), user_talk_volup_cb(), ast_conference::usercontainer, ast_conf_user::userflags, VOL_DOWN, and VOL_UP.
Referenced by load_module(), meetme_cmd_helper(), run_station(), sla_station_exec(), and sla_stop_ringing_trunk().
04756 { 04757 char *params; 04758 struct ast_conference *cnf; 04759 struct ast_conf_user *user = NULL; 04760 AST_DECLARE_APP_ARGS(args, 04761 AST_APP_ARG(confno); 04762 AST_APP_ARG(command); 04763 AST_APP_ARG(user); 04764 ); 04765 int res = 0; 04766 04767 if (ast_strlen_zero(data)) { 04768 ast_log(LOG_WARNING, "MeetMeAdmin requires an argument!\n"); 04769 pbx_builtin_setvar_helper(chan, "MEETMEADMINSTATUS", "NOPARSE"); 04770 return -1; 04771 } 04772 04773 params = ast_strdupa(data); 04774 AST_STANDARD_APP_ARGS(args, params); 04775 04776 if (!args.command) { 04777 ast_log(LOG_WARNING, "MeetmeAdmin requires a command!\n"); 04778 pbx_builtin_setvar_helper(chan, "MEETMEADMINSTATUS", "NOPARSE"); 04779 return -1; 04780 } 04781 04782 AST_LIST_LOCK(&confs); 04783 AST_LIST_TRAVERSE(&confs, cnf, list) { 04784 if (!strcmp(cnf->confno, args.confno)) 04785 break; 04786 } 04787 04788 if (!cnf) { 04789 ast_log(LOG_WARNING, "Conference number '%s' not found!\n", args.confno); 04790 AST_LIST_UNLOCK(&confs); 04791 pbx_builtin_setvar_helper(chan, "MEETMEADMINSTATUS", "NOTFOUND"); 04792 return 0; 04793 } 04794 04795 ast_atomic_fetchadd_int(&cnf->refcount, 1); 04796 04797 if (args.user) { 04798 user = find_user(cnf, args.user); 04799 if (!user) { 04800 ast_log(LOG_NOTICE, "Specified User not found!\n"); 04801 res = -2; 04802 goto usernotfound; 04803 } 04804 } 04805 04806 switch (*args.command) { 04807 case 76: /* L: Lock */ 04808 cnf->locked = 1; 04809 break; 04810 case 108: /* l: Unlock */ 04811 cnf->locked = 0; 04812 break; 04813 case 75: /* K: kick all users */ 04814 ao2_callback(cnf->usercontainer, OBJ_NODATA, user_set_kickme_cb, NULL); 04815 break; 04816 case 101: /* e: Eject last user*/ 04817 { 04818 int max_no = 0; 04819 04820 /* If they passed in a user, disregard it */ 04821 if (user) { 04822 ao2_ref(user, -1); 04823 } 04824 04825 ao2_callback(cnf->usercontainer, OBJ_NODATA, user_max_cmp, &max_no); 04826 user = ao2_find(cnf->usercontainer, &max_no, 0); 04827 if (!ast_test_flag64(&user->userflags, CONFFLAG_ADMIN)) 04828 user->adminflags |= ADMINFLAG_KICKME; 04829 else { 04830 res = -1; 04831 ast_log(LOG_NOTICE, "Not kicking last user, is an Admin!\n"); 04832 } 04833 ao2_ref(user, -1); 04834 break; 04835 } 04836 case 77: /* M: Mute */ 04837 user->adminflags |= ADMINFLAG_MUTED; 04838 break; 04839 case 78: /* N: Mute all (non-admin) users */ 04840 ao2_callback(cnf->usercontainer, OBJ_NODATA, user_set_muted_cb, &cnf); 04841 break; 04842 case 109: /* m: Unmute */ 04843 user->adminflags &= ~(ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED | ADMINFLAG_T_REQUEST); 04844 break; 04845 case 110: /* n: Unmute all users */ 04846 ao2_callback(cnf->usercontainer, OBJ_NODATA, user_set_unmuted_cb, NULL); 04847 break; 04848 case 107: /* k: Kick user */ 04849 user->adminflags |= ADMINFLAG_KICKME; 04850 break; 04851 case 118: /* v: Lower all users listen volume */ 04852 ao2_callback(cnf->usercontainer, OBJ_NODATA, user_listen_voldown_cb, NULL); 04853 break; 04854 case 86: /* V: Raise all users listen volume */ 04855 ao2_callback(cnf->usercontainer, OBJ_NODATA, user_listen_volup_cb, NULL); 04856 break; 04857 case 115: /* s: Lower all users speaking volume */ 04858 ao2_callback(cnf->usercontainer, OBJ_NODATA, user_talk_voldown_cb, NULL); 04859 break; 04860 case 83: /* S: Raise all users speaking volume */ 04861 ao2_callback(cnf->usercontainer, OBJ_NODATA, user_talk_volup_cb, NULL); 04862 break; 04863 case 82: /* R: Reset all volume levels */ 04864 ao2_callback(cnf->usercontainer, OBJ_NODATA, user_reset_vol_cb, NULL); 04865 break; 04866 case 114: /* r: Reset user's volume level */ 04867 reset_volumes(user); 04868 break; 04869 case 85: /* U: Raise user's listen volume */ 04870 tweak_listen_volume(user, VOL_UP); 04871 break; 04872 case 117: /* u: Lower user's listen volume */ 04873 tweak_listen_volume(user, VOL_DOWN); 04874 break; 04875 case 84: /* T: Raise user's talk volume */ 04876 tweak_talk_volume(user, VOL_UP); 04877 break; 04878 case 116: /* t: Lower user's talk volume */ 04879 tweak_talk_volume(user, VOL_DOWN); 04880 break; 04881 case 'E': /* E: Extend conference */ 04882 if (rt_extend_conf(args.confno)) { 04883 res = -1; 04884 } 04885 break; 04886 } 04887 04888 if (args.user) { 04889 /* decrement reference from find_user */ 04890 ao2_ref(user, -1); 04891 } 04892 usernotfound: 04893 AST_LIST_UNLOCK(&confs); 04894 04895 dispose_conf(cnf); 04896 pbx_builtin_setvar_helper(chan, "MEETMEADMINSTATUS", res == -2 ? "NOTFOUND" : res ? "FAILED" : "OK"); 04897 04898 return 0; 04899 }
static void* announce_thread | ( | void * | data | ) | [static] |
Definition at line 2171 of file app_meetme.c.
References ao2_ref, ast_check_hangup(), ast_cond_wait, ast_copy_string(), ast_filedelete(), ast_fileexists(), AST_LIST_APPEND_LIST, AST_LIST_EMPTY, AST_LIST_HEAD_INIT_NOLOCK, AST_LIST_HEAD_NOLOCK, AST_LIST_REMOVE_HEAD, ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_streamfile(), ast_waitstream(), CONF_HASLEFT, get_announce_filename(), and LOG_DEBUG.
Referenced by conf_run().
02172 { 02173 struct announce_listitem *current; 02174 struct ast_conference *conf = data; 02175 int res; 02176 char filename[PATH_MAX] = ""; 02177 AST_LIST_HEAD_NOLOCK(, announce_listitem) local_list; 02178 AST_LIST_HEAD_INIT_NOLOCK(&local_list); 02179 02180 while (!conf->announcethread_stop) { 02181 ast_mutex_lock(&conf->announcelistlock); 02182 if (conf->announcethread_stop) { 02183 ast_mutex_unlock(&conf->announcelistlock); 02184 break; 02185 } 02186 if (AST_LIST_EMPTY(&conf->announcelist)) 02187 ast_cond_wait(&conf->announcelist_addition, &conf->announcelistlock); 02188 02189 AST_LIST_APPEND_LIST(&local_list, &conf->announcelist, entry); 02190 AST_LIST_HEAD_INIT_NOLOCK(&conf->announcelist); 02191 02192 ast_mutex_unlock(&conf->announcelistlock); 02193 if (conf->announcethread_stop) { 02194 break; 02195 } 02196 02197 for (res = 1; !conf->announcethread_stop && (current = AST_LIST_REMOVE_HEAD(&local_list, entry)); ao2_ref(current, -1)) { 02198 ast_log(LOG_DEBUG, "About to play %s\n", current->namerecloc); 02199 if (!ast_fileexists(current->namerecloc, NULL, NULL)) 02200 continue; 02201 if ((current->confchan) && (current->confusers > 1) && !ast_check_hangup(current->confchan)) { 02202 if (!ast_streamfile(current->confchan, current->namerecloc, current->language)) 02203 res = ast_waitstream(current->confchan, ""); 02204 if (!res) { 02205 ast_copy_string(filename, get_announce_filename(current->announcetype), sizeof(filename)); 02206 if (!ast_streamfile(current->confchan, filename, current->language)) 02207 ast_waitstream(current->confchan, ""); 02208 } 02209 } 02210 if (current->announcetype == CONF_HASLEFT) { 02211 ast_filedelete(current->namerecloc, NULL); 02212 } 02213 } 02214 } 02215 02216 /* thread marked to stop, clean up */ 02217 while ((current = AST_LIST_REMOVE_HEAD(&local_list, entry))) { 02218 ast_filedelete(current->namerecloc, NULL); 02219 ao2_ref(current, -1); 02220 } 02221 return NULL; 02222 }
static void answer_trunk_chan | ( | struct ast_channel * | chan | ) | [static] |
Definition at line 5446 of file app_meetme.c.
References ast_answer(), and ast_indicate().
Referenced by run_station(), sla_handle_dial_state_event(), and sla_station_exec().
05447 { 05448 ast_answer(chan); 05449 ast_indicate(chan, -1); 05450 }
AST_APP_OPTIONS | ( | sla_trunk_opts | , | |
BEGIN_OPTIONS | AST_APP_OPTION_ARG'M', SLA_TRUNK_OPT_MOH, SLA_TRUNK_OPT_ARG_MOH_CLASS, | |||
END_OPTIONS | ||||
) |
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('C', CONFFLAG_KICK_CONTINUE) | , | |||
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_ARG('G', CONFFLAG_INTROMSG, OPT_ARG_INTROMSG) | , | |||
AST_APP_OPTION('i', CONFFLAG_INTROUSER) | , | |||
AST_APP_OPTION('I', CONFFLAG_INTROUSERNOREVIEW) | , | |||
AST_APP_OPTION_ARG('M', CONFFLAG_MOH, OPT_ARG_MOH_CLASS) | , | |||
AST_APP_OPTION('m', CONFFLAG_STARTMUTED) | , | |||
AST_APP_OPTION('n', CONFFLAG_DONT_DENOISE) | , | |||
AST_APP_OPTION('o', CONFFLAG_OPTIMIZETALKER) | , | |||
AST_APP_OPTION('P', CONFFLAG_ALWAYSPROMPT) | , | |||
AST_APP_OPTION_ARG('p', CONFFLAG_KEYEXIT, OPT_ARG_EXITKEYS) | , | |||
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) | , | |||
AST_APP_OPTION_ARG('S', CONFFLAG_DURATION_STOP, OPT_ARG_DURATION_STOP) | , | |||
AST_APP_OPTION_ARG('L', CONFFLAG_DURATION_LIMIT, OPT_ARG_DURATION_LIMIT) | , | |||
END_OPTIONS | ||||
) |
AST_DATA_STRUCTURE | ( | ast_conf_user | , | |
MEETME_USER_DATA_EXPORT | ||||
) |
AST_DATA_STRUCTURE | ( | ast_conference | , | |
MEETME_DATA_EXPORT | ||||
) |
static AST_LIST_HEAD_STATIC | ( | confs | , | |
ast_conference | ||||
) | [static] |
AST_MODULE_INFO | ( | ASTERISK_GPL_KEY | , | |
AST_MODFLAG_LOAD_ORDER | , | |||
"MeetMe conference bridge" | , | |||
. | load = load_module , |
|||
. | unload = unload_module , |
|||
. | reload = reload , |
|||
. | load_pri = AST_MODPRI_DEVSTATE_PROVIDER | |||
) |
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 | ( | const char * | confno, | |
const char * | pin, | |||
const char * | pinadmin, | |||
int | make, | |||
int | dynamic, | |||
int | refcount, | |||
const struct ast_channel * | chan, | |||
struct ast_test * | test | |||
) | [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 | |
chan | The asterisk channel |
Definition at line 1202 of file app_meetme.c.
References ao2_container_alloc, ao2_ref, ast_atomic_fetchadd_int(), ast_calloc, ast_copy_string(), AST_FORMAT_SLINEAR, ast_free, ast_hangup(), AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_mutex_destroy, ast_mutex_init, AST_PTHREADT_NULL, ast_request(), ast_set_read_format(), ast_set_write_format(), ast_test_status_update, ast_verb, ast_conference::chan, conf_map, ast_conference::confno, ast_conference::dahdiconf, ast_conference::fd, ast_channel::fds, ast_conference::isdynamic, ast_conference::listenlock, LOG_WARNING, ast_conference::maxusers, ast_conference::pin, ast_conference::pinadmin, ast_conference::playlock, ast_conference::recordthread, ast_conference::recordthreadlock, ast_conference::refcount, ast_conference::start, ast_conference::uniqueid, user_no_cmp(), and ast_conference::usercontainer.
Referenced by dial_trunk(), find_conf(), find_conf_realtime(), run_station(), sla_station_exec(), and sla_trunk_exec().
01205 { 01206 struct ast_conference *cnf; 01207 struct dahdi_confinfo dahdic = { 0, }; 01208 int confno_int = 0; 01209 01210 AST_LIST_LOCK(&confs); 01211 01212 AST_LIST_TRAVERSE(&confs, cnf, list) { 01213 if (!strcmp(confno, cnf->confno)) 01214 break; 01215 } 01216 01217 if (cnf || (!make && !dynamic)) 01218 goto cnfout; 01219 01220 /* Make a new one */ 01221 if (!(cnf = ast_calloc(1, sizeof(*cnf))) || 01222 !(cnf->usercontainer = ao2_container_alloc(1, NULL, user_no_cmp))) { 01223 goto cnfout; 01224 } 01225 01226 ast_mutex_init(&cnf->playlock); 01227 ast_mutex_init(&cnf->listenlock); 01228 cnf->recordthread = AST_PTHREADT_NULL; 01229 ast_mutex_init(&cnf->recordthreadlock); 01230 cnf->announcethread = AST_PTHREADT_NULL; 01231 ast_mutex_init(&cnf->announcethreadlock); 01232 ast_copy_string(cnf->confno, confno, sizeof(cnf->confno)); 01233 ast_copy_string(cnf->pin, pin, sizeof(cnf->pin)); 01234 ast_copy_string(cnf->pinadmin, pinadmin, sizeof(cnf->pinadmin)); 01235 ast_copy_string(cnf->uniqueid, chan->uniqueid, sizeof(cnf->uniqueid)); 01236 01237 /* Setup a new dahdi conference */ 01238 dahdic.confno = -1; 01239 dahdic.confmode = DAHDI_CONF_CONFANN | DAHDI_CONF_CONFANNMON; 01240 cnf->fd = open("/dev/dahdi/pseudo", O_RDWR); 01241 if (cnf->fd < 0 || ioctl(cnf->fd, DAHDI_SETCONF, &dahdic)) { 01242 if (test) { 01243 /* if we are creating a conference for a unit test, it is not neccesary 01244 * to open a pseudo channel, so, if we fail continue creating 01245 * the conference. */ 01246 ast_test_status_update(test, "Unable to open DAHDI pseudo device\n"); 01247 } else { 01248 ast_log(LOG_WARNING, "Unable to open DAHDI pseudo device\n"); 01249 if (cnf->fd >= 0) 01250 close(cnf->fd); 01251 ao2_ref(cnf->usercontainer, -1); 01252 ast_mutex_destroy(&cnf->playlock); 01253 ast_mutex_destroy(&cnf->listenlock); 01254 ast_mutex_destroy(&cnf->recordthreadlock); 01255 ast_mutex_destroy(&cnf->announcethreadlock); 01256 ast_free(cnf); 01257 cnf = NULL; 01258 goto cnfout; 01259 } 01260 } 01261 01262 cnf->dahdiconf = dahdic.confno; 01263 01264 /* Setup a new channel for playback of audio files */ 01265 cnf->chan = ast_request("DAHDI", AST_FORMAT_SLINEAR, chan, "pseudo", NULL); 01266 if (cnf->chan) { 01267 ast_set_read_format(cnf->chan, AST_FORMAT_SLINEAR); 01268 ast_set_write_format(cnf->chan, AST_FORMAT_SLINEAR); 01269 dahdic.chan = 0; 01270 dahdic.confno = cnf->dahdiconf; 01271 dahdic.confmode = DAHDI_CONF_CONFANN | DAHDI_CONF_CONFANNMON; 01272 if (ioctl(cnf->chan->fds[0], DAHDI_SETCONF, &dahdic)) { 01273 if (test) { 01274 ast_test_status_update(test, "Error setting conference on pseudo channel\n"); 01275 } 01276 ast_log(LOG_WARNING, "Error setting conference\n"); 01277 if (cnf->chan) 01278 ast_hangup(cnf->chan); 01279 else 01280 close(cnf->fd); 01281 ao2_ref(cnf->usercontainer, -1); 01282 ast_mutex_destroy(&cnf->playlock); 01283 ast_mutex_destroy(&cnf->listenlock); 01284 ast_mutex_destroy(&cnf->recordthreadlock); 01285 ast_mutex_destroy(&cnf->announcethreadlock); 01286 ast_free(cnf); 01287 cnf = NULL; 01288 goto cnfout; 01289 } 01290 } 01291 01292 /* Fill the conference struct */ 01293 cnf->start = time(NULL); 01294 cnf->maxusers = 0x7fffffff; 01295 cnf->isdynamic = dynamic ? 1 : 0; 01296 ast_verb(3, "Created MeetMe conference %d for conference '%s'\n", cnf->dahdiconf, cnf->confno); 01297 AST_LIST_INSERT_HEAD(&confs, cnf, list); 01298 01299 /* Reserve conference number in map */ 01300 if ((sscanf(cnf->confno, "%30d", &confno_int) == 1) && (confno_int >= 0 && confno_int < 1024)) 01301 conf_map[confno_int] = 1; 01302 01303 cnfout: 01304 if (cnf) 01305 ast_atomic_fetchadd_int(&cnf->refcount, refcount); 01306 01307 AST_LIST_UNLOCK(&confs); 01308 01309 return cnf; 01310 }
static int can_write | ( | struct ast_channel * | chan, | |
struct ast_flags64 * | confflags | |||
) | [static] |
Definition at line 2224 of file app_meetme.c.
References ast_channel::_state, AST_STATE_UP, ast_test_flag64, and CONFFLAG_NO_AUDIO_UNTIL_UP.
Referenced by conf_run().
02225 { 02226 if (!ast_test_flag64(confflags, CONFFLAG_NO_AUDIO_UNTIL_UP)) { 02227 return 1; 02228 } 02229 02230 return (chan->_state == AST_STATE_UP); 02231 }
static int careful_write | ( | int | fd, | |
unsigned char * | data, | |||
int | len, | |||
int | block | |||
) | [static] |
Definition at line 1005 of file app_meetme.c.
References ast_log(), errno, and LOG_WARNING.
Referenced by conf_play(), and conf_run().
01006 { 01007 int res; 01008 int x; 01009 01010 while (len) { 01011 if (block) { 01012 x = DAHDI_IOMUX_WRITE | DAHDI_IOMUX_SIGEVENT; 01013 res = ioctl(fd, DAHDI_IOMUX, &x); 01014 } else 01015 res = 0; 01016 if (res >= 0) 01017 res = write(fd, data, len); 01018 if (res < 1) { 01019 if (errno != EAGAIN) { 01020 ast_log(LOG_WARNING, "Failed to write audio data to conference: %s\n", strerror(errno)); 01021 return -1; 01022 } else 01023 return 0; 01024 } 01025 len -= res; 01026 data += res; 01027 } 01028 01029 return 0; 01030 }
static int channel_admin_exec | ( | struct ast_channel * | chan, | |
const char * | data | |||
) | [static] |
The MeetMeChannelAdmin application MeetMeChannelAdmin(channel, command).
Definition at line 4903 of file app_meetme.c.
References ADMINFLAG_KICKME, ADMINFLAG_MUTED, ast_conf_user::adminflags, ao2_callback, ao2_ref, args, AST_APP_ARG, AST_DECLARE_APP_ARGS, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), LOG_NOTICE, LOG_WARNING, user_chan_cb(), and ast_conference::usercontainer.
Referenced by load_module().
04903 { 04904 char *params; 04905 struct ast_conference *conf = NULL; 04906 struct ast_conf_user *user = NULL; 04907 AST_DECLARE_APP_ARGS(args, 04908 AST_APP_ARG(channel); 04909 AST_APP_ARG(command); 04910 ); 04911 04912 if (ast_strlen_zero(data)) { 04913 ast_log(LOG_WARNING, "MeetMeChannelAdmin requires two arguments!\n"); 04914 return -1; 04915 } 04916 04917 params = ast_strdupa(data); 04918 AST_STANDARD_APP_ARGS(args, params); 04919 04920 if (!args.channel) { 04921 ast_log(LOG_WARNING, "MeetMeChannelAdmin requires a channel name!\n"); 04922 return -1; 04923 } 04924 04925 if (!args.command) { 04926 ast_log(LOG_WARNING, "MeetMeChannelAdmin requires a command!\n"); 04927 return -1; 04928 } 04929 04930 AST_LIST_LOCK(&confs); 04931 AST_LIST_TRAVERSE(&confs, conf, list) { 04932 if ((user = ao2_callback(conf->usercontainer, 0, user_chan_cb, args.channel))) { 04933 break; 04934 } 04935 } 04936 04937 if (!user) { 04938 ast_log(LOG_NOTICE, "Specified user (%s) not found\n", args.channel); 04939 AST_LIST_UNLOCK(&confs); 04940 return 0; 04941 } 04942 04943 /* perform the specified action */ 04944 switch (*args.command) { 04945 case 77: /* M: Mute */ 04946 user->adminflags |= ADMINFLAG_MUTED; 04947 break; 04948 case 109: /* m: Unmute */ 04949 user->adminflags &= ~ADMINFLAG_MUTED; 04950 break; 04951 case 107: /* k: Kick user */ 04952 user->adminflags |= ADMINFLAG_KICKME; 04953 break; 04954 default: /* unknown command */ 04955 ast_log(LOG_WARNING, "Unknown MeetMeChannelAdmin command '%s'\n", args.command); 04956 break; 04957 } 04958 ao2_ref(user, -1); 04959 AST_LIST_UNLOCK(&confs); 04960 04961 return 0; 04962 }
static char* complete_confno | ( | const char * | word, | |
int | state | |||
) | [static] |
Definition at line 1312 of file app_meetme.c.
References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_strdup, ast_conference::confno, and len().
Referenced by complete_meetmecmd_list(), complete_meetmecmd_lock(), and complete_meetmecmd_mute_kick().
01313 { 01314 struct ast_conference *cnf; 01315 char *ret = NULL; 01316 int which = 0; 01317 int len = strlen(word); 01318 01319 AST_LIST_LOCK(&confs); 01320 AST_LIST_TRAVERSE(&confs, cnf, list) { 01321 if (!strncmp(word, cnf->confno, len) && ++which > state) { 01322 /* dup before releasing the lock */ 01323 ret = ast_strdup(cnf->confno); 01324 break; 01325 } 01326 } 01327 AST_LIST_UNLOCK(&confs); 01328 return ret; 01329 }
static char* complete_meetmecmd_list | ( | const char * | line, | |
const char * | word, | |||
int | pos, | |||
int | state | |||
) | [static] |
Definition at line 1401 of file app_meetme.c.
References ast_strdup, ast_strdupa, complete_confno(), ast_conference::confno, len(), and STR_CONCISE.
Referenced by meetme_show_cmd().
01402 { 01403 int len; 01404 01405 if (pos == 2) { 01406 len = strlen(word); 01407 if (!strncasecmp(word, STR_CONCISE, len)) { 01408 if (state == 0) { 01409 return ast_strdup(STR_CONCISE); 01410 } 01411 --state; 01412 } 01413 01414 return complete_confno(word, state); 01415 } 01416 if (pos == 3 && state == 0) { 01417 char *saved = NULL; 01418 char *myline; 01419 char *confno; 01420 01421 /* Extract the confno from the command line. */ 01422 myline = ast_strdupa(line); 01423 strtok_r(myline, " ", &saved); 01424 strtok_r(NULL, " ", &saved); 01425 confno = strtok_r(NULL, " ", &saved); 01426 01427 if (!strcasecmp(confno, STR_CONCISE)) { 01428 /* There is nothing valid in this position now. */ 01429 return NULL; 01430 } 01431 01432 len = strlen(word); 01433 if (!strncasecmp(word, STR_CONCISE, len)) { 01434 return ast_strdup(STR_CONCISE); 01435 } 01436 } 01437 return NULL; 01438 }
static char* complete_meetmecmd_lock | ( | const char * | word, | |
int | pos, | |||
int | state | |||
) | [static] |
Definition at line 1393 of file app_meetme.c.
References complete_confno().
Referenced by meetme_lock_cmd().
01394 { 01395 if (pos == 2) { 01396 return complete_confno(word, state); 01397 } 01398 return NULL; 01399 }
static char* complete_meetmecmd_mute_kick | ( | const char * | line, | |
const char * | word, | |||
int | pos, | |||
int | state | |||
) | [static] |
Definition at line 1353 of file app_meetme.c.
References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_strdup, ast_strdupa, complete_confno(), complete_userno(), ast_conference::confno, and len().
Referenced by meetme_kick_cmd(), and meetme_mute_cmd().
01354 { 01355 if (pos == 2) { 01356 return complete_confno(word, state); 01357 } 01358 if (pos == 3) { 01359 int len = strlen(word); 01360 char *ret = NULL; 01361 char *saved = NULL; 01362 char *myline; 01363 char *confno; 01364 struct ast_conference *cnf; 01365 01366 if (!strncasecmp(word, "all", len)) { 01367 if (state == 0) { 01368 return ast_strdup("all"); 01369 } 01370 --state; 01371 } 01372 01373 /* Extract the confno from the command line. */ 01374 myline = ast_strdupa(line); 01375 strtok_r(myline, " ", &saved); 01376 strtok_r(NULL, " ", &saved); 01377 confno = strtok_r(NULL, " ", &saved); 01378 01379 AST_LIST_LOCK(&confs); 01380 AST_LIST_TRAVERSE(&confs, cnf, list) { 01381 if (!strcmp(confno, cnf->confno)) { 01382 ret = complete_userno(cnf, word, state); 01383 break; 01384 } 01385 } 01386 AST_LIST_UNLOCK(&confs); 01387 01388 return ret; 01389 } 01390 return NULL; 01391 }
static char* complete_userno | ( | struct ast_conference * | cnf, | |
const char * | word, | |||
int | state | |||
) | [static] |
Definition at line 1331 of file app_meetme.c.
References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_ref, ast_strdup, len(), ast_conf_user::user_no, and ast_conference::usercontainer.
Referenced by complete_meetmecmd_mute_kick().
01332 { 01333 char usrno[50]; 01334 struct ao2_iterator iter; 01335 struct ast_conf_user *usr; 01336 char *ret = NULL; 01337 int which = 0; 01338 int len = strlen(word); 01339 01340 iter = ao2_iterator_init(cnf->usercontainer, 0); 01341 for (; (usr = ao2_iterator_next(&iter)); ao2_ref(usr, -1)) { 01342 snprintf(usrno, sizeof(usrno), "%d", usr->user_no); 01343 if (!strncmp(word, usrno, len) && ++which > state) { 01344 ao2_ref(usr, -1); 01345 ret = ast_strdup(usrno); 01346 break; 01347 } 01348 } 01349 ao2_iterator_destroy(&iter); 01350 return ret; 01351 }
static int conf_exec | ( | struct ast_channel * | chan, | |
const char * | data | |||
) | [static] |
The meetme() application.
Definition at line 4368 of file app_meetme.c.
References ast_channel::_state, ast_conference::adminopts, args, ARRAY_LEN, ast_answer(), AST_APP_ARG, ast_app_getdata(), ast_app_parse_options64(), ast_category_browse(), ast_config_destroy(), ast_config_load, ast_copy_string(), AST_DECLARE_APP_ARGS, AST_DIGIT_ANY, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_load_realtime_multientry(), ast_log(), ast_say_digits(), AST_STANDARD_APP_ARGS, AST_STATE_UP, ast_stopstream(), ast_strdupa, ast_streamfile(), ast_strlen_zero(), ast_test_flag64, ast_test_suite_event_notify, ast_variable_browse(), ast_variable_retrieve(), ast_verb, ast_waitstream(), conf_map, conf_run(), CONFFLAG_ADMIN, CONFFLAG_ALWAYSPROMPT, CONFFLAG_DYNAMIC, CONFFLAG_DYNAMICPIN, CONFFLAG_EMPTY, CONFFLAG_EMPTYNOPIN, CONFFLAG_QUIET, CONFIG_FILE_NAME, CONFIG_STATUS_FILEINVALID, ast_conference::confno, dispose_conf(), find_conf(), find_conf_realtime(), ast_conference::isdynamic, LOG_ERROR, LOG_WARNING, MAX_CONFNUM, MAX_PIN, MAX_SETTINGS, ast_variable::name, ast_variable::next, OPT_ARG_ARRAY_SIZE, parse(), ast_conference::pin, ast_conference::pinadmin, ast_conference::recordingfilename, ast_conference::recordingformat, SENTINEL, ast_conference::useropts, ast_conference::users, ast_variable::value, and var.
Referenced by load_module().
04369 { 04370 int res = -1; 04371 char confno[MAX_CONFNUM] = ""; 04372 int allowretry = 0; 04373 int retrycnt = 0; 04374 struct ast_conference *cnf = NULL; 04375 struct ast_flags64 confflags = {0}; 04376 struct ast_flags config_flags = { 0 }; 04377 int dynamic = 0; 04378 int empty = 0, empty_no_pin = 0; 04379 int always_prompt = 0; 04380 const char *notdata; 04381 char *info, the_pin[MAX_PIN] = ""; 04382 AST_DECLARE_APP_ARGS(args, 04383 AST_APP_ARG(confno); 04384 AST_APP_ARG(options); 04385 AST_APP_ARG(pin); 04386 ); 04387 char *optargs[OPT_ARG_ARRAY_SIZE] = { NULL, }; 04388 04389 if (ast_strlen_zero(data)) { 04390 allowretry = 1; 04391 notdata = ""; 04392 } else { 04393 notdata = data; 04394 } 04395 04396 if (chan->_state != AST_STATE_UP) 04397 ast_answer(chan); 04398 04399 info = ast_strdupa(notdata); 04400 04401 AST_STANDARD_APP_ARGS(args, info); 04402 04403 if (args.confno) { 04404 ast_copy_string(confno, args.confno, sizeof(confno)); 04405 if (ast_strlen_zero(confno)) { 04406 allowretry = 1; 04407 } 04408 } 04409 04410 if (args.pin) 04411 ast_copy_string(the_pin, args.pin, sizeof(the_pin)); 04412 04413 if (args.options) { 04414 ast_app_parse_options64(meetme_opts, &confflags, optargs, args.options); 04415 dynamic = ast_test_flag64(&confflags, CONFFLAG_DYNAMIC | CONFFLAG_DYNAMICPIN); 04416 if (ast_test_flag64(&confflags, CONFFLAG_DYNAMICPIN) && ast_strlen_zero(args.pin)) 04417 strcpy(the_pin, "q"); 04418 04419 empty = ast_test_flag64(&confflags, CONFFLAG_EMPTY | CONFFLAG_EMPTYNOPIN); 04420 empty_no_pin = ast_test_flag64(&confflags, CONFFLAG_EMPTYNOPIN); 04421 always_prompt = ast_test_flag64(&confflags, CONFFLAG_ALWAYSPROMPT | CONFFLAG_DYNAMICPIN); 04422 } 04423 04424 do { 04425 if (retrycnt > 3) 04426 allowretry = 0; 04427 if (empty) { 04428 int i; 04429 struct ast_config *cfg; 04430 struct ast_variable *var; 04431 int confno_int; 04432 04433 /* We only need to load the config file for static and empty_no_pin (otherwise we don't care) */ 04434 if ((empty_no_pin) || (!dynamic)) { 04435 cfg = ast_config_load(CONFIG_FILE_NAME, config_flags); 04436 if (cfg && cfg != CONFIG_STATUS_FILEINVALID) { 04437 var = ast_variable_browse(cfg, "rooms"); 04438 while (var) { 04439 char parse[MAX_SETTINGS], *stringp = parse, *confno_tmp; 04440 if (!strcasecmp(var->name, "conf")) { 04441 int found = 0; 04442 ast_copy_string(parse, var->value, sizeof(parse)); 04443 confno_tmp = strsep(&stringp, "|,"); 04444 if (!dynamic) { 04445 /* For static: run through the list and see if this conference is empty */ 04446 AST_LIST_LOCK(&confs); 04447 AST_LIST_TRAVERSE(&confs, cnf, list) { 04448 if (!strcmp(confno_tmp, cnf->confno)) { 04449 /* The conference exists, therefore it's not empty */ 04450 found = 1; 04451 break; 04452 } 04453 } 04454 AST_LIST_UNLOCK(&confs); 04455 cnf = NULL; 04456 if (!found) { 04457 /* At this point, we have a confno_tmp (static conference) that is empty */ 04458 if ((empty_no_pin && ast_strlen_zero(stringp)) || (!empty_no_pin)) { 04459 /* Case 1: empty_no_pin and pin is nonexistent (NULL) 04460 * Case 2: empty_no_pin and pin is blank (but not NULL) 04461 * Case 3: not empty_no_pin 04462 */ 04463 ast_copy_string(confno, confno_tmp, sizeof(confno)); 04464 break; 04465 } 04466 } 04467 } 04468 } 04469 var = var->next; 04470 } 04471 ast_config_destroy(cfg); 04472 } 04473 04474 if (ast_strlen_zero(confno) && (cfg = ast_load_realtime_multientry("meetme", "confno LIKE", "%", SENTINEL))) { 04475 const char *catg; 04476 for (catg = ast_category_browse(cfg, NULL); catg; catg = ast_category_browse(cfg, catg)) { 04477 const char *confno_tmp = ast_variable_retrieve(cfg, catg, "confno"); 04478 const char *pin_tmp = ast_variable_retrieve(cfg, catg, "pin"); 04479 if (ast_strlen_zero(confno_tmp)) { 04480 continue; 04481 } 04482 if (!dynamic) { 04483 int found = 0; 04484 /* For static: run through the list and see if this conference is empty */ 04485 AST_LIST_LOCK(&confs); 04486 AST_LIST_TRAVERSE(&confs, cnf, list) { 04487 if (!strcmp(confno_tmp, cnf->confno)) { 04488 /* The conference exists, therefore it's not empty */ 04489 found = 1; 04490 break; 04491 } 04492 } 04493 AST_LIST_UNLOCK(&confs); 04494 if (!found) { 04495 /* At this point, we have a confno_tmp (realtime conference) that is empty */ 04496 if ((empty_no_pin && ast_strlen_zero(pin_tmp)) || (!empty_no_pin)) { 04497 /* Case 1: empty_no_pin and pin is nonexistent (NULL) 04498 * Case 2: empty_no_pin and pin is blank (but not NULL) 04499 * Case 3: not empty_no_pin 04500 */ 04501 ast_copy_string(confno, confno_tmp, sizeof(confno)); 04502 break; 04503 } 04504 } 04505 } 04506 } 04507 ast_config_destroy(cfg); 04508 } 04509 } 04510 04511 /* Select first conference number not in use */ 04512 if (ast_strlen_zero(confno) && dynamic) { 04513 AST_LIST_LOCK(&confs); 04514 for (i = 0; i < ARRAY_LEN(conf_map); i++) { 04515 if (!conf_map[i]) { 04516 snprintf(confno, sizeof(confno), "%d", i); 04517 conf_map[i] = 1; 04518 break; 04519 } 04520 } 04521 AST_LIST_UNLOCK(&confs); 04522 } 04523 04524 /* Not found? */ 04525 if (ast_strlen_zero(confno)) { 04526 ast_test_suite_event_notify("PLAYBACK", "Message: conf-noempty"); 04527 res = ast_streamfile(chan, "conf-noempty", chan->language); 04528 if (!res) 04529 ast_waitstream(chan, ""); 04530 } else { 04531 if (sscanf(confno, "%30d", &confno_int) == 1) { 04532 if (!ast_test_flag64(&confflags, CONFFLAG_QUIET)) { 04533 res = ast_streamfile(chan, "conf-enteringno", chan->language); 04534 if (!res) { 04535 ast_waitstream(chan, ""); 04536 res = ast_say_digits(chan, confno_int, "", chan->language); 04537 } 04538 } 04539 } else { 04540 ast_log(LOG_ERROR, "Could not scan confno '%s'\n", confno); 04541 } 04542 } 04543 } 04544 04545 while (allowretry && (ast_strlen_zero(confno)) && (++retrycnt < 4)) { 04546 /* Prompt user for conference number */ 04547 res = ast_app_getdata(chan, "conf-getconfno", confno, sizeof(confno) - 1, 0); 04548 if (res < 0) { 04549 /* Don't try to validate when we catch an error */ 04550 confno[0] = '\0'; 04551 allowretry = 0; 04552 break; 04553 } 04554 } 04555 if (!ast_strlen_zero(confno)) { 04556 /* Check the validity of the conference */ 04557 cnf = find_conf(chan, confno, 1, dynamic, the_pin, 04558 sizeof(the_pin), 1, &confflags); 04559 if (!cnf) { 04560 int too_early = 0; 04561 04562 cnf = find_conf_realtime(chan, confno, 1, dynamic, 04563 the_pin, sizeof(the_pin), 1, &confflags, &too_early, optargs); 04564 if (rt_schedule && too_early) 04565 allowretry = 0; 04566 } 04567 04568 if (!cnf) { 04569 if (allowretry) { 04570 confno[0] = '\0'; 04571 res = ast_streamfile(chan, "conf-invalid", chan->language); 04572 if (!res) 04573 ast_waitstream(chan, ""); 04574 res = -1; 04575 } 04576 } else { 04577 /* Conference requires a pin for specified access level */ 04578 int req_pin = !ast_strlen_zero(cnf->pin) || 04579 (!ast_strlen_zero(cnf->pinadmin) && 04580 ast_test_flag64(&confflags, CONFFLAG_ADMIN)); 04581 /* The following logic was derived from a 04582 * 4 variable truth table and defines which 04583 * circumstances are not exempt from pin 04584 * checking. 04585 * If this needs to be modified, write the 04586 * truth table back out from the boolean 04587 * expression AB+A'D+C', change the erroneous 04588 * result, and rederive the expression. 04589 * Variables: 04590 * A: pin provided? 04591 * B: always prompt? 04592 * C: dynamic? 04593 * D: has users? */ 04594 int not_exempt = !cnf->isdynamic; 04595 not_exempt = not_exempt || (!ast_strlen_zero(args.pin) && ast_test_flag64(&confflags, CONFFLAG_ALWAYSPROMPT)); 04596 not_exempt = not_exempt || (ast_strlen_zero(args.pin) && cnf->users); 04597 if (req_pin && not_exempt) { 04598 char pin[MAX_PIN] = ""; 04599 int j; 04600 04601 /* Allow the pin to be retried up to 3 times */ 04602 for (j = 0; j < 3; j++) { 04603 if (*the_pin && (always_prompt == 0)) { 04604 ast_copy_string(pin, the_pin, sizeof(pin)); 04605 res = 0; 04606 } else { 04607 /* Prompt user for pin if pin is required */ 04608 ast_test_suite_event_notify("PLAYBACK", "Message: conf-getpin\r\n" 04609 "Channel: %s", 04610 chan->name); 04611 res = ast_app_getdata(chan, "conf-getpin", pin + strlen(pin), sizeof(pin) - 1 - strlen(pin), 0); 04612 } 04613 if (res >= 0) { 04614 if ((!strcasecmp(pin, cnf->pin) && 04615 (ast_strlen_zero(cnf->pinadmin) || 04616 !ast_test_flag64(&confflags, CONFFLAG_ADMIN))) || 04617 (!ast_strlen_zero(cnf->pinadmin) && 04618 !strcasecmp(pin, cnf->pinadmin))) { 04619 /* Pin correct */ 04620 allowretry = 0; 04621 if (!ast_strlen_zero(cnf->pinadmin) && !strcasecmp(pin, cnf->pinadmin)) { 04622 if (!ast_strlen_zero(cnf->adminopts)) { 04623 char *opts = ast_strdupa(cnf->adminopts); 04624 ast_app_parse_options64(meetme_opts, &confflags, optargs, opts); 04625 } 04626 } else { 04627 if (!ast_strlen_zero(cnf->useropts)) { 04628 char *opts = ast_strdupa(cnf->useropts); 04629 ast_app_parse_options64(meetme_opts, &confflags, optargs, opts); 04630 } 04631 } 04632 /* Run the conference */ 04633 ast_verb(4, "Starting recording of MeetMe Conference %s into file %s.%s.\n", cnf->confno, cnf->recordingfilename, cnf->recordingformat); 04634 res = conf_run(chan, cnf, &confflags, optargs); 04635 break; 04636 } else { 04637 /* Pin invalid */ 04638 if (!ast_streamfile(chan, "conf-invalidpin", chan->language)) { 04639 res = ast_waitstream(chan, AST_DIGIT_ANY); 04640 ast_stopstream(chan); 04641 } else { 04642 ast_log(LOG_WARNING, "Couldn't play invalid pin msg!\n"); 04643 break; 04644 } 04645 if (res < 0) 04646 break; 04647 pin[0] = res; 04648 pin[1] = '\0'; 04649 res = -1; 04650 if (allowretry) 04651 confno[0] = '\0'; 04652 } 04653 } else { 04654 /* failed when getting the pin */ 04655 res = -1; 04656 allowretry = 0; 04657 /* see if we need to get rid of the conference */ 04658 break; 04659 } 04660 04661 /* Don't retry pin with a static pin */ 04662 if (*the_pin && (always_prompt == 0)) { 04663 break; 04664 } 04665 } 04666 } else { 04667 /* No pin required */ 04668 allowretry = 0; 04669 04670 /* For RealTime conferences without a pin 04671 * should still support loading options 04672 */ 04673 if (!ast_strlen_zero(cnf->useropts)) { 04674 char *opts = ast_strdupa(cnf->useropts); 04675 ast_app_parse_options64(meetme_opts, &confflags, optargs, opts); 04676 } 04677 04678 /* Run the conference */ 04679 res = conf_run(chan, cnf, &confflags, optargs); 04680 } 04681 dispose_conf(cnf); 04682 cnf = NULL; 04683 } 04684 } 04685 } while (allowretry); 04686 04687 if (cnf) 04688 dispose_conf(cnf); 04689 04690 return res; 04691 }
static void conf_flush | ( | int | fd, | |
struct ast_channel * | chan | |||
) | [static] |
Definition at line 1870 of file app_meetme.c.
References ast_frfree, ast_log(), ast_read(), ast_waitfor(), f, and LOG_WARNING.
Referenced by conf_run().
01871 { 01872 int x; 01873 01874 /* read any frames that may be waiting on the channel 01875 and throw them away 01876 */ 01877 if (chan) { 01878 struct ast_frame *f; 01879 01880 /* when no frames are available, this will wait 01881 for 1 millisecond maximum 01882 */ 01883 while (ast_waitfor(chan, 1) > 0) { 01884 f = ast_read(chan); 01885 if (f) 01886 ast_frfree(f); 01887 else /* channel was hung up or something else happened */ 01888 break; 01889 } 01890 } 01891 01892 /* flush any data sitting in the pseudo channel */ 01893 x = DAHDI_FLUSH_ALL; 01894 if (ioctl(fd, DAHDI_FLUSH, &x)) 01895 ast_log(LOG_WARNING, "Error flushing channel\n"); 01896 01897 }
static int conf_free | ( | struct ast_conference * | conf | ) | [static] |
Remove the conference from the list and free it.
We assume that this was called while holding conflock.
Definition at line 1902 of file app_meetme.c.
References ao2_ref, ast_cond_signal, ast_filedelete(), AST_FRAME_BITS, ast_free, ast_frfree, ast_hangup(), AST_LIST_LOCK, AST_LIST_REMOVE, AST_LIST_REMOVE_HEAD, AST_LIST_UNLOCK, ast_mutex_destroy, ast_mutex_lock, ast_mutex_unlock, AST_PTHREADT_NULL, ast_softhangup(), AST_SOFTHANGUP_EXPLICIT, ast_translator_free_path(), ast_conference::chan, ast_conference::confno, EVENT_FLAG_CALL, ast_conference::fd, ast_conference::lchan, ast_conference::listenlock, manager_event, MEETME_RECORD_ACTIVE, MEETME_RECORD_OFF, MEETME_RECORD_TERMINATE, ast_conference::origframe, ast_conference::playlock, ast_conference::recordingfilename, ast_conference::recordingformat, ast_conference::recordthreadlock, ast_conference::transframe, ast_conference::transpath, and ast_conference::usercontainer.
Referenced by dispose_conf().
01903 { 01904 int x; 01905 struct announce_listitem *item; 01906 01907 AST_LIST_REMOVE(&confs, conf, list); 01908 manager_event(EVENT_FLAG_CALL, "MeetmeEnd", "Meetme: %s\r\n", conf->confno); 01909 01910 if (conf->recording == MEETME_RECORD_ACTIVE) { 01911 conf->recording = MEETME_RECORD_TERMINATE; 01912 AST_LIST_UNLOCK(&confs); 01913 while (1) { 01914 usleep(1); 01915 AST_LIST_LOCK(&confs); 01916 if (conf->recording == MEETME_RECORD_OFF) 01917 break; 01918 AST_LIST_UNLOCK(&confs); 01919 } 01920 } 01921 01922 for (x = 0; x < AST_FRAME_BITS; x++) { 01923 if (conf->transframe[x]) 01924 ast_frfree(conf->transframe[x]); 01925 if (conf->transpath[x]) 01926 ast_translator_free_path(conf->transpath[x]); 01927 } 01928 if (conf->announcethread != AST_PTHREADT_NULL) { 01929 ast_mutex_lock(&conf->announcelistlock); 01930 conf->announcethread_stop = 1; 01931 ast_softhangup(conf->chan, AST_SOFTHANGUP_EXPLICIT); 01932 ast_cond_signal(&conf->announcelist_addition); 01933 ast_mutex_unlock(&conf->announcelistlock); 01934 pthread_join(conf->announcethread, NULL); 01935 01936 while ((item = AST_LIST_REMOVE_HEAD(&conf->announcelist, entry))) { 01937 ast_filedelete(item->namerecloc, NULL); 01938 ao2_ref(item, -1); 01939 } 01940 ast_mutex_destroy(&conf->announcelistlock); 01941 } 01942 01943 if (conf->origframe) 01944 ast_frfree(conf->origframe); 01945 if (conf->lchan) 01946 ast_hangup(conf->lchan); 01947 if (conf->chan) 01948 ast_hangup(conf->chan); 01949 if (conf->fd >= 0) 01950 close(conf->fd); 01951 if (conf->recordingfilename) { 01952 ast_free(conf->recordingfilename); 01953 } 01954 if (conf->usercontainer) { 01955 ao2_ref(conf->usercontainer, -1); 01956 } 01957 if (conf->recordingformat) { 01958 ast_free(conf->recordingformat); 01959 } 01960 ast_mutex_destroy(&conf->playlock); 01961 ast_mutex_destroy(&conf->listenlock); 01962 ast_mutex_destroy(&conf->recordthreadlock); 01963 ast_mutex_destroy(&conf->announcethreadlock); 01964 ast_free(conf); 01965 01966 return 0; 01967 }
static void conf_play | ( | struct ast_channel * | chan, | |
struct ast_conference * | conf, | |||
enum entrance_sound | sound | |||
) | [static] |
Definition at line 1123 of file app_meetme.c.
References ast_autoservice_start(), ast_autoservice_stop(), ast_check_hangup(), AST_LIST_LOCK, AST_LIST_UNLOCK, ast_test_suite_event_notify, careful_write(), ast_conference::confno, enter, ENTER, ast_conference::fd, leave, LEAVE, len(), and ast_conference::markedusers.
Referenced by conf_run().
01124 { 01125 unsigned char *data; 01126 int len; 01127 int res = -1; 01128 01129 ast_test_suite_event_notify("CONFPLAY", "Channel: %s\r\n" 01130 "Conference: %s\r\n" 01131 "Marked: %d", 01132 chan->name, 01133 conf->confno, 01134 conf->markedusers); 01135 01136 if (!ast_check_hangup(chan)) 01137 res = ast_autoservice_start(chan); 01138 01139 AST_LIST_LOCK(&confs); 01140 01141 switch(sound) { 01142 case ENTER: 01143 data = enter; 01144 len = sizeof(enter); 01145 break; 01146 case LEAVE: 01147 data = leave; 01148 len = sizeof(leave); 01149 break; 01150 default: 01151 data = NULL; 01152 len = 0; 01153 } 01154 if (data) { 01155 careful_write(conf->fd, data, len, 1); 01156 } 01157 01158 AST_LIST_UNLOCK(&confs); 01159 01160 if (!res) 01161 ast_autoservice_stop(chan); 01162 }
static void conf_queue_dtmf | ( | const struct ast_conference * | conf, | |
const struct ast_conf_user * | sender, | |||
struct ast_frame * | f | |||
) | [static] |
Definition at line 1969 of file app_meetme.c.
References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_ref, ast_log(), ast_write(), ast_conf_user::chan, LOG_WARNING, and ast_conference::usercontainer.
Referenced by conf_run().
01971 { 01972 struct ast_conf_user *user; 01973 struct ao2_iterator user_iter; 01974 01975 user_iter = ao2_iterator_init(conf->usercontainer, 0); 01976 while ((user = ao2_iterator_next(&user_iter))) { 01977 if (user == sender) { 01978 ao2_ref(user, -1); 01979 continue; 01980 } 01981 if (ast_write(user->chan, f) < 0) 01982 ast_log(LOG_WARNING, "Error writing frame to channel %s\n", user->chan->name); 01983 ao2_ref(user, -1); 01984 } 01985 ao2_iterator_destroy(&user_iter); 01986 }
static int conf_run | ( | struct ast_channel * | chan, | |
struct ast_conference * | conf, | |||
struct ast_flags64 * | confflags, | |||
char * | optargs[] | |||
) | [static] |
Definition at line 2717 of file app_meetme.c.
References volume::actual, ADMINFLAG_KICKME, ADMINFLAG_MUTED, ADMINFLAG_SELFMUTED, ADMINFLAG_T_REQUEST, ast_conf_user::adminflags, announce_thread(), ao2_alloc, ao2_callback, ao2_link, ao2_lock, ao2_ref, ao2_unlink, ao2_unlock, ast_channel_lock, ast_channel_setoption(), ast_channel_unlock, ast_check_hangup(), ast_cond_signal, ast_config_AST_SPOOL_DIR, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_HOLD, ast_copy_string(), ast_debug, AST_DEVICE_INUSE, AST_DEVICE_NOT_INUSE, AST_DEVSTATE_CACHABLE, ast_devstate_changed(), AST_DEVSTATE_NOT_CACHABLE, AST_DIGIT_ANY, ast_dsp_free(), ast_dsp_get_threshold_from_settings(), ast_dsp_new(), ast_dsp_silence(), ast_exists_extension(), ast_filedelete(), 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_free, ast_frfree, AST_FRIENDLY_OFFSET, ast_func_write(), ast_goto_if_exists(), ast_hangup(), ast_indicate(), AST_LIST_HEAD_INIT_NOLOCK, AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_NEXT, AST_LIST_UNLOCK, ast_load_realtime(), ast_localtime(), ast_log(), ast_manager_event, AST_MAX_CONTEXT, AST_MAX_EXTENSION, ast_mkdir(), ast_mktime(), ast_module_helper(), ast_moh_stop(), ast_mutex_init, ast_mutex_lock, ast_mutex_unlock, ast_null_frame, AST_OPTION_TONE_VERIFY, ast_play_and_record(), ast_pthread_create_background, ast_pthread_create_detached_background, AST_PTHREADT_NULL, ast_read(), ast_read_noaudio(), ast_realtime_require_field(), ast_record_review(), ast_request(), ast_safe_sleep(), ast_samp2tv(), ast_say_digits(), ast_say_number(), ast_set_read_format(), ast_set_write_format(), ast_stopstream(), ast_strdup, ast_strdupa, ast_streamfile(), ast_strftime(), ast_strlen_zero(), ast_strptime(), ast_test_flag64, ast_test_suite_event_notify, ast_translate(), ast_translator_build_path(), ast_tvadd(), ast_tvdiff_ms(), ast_tvnow(), ast_tvsub(), ast_tvzero(), ast_update_realtime(), ast_variables_destroy(), ast_verb, ast_verbose, ast_waitfor_nandfds(), ast_waitstream(), ast_write(), ast_channel::audiohooks, ast_conference::bookid, ast_channel::caller, can_write(), careful_write(), ast_conference::chan, ast_conf_user::chan, ast_frame_subclass::codec, conf_flush(), CONF_HASJOIN, CONF_HASLEFT, conf_play(), conf_queue_dtmf(), CONF_SIZE, conf_start_moh(), CONFFLAG_ADMIN, CONFFLAG_AGI, CONFFLAG_ANNOUNCEUSERCOUNT, CONFFLAG_DONT_DENOISE, CONFFLAG_DURATION_LIMIT, CONFFLAG_DURATION_STOP, CONFFLAG_EXIT_CONTEXT, CONFFLAG_INTROMSG, CONFFLAG_INTROUSER, CONFFLAG_INTROUSERNOREVIEW, CONFFLAG_KEYEXIT, CONFFLAG_KICK_CONTINUE, CONFFLAG_MARKEDEXIT, CONFFLAG_MARKEDUSER, CONFFLAG_MOH, CONFFLAG_MONITOR, CONFFLAG_MONITORTALKER, CONFFLAG_NO_AUDIO_UNTIL_UP, CONFFLAG_NOONLYPERSON, CONFFLAG_OPTIMIZETALKER, CONFFLAG_PASS_DTMF, CONFFLAG_QUIET, CONFFLAG_RECORDCONF, CONFFLAG_SLA_STATION, CONFFLAG_STARMENU, CONFFLAG_STARTMUTED, CONFFLAG_TALKER, CONFFLAG_WAITMARKED, ast_conference::confno, ast_channel::connected, ast_channel::context, ast_conf_user::dahdichannel, ast_conference::dahdiconf, ast_frame::data, ast_frame::datalen, DATE_FORMAT, volume::desired, dtmfstr, ast_conf_user::end_sound, ast_conference::endalert, ast_conference::endtime, ENTER, errno, EVENT_FLAG_CALL, exitcontext, f, ast_conference::fd, ast_channel::fds, ast_frame::frametype, ast_conference::gmuted, ast_party_connected_line::id, ast_party_caller::id, ast_frame_subclass::integer, ast_conference::isdynamic, ast_conf_user::jointime, ast_conf_user::kicktime, ast_conference::lchan, LEAVE, ast_conf_user::listen, ast_conference::listenlock, ast_conference::locked, LOG_WARNING, ast_channel::macrocontext, ast_conference::markedusers, ast_conference::maxusers, MEETME_DELAYDETECTENDTALK, MEETME_DELAYDETECTTALK, meetme_menu(), MENU_ADMIN, MENU_DISABLED, MENU_NORMAL, ast_channel::monitor, ast_variable::name, ast_party_id::name, ast_conf_user::namerecloc, ast_variable::next, ast_party_id::number, OBJ_NODATA, ast_frame::offset, OPT_ARG_DURATION_LIMIT, OPT_ARG_DURATION_STOP, OPT_ARG_EXITKEYS, OPT_ARG_INTROMSG, OPT_ARG_MOH_CLASS, OPT_ARG_WAITMARKED, ast_conference::origframe, parse(), pbx_builtin_getvar_helper(), pbx_builtin_setvar_helper(), pbx_exec(), pbx_findapp(), ast_conf_user::play_warning, ast_conference::playlock, ast_frame::ptr, ast_channel::rawwriteformat, ast_conference::recordingfilename, ast_conference::recordingformat, ast_conference::recordthread, ast_conference::recordthreadlock, reset_volumes(), RQ_UINTEGER1, RQ_UINTEGER2, RQ_UINTEGER3, RQ_UINTEGER4, S_COR, ast_frame::samples, set_talk_volume(), set_user_talking(), SLA_EVENT_HOLD, sla_queue_event_conf(), ast_conf_user::start_time, ast_party_name::str, ast_party_number::str, ast_frame::subclass, ast_conf_user::talk, ast_conf_user::talking, ast_channel::tech, THRESHOLD_SILENCE, ast_conf_user::timelimit, ast_conference::transframe, ast_conference::transpath, ast_channel_tech::type, ast_conference::uniqueid, user_max_cmp(), ast_conf_user::user_no, ast_conference::usercontainer, ast_conf_user::userflags, ast_conference::users, ast_party_name::valid, ast_party_number::valid, ast_variable::value, var, ast_conf_user::warning_freq, and ast_conf_user::warning_sound.
Referenced by conf_exec(), dial_trunk(), run_station(), sla_station_exec(), and sla_trunk_exec().
02718 { 02719 struct ast_conf_user *user = NULL; 02720 int fd; 02721 struct dahdi_confinfo dahdic, dahdic_empty; 02722 struct ast_frame *f; 02723 struct ast_channel *c; 02724 struct ast_frame fr; 02725 int outfd; 02726 int ms; 02727 int nfds; 02728 int res; 02729 int retrydahdi; 02730 int origfd; 02731 int musiconhold = 0, mohtempstopped = 0; 02732 int firstpass = 0; 02733 int lastmarked = 0; 02734 int currentmarked = 0; 02735 int ret = -1; 02736 int x; 02737 enum menu_modes menu_mode = MENU_DISABLED; 02738 int talkreq_manager = 0; 02739 int using_pseudo = 0; 02740 int duration = 20; 02741 int sent_event = 0; 02742 int checked = 0; 02743 int announcement_played = 0; 02744 struct timeval now; 02745 struct ast_dsp *dsp = NULL; 02746 struct ast_app *agi_app; 02747 char *agifile, *mod_speex; 02748 const char *agifiledefault = "conf-background.agi", *tmpvar; 02749 char meetmesecs[30] = ""; 02750 char exitcontext[AST_MAX_CONTEXT] = ""; 02751 char recordingtmp[AST_MAX_EXTENSION] = ""; 02752 char members[10] = ""; 02753 int dtmf = 0, opt_waitmarked_timeout = 0; 02754 time_t timeout = 0; 02755 struct dahdi_bufferinfo bi; 02756 char __buf[CONF_SIZE + AST_FRIENDLY_OFFSET]; 02757 char *buf = __buf + AST_FRIENDLY_OFFSET; 02758 char *exitkeys = NULL; 02759 unsigned int calldurationlimit = 0; 02760 long timelimit = 0; 02761 long play_warning = 0; 02762 long warning_freq = 0; 02763 const char *warning_sound = NULL; 02764 const char *end_sound = NULL; 02765 char *parse; 02766 long time_left_ms = 0; 02767 struct timeval nexteventts = { 0, }; 02768 int to; 02769 int setusercount = 0; 02770 int confsilence = 0, totalsilence = 0; 02771 02772 if (!(user = ao2_alloc(sizeof(*user), NULL))) { 02773 return ret; 02774 } 02775 02776 /* Possible timeout waiting for marked user */ 02777 if (ast_test_flag64(confflags, CONFFLAG_WAITMARKED) && 02778 !ast_strlen_zero(optargs[OPT_ARG_WAITMARKED]) && 02779 (sscanf(optargs[OPT_ARG_WAITMARKED], "%30d", &opt_waitmarked_timeout) == 1) && 02780 (opt_waitmarked_timeout > 0)) { 02781 timeout = time(NULL) + opt_waitmarked_timeout; 02782 } 02783 02784 if (ast_test_flag64(confflags, CONFFLAG_DURATION_STOP) && !ast_strlen_zero(optargs[OPT_ARG_DURATION_STOP])) { 02785 calldurationlimit = atoi(optargs[OPT_ARG_DURATION_STOP]); 02786 ast_verb(3, "Setting call duration limit to %d seconds.\n", calldurationlimit); 02787 } 02788 02789 if (ast_test_flag64(confflags, CONFFLAG_DURATION_LIMIT) && !ast_strlen_zero(optargs[OPT_ARG_DURATION_LIMIT])) { 02790 char *limit_str, *warning_str, *warnfreq_str; 02791 const char *var; 02792 02793 parse = optargs[OPT_ARG_DURATION_LIMIT]; 02794 limit_str = strsep(&parse, ":"); 02795 warning_str = strsep(&parse, ":"); 02796 warnfreq_str = parse; 02797 02798 timelimit = atol(limit_str); 02799 if (warning_str) 02800 play_warning = atol(warning_str); 02801 if (warnfreq_str) 02802 warning_freq = atol(warnfreq_str); 02803 02804 if (!timelimit) { 02805 timelimit = play_warning = warning_freq = 0; 02806 warning_sound = NULL; 02807 } else if (play_warning > timelimit) { 02808 if (!warning_freq) { 02809 play_warning = 0; 02810 } else { 02811 while (play_warning > timelimit) 02812 play_warning -= warning_freq; 02813 if (play_warning < 1) 02814 play_warning = warning_freq = 0; 02815 } 02816 } 02817 02818 ast_verb(3, "Setting conference duration limit to: %ldms.\n", timelimit); 02819 if (play_warning) { 02820 ast_verb(3, "Setting warning time to %ldms from the conference duration limit.\n", play_warning); 02821 } 02822 if (warning_freq) { 02823 ast_verb(3, "Setting warning frequency to %ldms.\n", warning_freq); 02824 } 02825 02826 ast_channel_lock(chan); 02827 if ((var = pbx_builtin_getvar_helper(chan, "CONF_LIMIT_WARNING_FILE"))) { 02828 var = ast_strdupa(var); 02829 } 02830 ast_channel_unlock(chan); 02831 02832 warning_sound = var ? var : "timeleft"; 02833 02834 ast_channel_lock(chan); 02835 if ((var = pbx_builtin_getvar_helper(chan, "CONF_LIMIT_TIMEOUT_FILE"))) { 02836 var = ast_strdupa(var); 02837 } 02838 ast_channel_unlock(chan); 02839 02840 end_sound = var ? var : NULL; 02841 02842 /* undo effect of S(x) in case they are both used */ 02843 calldurationlimit = 0; 02844 /* more efficient do it like S(x) does since no advanced opts */ 02845 if (!play_warning && !end_sound && timelimit) { 02846 calldurationlimit = timelimit / 1000; 02847 timelimit = play_warning = warning_freq = 0; 02848 } else { 02849 ast_debug(2, "Limit Data for this call:\n"); 02850 ast_debug(2, "- timelimit = %ld\n", timelimit); 02851 ast_debug(2, "- play_warning = %ld\n", play_warning); 02852 ast_debug(2, "- warning_freq = %ld\n", warning_freq); 02853 ast_debug(2, "- warning_sound = %s\n", warning_sound ? warning_sound : "UNDEF"); 02854 ast_debug(2, "- end_sound = %s\n", end_sound ? end_sound : "UNDEF"); 02855 } 02856 } 02857 02858 /* Get exit keys */ 02859 if (ast_test_flag64(confflags, CONFFLAG_KEYEXIT)) { 02860 if (!ast_strlen_zero(optargs[OPT_ARG_EXITKEYS])) 02861 exitkeys = ast_strdupa(optargs[OPT_ARG_EXITKEYS]); 02862 else 02863 exitkeys = ast_strdupa("#"); /* Default */ 02864 } 02865 02866 if (ast_test_flag64(confflags, CONFFLAG_RECORDCONF)) { 02867 if (!conf->recordingfilename) { 02868 const char *var; 02869 ast_channel_lock(chan); 02870 if ((var = pbx_builtin_getvar_helper(chan, "MEETME_RECORDINGFILE"))) { 02871 conf->recordingfilename = ast_strdup(var); 02872 } 02873 if ((var = pbx_builtin_getvar_helper(chan, "MEETME_RECORDINGFORMAT"))) { 02874 conf->recordingformat = ast_strdup(var); 02875 } 02876 ast_channel_unlock(chan); 02877 if (!conf->recordingfilename) { 02878 snprintf(recordingtmp, sizeof(recordingtmp), "meetme-conf-rec-%s-%s", conf->confno, chan->uniqueid); 02879 conf->recordingfilename = ast_strdup(recordingtmp); 02880 } 02881 if (!conf->recordingformat) { 02882 conf->recordingformat = ast_strdup("wav"); 02883 } 02884 ast_verb(4, "Starting recording of MeetMe Conference %s into file %s.%s.\n", 02885 conf->confno, conf->recordingfilename, conf->recordingformat); 02886 } 02887 } 02888 02889 ast_mutex_lock(&conf->recordthreadlock); 02890 if ((conf->recordthread == AST_PTHREADT_NULL) && ast_test_flag64(confflags, CONFFLAG_RECORDCONF) && 02891 ((conf->lchan = ast_request("DAHDI", AST_FORMAT_SLINEAR, chan, "pseudo", NULL)))) { 02892 ast_set_read_format(conf->lchan, AST_FORMAT_SLINEAR); 02893 ast_set_write_format(conf->lchan, AST_FORMAT_SLINEAR); 02894 dahdic.chan = 0; 02895 dahdic.confno = conf->dahdiconf; 02896 dahdic.confmode = DAHDI_CONF_CONFANN | DAHDI_CONF_CONFANNMON; 02897 if (ioctl(conf->lchan->fds[0], DAHDI_SETCONF, &dahdic)) { 02898 ast_log(LOG_WARNING, "Error starting listen channel\n"); 02899 ast_hangup(conf->lchan); 02900 conf->lchan = NULL; 02901 } else { 02902 ast_pthread_create_detached_background(&conf->recordthread, NULL, recordthread, conf); 02903 } 02904 } 02905 ast_mutex_unlock(&conf->recordthreadlock); 02906 02907 ast_mutex_lock(&conf->announcethreadlock); 02908 if ((conf->announcethread == AST_PTHREADT_NULL) && !ast_test_flag64(confflags, CONFFLAG_QUIET) && 02909 (ast_test_flag64(confflags, CONFFLAG_INTROUSER) || ast_test_flag64(confflags, CONFFLAG_INTROUSERNOREVIEW))) { 02910 ast_mutex_init(&conf->announcelistlock); 02911 AST_LIST_HEAD_INIT_NOLOCK(&conf->announcelist); 02912 ast_pthread_create_background(&conf->announcethread, NULL, announce_thread, conf); 02913 } 02914 ast_mutex_unlock(&conf->announcethreadlock); 02915 02916 time(&user->jointime); 02917 02918 user->timelimit = timelimit; 02919 user->play_warning = play_warning; 02920 user->warning_freq = warning_freq; 02921 user->warning_sound = warning_sound; 02922 user->end_sound = end_sound; 02923 02924 if (calldurationlimit > 0) { 02925 time(&user->kicktime); 02926 user->kicktime = user->kicktime + calldurationlimit; 02927 } 02928 02929 if (ast_tvzero(user->start_time)) 02930 user->start_time = ast_tvnow(); 02931 time_left_ms = user->timelimit; 02932 02933 if (user->timelimit) { 02934 nexteventts = ast_tvadd(user->start_time, ast_samp2tv(user->timelimit, 1000)); 02935 nexteventts = ast_tvsub(nexteventts, ast_samp2tv(user->play_warning, 1000)); 02936 } 02937 02938 if (conf->locked && (!ast_test_flag64(confflags, CONFFLAG_ADMIN))) { 02939 /* Sorry, but this conference is locked! */ 02940 if (!ast_streamfile(chan, "conf-locked", chan->language)) 02941 ast_waitstream(chan, ""); 02942 goto outrun; 02943 } 02944 02945 ast_mutex_lock(&conf->playlock); 02946 02947 if (rt_schedule && conf->maxusers) { 02948 if (conf->users >= conf->maxusers) { 02949 /* Sorry, but this confernce has reached the participant limit! */ 02950 if (!ast_streamfile(chan, "conf-full", chan->language)) 02951 ast_waitstream(chan, ""); 02952 ast_mutex_unlock(&conf->playlock); 02953 goto outrun; 02954 } 02955 } 02956 02957 ao2_lock(conf->usercontainer); 02958 ao2_callback(conf->usercontainer, OBJ_NODATA, user_max_cmp, &user->user_no); 02959 user->user_no++; 02960 ao2_link(conf->usercontainer, user); 02961 ao2_unlock(conf->usercontainer); 02962 02963 user->chan = chan; 02964 user->userflags = *confflags; 02965 user->adminflags = ast_test_flag64(confflags, CONFFLAG_STARTMUTED) ? ADMINFLAG_SELFMUTED : 0; 02966 user->adminflags |= (conf->gmuted) ? ADMINFLAG_MUTED : 0; 02967 user->talking = -1; 02968 02969 ast_mutex_unlock(&conf->playlock); 02970 02971 if (!ast_test_flag64(confflags, CONFFLAG_QUIET) && (ast_test_flag64(confflags, CONFFLAG_INTROUSER) || 02972 ast_test_flag64(confflags, CONFFLAG_INTROUSERNOREVIEW))) { 02973 char destdir[PATH_MAX]; 02974 02975 snprintf(destdir, sizeof(destdir), "%s/meetme", ast_config_AST_SPOOL_DIR); 02976 02977 if (ast_mkdir(destdir, 0777) != 0) { 02978 ast_log(LOG_WARNING, "mkdir '%s' failed: %s\n", destdir, strerror(errno)); 02979 goto outrun; 02980 } 02981 02982 snprintf(user->namerecloc, sizeof(user->namerecloc), 02983 "%s/meetme-username-%s-%d", destdir, 02984 conf->confno, user->user_no); 02985 if (ast_test_flag64(confflags, CONFFLAG_INTROUSERNOREVIEW)) 02986 res = ast_play_and_record(chan, "vm-rec-name", user->namerecloc, 10, "sln", &duration, NULL, ast_dsp_get_threshold_from_settings(THRESHOLD_SILENCE), 0, NULL); 02987 else 02988 res = ast_record_review(chan, "vm-rec-name", user->namerecloc, 10, "sln", &duration, NULL); 02989 if (res == -1) 02990 goto outrun; 02991 } 02992 02993 ast_mutex_lock(&conf->playlock); 02994 02995 if (ast_test_flag64(confflags, CONFFLAG_MARKEDUSER)) 02996 conf->markedusers++; 02997 conf->users++; 02998 if (rt_log_members) { 02999 /* Update table */ 03000 snprintf(members, sizeof(members), "%d", conf->users); 03001 ast_realtime_require_field("meetme", 03002 "confno", strlen(conf->confno) > 7 ? RQ_UINTEGER4 : strlen(conf->confno) > 4 ? RQ_UINTEGER3 : RQ_UINTEGER2, strlen(conf->confno), 03003 "members", RQ_UINTEGER1, strlen(members), 03004 NULL); 03005 ast_update_realtime("meetme", "confno", conf->confno, "members", members, NULL); 03006 } 03007 setusercount = 1; 03008 03009 /* This device changed state now - if this is the first user */ 03010 if (conf->users == 1) 03011 ast_devstate_changed(AST_DEVICE_INUSE, (conf->isdynamic ? AST_DEVSTATE_NOT_CACHABLE : AST_DEVSTATE_CACHABLE), "meetme:%s", conf->confno); 03012 03013 ast_mutex_unlock(&conf->playlock); 03014 03015 /* return the unique ID of the conference */ 03016 pbx_builtin_setvar_helper(chan, "MEETMEUNIQUEID", conf->uniqueid); 03017 03018 if (ast_test_flag64(confflags, CONFFLAG_EXIT_CONTEXT)) { 03019 ast_channel_lock(chan); 03020 if ((tmpvar = pbx_builtin_getvar_helper(chan, "MEETME_EXIT_CONTEXT"))) { 03021 ast_copy_string(exitcontext, tmpvar, sizeof(exitcontext)); 03022 } else if (!ast_strlen_zero(chan->macrocontext)) { 03023 ast_copy_string(exitcontext, chan->macrocontext, sizeof(exitcontext)); 03024 } else { 03025 ast_copy_string(exitcontext, chan->context, sizeof(exitcontext)); 03026 } 03027 ast_channel_unlock(chan); 03028 } 03029 03030 /* Play an arbitrary intro message */ 03031 if (ast_test_flag64(confflags, CONFFLAG_INTROMSG) && 03032 !ast_strlen_zero(optargs[OPT_ARG_INTROMSG])) { 03033 if (!ast_streamfile(chan, optargs[OPT_ARG_INTROMSG], chan->language)) { 03034 ast_waitstream(chan, ""); 03035 } 03036 } 03037 03038 if (!ast_test_flag64(confflags, (CONFFLAG_QUIET | CONFFLAG_NOONLYPERSON))) { 03039 if (conf->users == 1 && !ast_test_flag64(confflags, CONFFLAG_WAITMARKED)) 03040 if (!ast_streamfile(chan, "conf-onlyperson", chan->language)) 03041 ast_waitstream(chan, ""); 03042 if (ast_test_flag64(confflags, CONFFLAG_WAITMARKED) && conf->markedusers == 0) 03043 if (!ast_streamfile(chan, "conf-waitforleader", chan->language)) 03044 ast_waitstream(chan, ""); 03045 } 03046 03047 if (!ast_test_flag64(confflags, CONFFLAG_QUIET) && ast_test_flag64(confflags, CONFFLAG_ANNOUNCEUSERCOUNT) && 03048 conf->users > 1) { 03049 int keepplaying = 1; 03050 03051 if (conf->users == 2) { 03052 if (!ast_streamfile(chan, "conf-onlyone", chan->language)) { 03053 res = ast_waitstream(chan, AST_DIGIT_ANY); 03054 ast_stopstream(chan); 03055 if (res > 0) 03056 keepplaying = 0; 03057 else if (res == -1) 03058 goto outrun; 03059 } 03060 } else { 03061 if (!ast_streamfile(chan, "conf-thereare", chan->language)) { 03062 res = ast_waitstream(chan, AST_DIGIT_ANY); 03063 ast_stopstream(chan); 03064 if (res > 0) 03065 keepplaying = 0; 03066 else if (res == -1) 03067 goto outrun; 03068 } 03069 if (keepplaying) { 03070 res = ast_say_number(chan, conf->users - 1, AST_DIGIT_ANY, chan->language, (char *) NULL); 03071 if (res > 0) 03072 keepplaying = 0; 03073 else if (res == -1) 03074 goto outrun; 03075 } 03076 if (keepplaying && !ast_streamfile(chan, "conf-otherinparty", chan->language)) { 03077 res = ast_waitstream(chan, AST_DIGIT_ANY); 03078 ast_stopstream(chan); 03079 if (res > 0) 03080 keepplaying = 0; 03081 else if (res == -1) 03082 goto outrun; 03083 } 03084 } 03085 } 03086 03087 if (!ast_test_flag64(confflags, CONFFLAG_NO_AUDIO_UNTIL_UP)) { 03088 /* We're leaving this alone until the state gets changed to up */ 03089 ast_indicate(chan, -1); 03090 } 03091 03092 if (ast_set_write_format(chan, AST_FORMAT_SLINEAR) < 0) { 03093 ast_log(LOG_WARNING, "Unable to set '%s' to write linear mode\n", chan->name); 03094 goto outrun; 03095 } 03096 03097 if (ast_set_read_format(chan, AST_FORMAT_SLINEAR) < 0) { 03098 ast_log(LOG_WARNING, "Unable to set '%s' to read linear mode\n", chan->name); 03099 goto outrun; 03100 } 03101 03102 /* Reduce background noise from each participant */ 03103 if (!ast_test_flag64(confflags, CONFFLAG_DONT_DENOISE) && 03104 (mod_speex = ast_module_helper("", "func_speex", 0, 0, 0, 0))) { 03105 ast_free(mod_speex); 03106 ast_func_write(chan, "DENOISE(rx)", "on"); 03107 } 03108 03109 retrydahdi = (strcasecmp(chan->tech->type, "DAHDI") || (chan->audiohooks || chan->monitor) ? 1 : 0); 03110 user->dahdichannel = !retrydahdi; 03111 03112 dahdiretry: 03113 origfd = chan->fds[0]; 03114 if (retrydahdi) { 03115 /* open pseudo in non-blocking mode */ 03116 fd = open("/dev/dahdi/pseudo", O_RDWR | O_NONBLOCK); 03117 if (fd < 0) { 03118 ast_log(LOG_WARNING, "Unable to open DAHDI pseudo channel: %s\n", strerror(errno)); 03119 goto outrun; 03120 } 03121 using_pseudo = 1; 03122 /* Setup buffering information */ 03123 memset(&bi, 0, sizeof(bi)); 03124 bi.bufsize = CONF_SIZE / 2; 03125 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE; 03126 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE; 03127 bi.numbufs = audio_buffers; 03128 if (ioctl(fd, DAHDI_SET_BUFINFO, &bi)) { 03129 ast_log(LOG_WARNING, "Unable to set buffering information: %s\n", strerror(errno)); 03130 close(fd); 03131 goto outrun; 03132 } 03133 x = 1; 03134 if (ioctl(fd, DAHDI_SETLINEAR, &x)) { 03135 ast_log(LOG_WARNING, "Unable to set linear mode: %s\n", strerror(errno)); 03136 close(fd); 03137 goto outrun; 03138 } 03139 nfds = 1; 03140 } else { 03141 /* XXX Make sure we're not running on a pseudo channel XXX */ 03142 fd = chan->fds[0]; 03143 nfds = 0; 03144 } 03145 memset(&dahdic, 0, sizeof(dahdic)); 03146 memset(&dahdic_empty, 0, sizeof(dahdic_empty)); 03147 /* Check to see if we're in a conference... */ 03148 dahdic.chan = 0; 03149 if (ioctl(fd, DAHDI_GETCONF, &dahdic)) { 03150 ast_log(LOG_WARNING, "Error getting conference\n"); 03151 close(fd); 03152 goto outrun; 03153 } 03154 if (dahdic.confmode) { 03155 /* Whoa, already in a conference... Retry... */ 03156 if (!retrydahdi) { 03157 ast_debug(1, "DAHDI channel is in a conference already, retrying with pseudo\n"); 03158 retrydahdi = 1; 03159 goto dahdiretry; 03160 } 03161 } 03162 memset(&dahdic, 0, sizeof(dahdic)); 03163 /* Add us to the conference */ 03164 dahdic.chan = 0; 03165 dahdic.confno = conf->dahdiconf; 03166 03167 if (!ast_test_flag64(confflags, CONFFLAG_QUIET) && (ast_test_flag64(confflags, CONFFLAG_INTROUSER) || 03168 ast_test_flag64(confflags, CONFFLAG_INTROUSERNOREVIEW)) && conf->users > 1) { 03169 struct announce_listitem *item; 03170 if (!(item = ao2_alloc(sizeof(*item), NULL))) 03171 goto outrun; 03172 ast_copy_string(item->namerecloc, user->namerecloc, sizeof(item->namerecloc)); 03173 ast_copy_string(item->language, chan->language, sizeof(item->language)); 03174 item->confchan = conf->chan; 03175 item->confusers = conf->users; 03176 item->announcetype = CONF_HASJOIN; 03177 ast_mutex_lock(&conf->announcelistlock); 03178 ao2_ref(item, +1); /* add one more so we can determine when announce_thread is done playing it */ 03179 AST_LIST_INSERT_TAIL(&conf->announcelist, item, entry); 03180 ast_cond_signal(&conf->announcelist_addition); 03181 ast_mutex_unlock(&conf->announcelistlock); 03182 03183 while (!ast_check_hangup(conf->chan) && ao2_ref(item, 0) == 2 && !ast_safe_sleep(chan, 1000)) { 03184 ; 03185 } 03186 ao2_ref(item, -1); 03187 } 03188 03189 if (ast_test_flag64(confflags, CONFFLAG_WAITMARKED) && !conf->markedusers) 03190 dahdic.confmode = DAHDI_CONF_CONF; 03191 else if (ast_test_flag64(confflags, CONFFLAG_MONITOR)) 03192 dahdic.confmode = DAHDI_CONF_CONFMON | DAHDI_CONF_LISTENER; 03193 else if (ast_test_flag64(confflags, CONFFLAG_TALKER)) 03194 dahdic.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER; 03195 else 03196 dahdic.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER; 03197 03198 if (ioctl(fd, DAHDI_SETCONF, &dahdic)) { 03199 ast_log(LOG_WARNING, "Error setting conference\n"); 03200 close(fd); 03201 goto outrun; 03202 } 03203 ast_debug(1, "Placed channel %s in DAHDI conf %d\n", chan->name, conf->dahdiconf); 03204 03205 if (!sent_event) { 03206 ast_manager_event(chan, EVENT_FLAG_CALL, "MeetmeJoin", 03207 "Channel: %s\r\n" 03208 "Uniqueid: %s\r\n" 03209 "Meetme: %s\r\n" 03210 "Usernum: %d\r\n" 03211 "CallerIDnum: %s\r\n" 03212 "CallerIDname: %s\r\n" 03213 "ConnectedLineNum: %s\r\n" 03214 "ConnectedLineName: %s\r\n", 03215 chan->name, chan->uniqueid, conf->confno, 03216 user->user_no, 03217 S_COR(user->chan->caller.id.number.valid, user->chan->caller.id.number.str, "<unknown>"), 03218 S_COR(user->chan->caller.id.name.valid, user->chan->caller.id.name.str, "<unknown>"), 03219 S_COR(user->chan->connected.id.number.valid, user->chan->connected.id.number.str, "<unknown>"), 03220 S_COR(user->chan->connected.id.name.valid, user->chan->connected.id.name.str, "<unknown>") 03221 ); 03222 sent_event = 1; 03223 } 03224 03225 if (!firstpass && !ast_test_flag64(confflags, CONFFLAG_MONITOR) && 03226 !ast_test_flag64(confflags, CONFFLAG_ADMIN)) { 03227 firstpass = 1; 03228 if (!ast_test_flag64(confflags, CONFFLAG_QUIET)) 03229 if (!ast_test_flag64(confflags, CONFFLAG_WAITMARKED) || (ast_test_flag64(confflags, CONFFLAG_MARKEDUSER) && 03230 (conf->markedusers >= 1))) { 03231 conf_play(chan, conf, ENTER); 03232 } 03233 } 03234 03235 conf_flush(fd, chan); 03236 03237 if (dsp) 03238 ast_dsp_free(dsp); 03239 03240 if (!(dsp = ast_dsp_new())) { 03241 ast_log(LOG_WARNING, "Unable to allocate DSP!\n"); 03242 res = -1; 03243 } 03244 03245 if (ast_test_flag64(confflags, CONFFLAG_AGI)) { 03246 /* Get name of AGI file to run from $(MEETME_AGI_BACKGROUND) 03247 or use default filename of conf-background.agi */ 03248 03249 ast_channel_lock(chan); 03250 if ((tmpvar = pbx_builtin_getvar_helper(chan, "MEETME_AGI_BACKGROUND"))) { 03251 agifile = ast_strdupa(tmpvar); 03252 } else { 03253 agifile = ast_strdupa(agifiledefault); 03254 } 03255 ast_channel_unlock(chan); 03256 03257 if (user->dahdichannel) { 03258 /* Set CONFMUTE mode on DAHDI channel to mute DTMF tones */ 03259 x = 1; 03260 ast_channel_setoption(chan, AST_OPTION_TONE_VERIFY, &x, sizeof(char), 0); 03261 } 03262 /* Find a pointer to the agi app and execute the script */ 03263 agi_app = pbx_findapp("agi"); 03264 if (agi_app) { 03265 ret = pbx_exec(chan, agi_app, agifile); 03266 } else { 03267 ast_log(LOG_WARNING, "Could not find application (agi)\n"); 03268 ret = -2; 03269 } 03270 if (user->dahdichannel) { 03271 /* Remove CONFMUTE mode on DAHDI channel */ 03272 x = 0; 03273 ast_channel_setoption(chan, AST_OPTION_TONE_VERIFY, &x, sizeof(char), 0); 03274 } 03275 } else { 03276 int lastusers = conf->users; 03277 if (user->dahdichannel && ast_test_flag64(confflags, CONFFLAG_STARMENU)) { 03278 /* Set CONFMUTE mode on DAHDI channel to mute DTMF tones when the menu is enabled */ 03279 x = 1; 03280 ast_channel_setoption(chan, AST_OPTION_TONE_VERIFY, &x, sizeof(char), 0); 03281 } 03282 03283 for (;;) { 03284 int menu_was_active = 0; 03285 03286 outfd = -1; 03287 ms = -1; 03288 now = ast_tvnow(); 03289 03290 if (rt_schedule && conf->endtime) { 03291 char currenttime[32]; 03292 long localendtime = 0; 03293 int extended = 0; 03294 struct ast_tm tm; 03295 struct ast_variable *var, *origvar; 03296 struct timeval tmp; 03297 03298 if (now.tv_sec % 60 == 0) { 03299 if (!checked) { 03300 ast_localtime(&now, &tm, NULL); 03301 ast_strftime(currenttime, sizeof(currenttime), DATE_FORMAT, &tm); 03302 var = origvar = ast_load_realtime("meetme", "confno", 03303 conf->confno, "starttime <=", currenttime, 03304 "endtime >=", currenttime, NULL); 03305 03306 for ( ; var; var = var->next) { 03307 if (!strcasecmp(var->name, "endtime")) { 03308 struct ast_tm endtime_tm; 03309 ast_strptime(var->value, "%Y-%m-%d %H:%M:%S", &endtime_tm); 03310 tmp = ast_mktime(&endtime_tm, NULL); 03311 localendtime = tmp.tv_sec; 03312 } 03313 } 03314 ast_variables_destroy(origvar); 03315 03316 /* A conference can be extended from the 03317 Admin/User menu or by an external source */ 03318 if (localendtime > conf->endtime){ 03319 conf->endtime = localendtime; 03320 extended = 1; 03321 } 03322 03323 if (conf->endtime && (now.tv_sec >= conf->endtime)) { 03324 ast_verbose("Quitting time...\n"); 03325 goto outrun; 03326 } 03327 03328 if (!announcement_played && conf->endalert) { 03329 if (now.tv_sec + conf->endalert >= conf->endtime) { 03330 if (!ast_streamfile(chan, "conf-will-end-in", chan->language)) 03331 ast_waitstream(chan, ""); 03332 ast_say_digits(chan, (conf->endtime - now.tv_sec) / 60, "", chan->language); 03333 if (!ast_streamfile(chan, "minutes", chan->language)) 03334 ast_waitstream(chan, ""); 03335 if (musiconhold) { 03336 conf_start_moh(chan, optargs[OPT_ARG_MOH_CLASS]); 03337 } 03338 announcement_played = 1; 03339 } 03340 } 03341 03342 if (extended) { 03343 announcement_played = 0; 03344 } 03345 03346 checked = 1; 03347 } 03348 } else { 03349 checked = 0; 03350 } 03351 } 03352 03353 if (user->kicktime && (user->kicktime <= now.tv_sec)) { 03354 if (ast_test_flag64(confflags, CONFFLAG_KICK_CONTINUE)) { 03355 ret = 0; 03356 } else { 03357 ret = -1; 03358 } 03359 break; 03360 } 03361 03362 to = -1; 03363 if (user->timelimit) { 03364 int minutes = 0, seconds = 0, remain = 0; 03365 03366 to = ast_tvdiff_ms(nexteventts, now); 03367 if (to < 0) { 03368 to = 0; 03369 } 03370 time_left_ms = user->timelimit - ast_tvdiff_ms(now, user->start_time); 03371 if (time_left_ms < to) { 03372 to = time_left_ms; 03373 } 03374 03375 if (time_left_ms <= 0) { 03376 if (user->end_sound) { 03377 res = ast_streamfile(chan, user->end_sound, chan->language); 03378 res = ast_waitstream(chan, ""); 03379 } 03380 if (ast_test_flag64(confflags, CONFFLAG_KICK_CONTINUE)) { 03381 ret = 0; 03382 } else { 03383 ret = -1; 03384 } 03385 break; 03386 } 03387 03388 if (!to) { 03389 if (time_left_ms >= 5000) { 03390 03391 remain = (time_left_ms + 500) / 1000; 03392 if (remain / 60 >= 1) { 03393 minutes = remain / 60; 03394 seconds = remain % 60; 03395 } else { 03396 seconds = remain; 03397 } 03398 03399 /* force the time left to round up if appropriate */ 03400 if (user->warning_sound && user->play_warning) { 03401 if (!strcmp(user->warning_sound, "timeleft")) { 03402 03403 res = ast_streamfile(chan, "vm-youhave", chan->language); 03404 res = ast_waitstream(chan, ""); 03405 if (minutes) { 03406 res = ast_say_number(chan, minutes, AST_DIGIT_ANY, chan->language, (char *) NULL); 03407 res = ast_streamfile(chan, "queue-minutes", chan->language); 03408 res = ast_waitstream(chan, ""); 03409 } 03410 if (seconds) { 03411 res = ast_say_number(chan, seconds, AST_DIGIT_ANY, chan->language, (char *) NULL); 03412 res = ast_streamfile(chan, "queue-seconds", chan->language); 03413 res = ast_waitstream(chan, ""); 03414 } 03415 } else { 03416 res = ast_streamfile(chan, user->warning_sound, chan->language); 03417 res = ast_waitstream(chan, ""); 03418 } 03419 if (musiconhold) { 03420 conf_start_moh(chan, optargs[OPT_ARG_MOH_CLASS]); 03421 } 03422 } 03423 } 03424 if (user->warning_freq) { 03425 nexteventts = ast_tvadd(nexteventts, ast_samp2tv(user->warning_freq, 1000)); 03426 } else { 03427 nexteventts = ast_tvadd(user->start_time, ast_samp2tv(user->timelimit, 1000)); 03428 } 03429 } 03430 } 03431 03432 now = ast_tvnow(); 03433 if (timeout && now.tv_sec >= timeout) { 03434 if (ast_test_flag64(confflags, CONFFLAG_KICK_CONTINUE)) { 03435 ret = 0; 03436 } else { 03437 ret = -1; 03438 } 03439 break; 03440 } 03441 03442 /* if we have just exited from the menu, and the user had a channel-driver 03443 volume adjustment, restore it 03444 */ 03445 if (!menu_mode && menu_was_active && user->listen.desired && !user->listen.actual) { 03446 set_talk_volume(user, user->listen.desired); 03447 } 03448 03449 menu_was_active = menu_mode; 03450 03451 currentmarked = conf->markedusers; 03452 if (!ast_test_flag64(confflags, CONFFLAG_QUIET) && 03453 ast_test_flag64(confflags, CONFFLAG_MARKEDUSER) && 03454 ast_test_flag64(confflags, CONFFLAG_WAITMARKED) && 03455 lastmarked == 0) { 03456 if (currentmarked == 1 && conf->users > 1) { 03457 ast_say_number(chan, conf->users - 1, AST_DIGIT_ANY, chan->language, (char *) NULL); 03458 if (conf->users - 1 == 1) { 03459 if (!ast_streamfile(chan, "conf-userwilljoin", chan->language)) { 03460 ast_waitstream(chan, ""); 03461 } 03462 } else { 03463 if (!ast_streamfile(chan, "conf-userswilljoin", chan->language)) { 03464 ast_waitstream(chan, ""); 03465 } 03466 } 03467 } 03468 if (conf->users == 1 && !ast_test_flag64(confflags, CONFFLAG_MARKEDUSER)) { 03469 if (!ast_streamfile(chan, "conf-onlyperson", chan->language)) { 03470 ast_waitstream(chan, ""); 03471 } 03472 } 03473 } 03474 03475 /* Update the struct with the actual confflags */ 03476 user->userflags = *confflags; 03477 03478 if (ast_test_flag64(confflags, CONFFLAG_WAITMARKED)) { 03479 if (currentmarked == 0) { 03480 if (lastmarked != 0) { 03481 if (!ast_test_flag64(confflags, CONFFLAG_QUIET)) { 03482 if (!ast_streamfile(chan, "conf-leaderhasleft", chan->language)) { 03483 ast_waitstream(chan, ""); 03484 } 03485 } 03486 if (ast_test_flag64(confflags, CONFFLAG_MARKEDEXIT)) { 03487 if (ast_test_flag64(confflags, CONFFLAG_KICK_CONTINUE)) { 03488 ret = 0; 03489 } 03490 break; 03491 } else { 03492 dahdic.confmode = DAHDI_CONF_CONF; 03493 if (ioctl(fd, DAHDI_SETCONF, &dahdic)) { 03494 ast_log(LOG_WARNING, "Error setting conference\n"); 03495 close(fd); 03496 goto outrun; 03497 } 03498 } 03499 } 03500 if (!musiconhold && (ast_test_flag64(confflags, CONFFLAG_MOH))) { 03501 conf_start_moh(chan, optargs[OPT_ARG_MOH_CLASS]); 03502 musiconhold = 1; 03503 } 03504 } else if (currentmarked >= 1 && lastmarked == 0) { 03505 /* Marked user entered, so cancel timeout */ 03506 timeout = 0; 03507 if (ast_test_flag64(confflags, CONFFLAG_MONITOR)) { 03508 dahdic.confmode = DAHDI_CONF_CONFMON | DAHDI_CONF_LISTENER; 03509 } else if (ast_test_flag64(confflags, CONFFLAG_TALKER)) { 03510 dahdic.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER; 03511 } else { 03512 dahdic.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER; 03513 } 03514 if (ioctl(fd, DAHDI_SETCONF, &dahdic)) { 03515 ast_log(LOG_WARNING, "Error setting conference\n"); 03516 close(fd); 03517 goto outrun; 03518 } 03519 if (musiconhold && (ast_test_flag64(confflags, CONFFLAG_MOH))) { 03520 ast_moh_stop(chan); 03521 musiconhold = 0; 03522 } 03523 if (!ast_test_flag64(confflags, CONFFLAG_QUIET) && 03524 !ast_test_flag64(confflags, CONFFLAG_MARKEDUSER)) { 03525 if (!ast_streamfile(chan, "conf-placeintoconf", chan->language)) { 03526 ast_waitstream(chan, ""); 03527 } 03528 conf_play(chan, conf, ENTER); 03529 } 03530 } 03531 } 03532 03533 /* trying to add moh for single person conf */ 03534 if (ast_test_flag64(confflags, CONFFLAG_MOH) && !ast_test_flag64(confflags, CONFFLAG_WAITMARKED)) { 03535 if (conf->users == 1) { 03536 if (!musiconhold) { 03537 conf_start_moh(chan, optargs[OPT_ARG_MOH_CLASS]); 03538 musiconhold = 1; 03539 } 03540 } else { 03541 if (musiconhold) { 03542 ast_moh_stop(chan); 03543 musiconhold = 0; 03544 } 03545 } 03546 } 03547 03548 /* Leave if the last marked user left */ 03549 if (currentmarked == 0 && lastmarked != 0 && ast_test_flag64(confflags, CONFFLAG_MARKEDEXIT)) { 03550 if (ast_test_flag64(confflags, CONFFLAG_KICK_CONTINUE)) { 03551 ret = 0; 03552 } else { 03553 ret = -1; 03554 } 03555 break; 03556 } 03557 03558 /* Throw a TestEvent if a user exit did not cause this user to leave the conference */ 03559 if (conf->users != lastusers) { 03560 if (conf->users < lastusers) { 03561 ast_test_suite_event_notify("NOEXIT", "Message: CONFFLAG_MARKEDEXIT\r\nLastUsers: %d\r\nUsers: %d", lastusers, conf->users); 03562 } 03563 lastusers = conf->users; 03564 } 03565 03566 /* Check if my modes have changed */ 03567 03568 /* If I should be muted but am still talker, mute me */ 03569 if ((user->adminflags & (ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED)) && (dahdic.confmode & DAHDI_CONF_TALKER)) { 03570 dahdic.confmode ^= DAHDI_CONF_TALKER; 03571 if (ioctl(fd, DAHDI_SETCONF, &dahdic)) { 03572 ast_log(LOG_WARNING, "Error setting conference - Un/Mute \n"); 03573 ret = -1; 03574 break; 03575 } 03576 03577 /* Indicate user is not talking anymore - change him to unmonitored state */ 03578 if (ast_test_flag64(confflags, (CONFFLAG_MONITORTALKER | CONFFLAG_OPTIMIZETALKER))) { 03579 set_user_talking(chan, conf, user, -1, ast_test_flag64(confflags, CONFFLAG_MONITORTALKER)); 03580 } 03581 03582 ast_manager_event(chan, EVENT_FLAG_CALL, "MeetmeMute", 03583 "Channel: %s\r\n" 03584 "Uniqueid: %s\r\n" 03585 "Meetme: %s\r\n" 03586 "Usernum: %d\r\n" 03587 "Status: on\r\n", 03588 chan->name, chan->uniqueid, conf->confno, user->user_no); 03589 } 03590 03591 /* If I should be un-muted but am not talker, un-mute me */ 03592 if (!(user->adminflags & (ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED)) && !ast_test_flag64(confflags, CONFFLAG_MONITOR) && !(dahdic.confmode & DAHDI_CONF_TALKER)) { 03593 dahdic.confmode |= DAHDI_CONF_TALKER; 03594 if (ioctl(fd, DAHDI_SETCONF, &dahdic)) { 03595 ast_log(LOG_WARNING, "Error setting conference - Un/Mute \n"); 03596 ret = -1; 03597 break; 03598 } 03599 03600 ast_manager_event(chan, EVENT_FLAG_CALL, "MeetmeMute", 03601 "Channel: %s\r\n" 03602 "Uniqueid: %s\r\n" 03603 "Meetme: %s\r\n" 03604 "Usernum: %d\r\n" 03605 "Status: off\r\n", 03606 chan->name, chan->uniqueid, conf->confno, user->user_no); 03607 } 03608 03609 if ((user->adminflags & (ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED)) && 03610 (user->adminflags & ADMINFLAG_T_REQUEST) && !(talkreq_manager)) { 03611 talkreq_manager = 1; 03612 03613 ast_manager_event(chan, EVENT_FLAG_CALL, "MeetmeTalkRequest", 03614 "Channel: %s\r\n" 03615 "Uniqueid: %s\r\n" 03616 "Meetme: %s\r\n" 03617 "Usernum: %d\r\n" 03618 "Status: on\r\n", 03619 chan->name, chan->uniqueid, conf->confno, user->user_no); 03620 } 03621 03622 03623 if (!(user->adminflags & (ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED)) && 03624 !(user->adminflags & ADMINFLAG_T_REQUEST) && (talkreq_manager)) { 03625 talkreq_manager = 0; 03626 ast_manager_event(chan, EVENT_FLAG_CALL, "MeetmeTalkRequest", 03627 "Channel: %s\r\n" 03628 "Uniqueid: %s\r\n" 03629 "Meetme: %s\r\n" 03630 "Usernum: %d\r\n" 03631 "Status: off\r\n", 03632 chan->name, chan->uniqueid, conf->confno, user->user_no); 03633 } 03634 03635 /* If I have been kicked, exit the conference */ 03636 if (user->adminflags & ADMINFLAG_KICKME) { 03637 /* You have been kicked. */ 03638 if (!ast_test_flag64(confflags, CONFFLAG_QUIET) && 03639 !ast_streamfile(chan, "conf-kicked", chan->language)) { 03640 ast_waitstream(chan, ""); 03641 } 03642 ret = 0; 03643 break; 03644 } 03645 03646 /* Perform a hangup check here since ast_waitfor_nandfds will not always be able to get a channel after a hangup has occurred */ 03647 if (ast_check_hangup(chan)) { 03648 break; 03649 } 03650 03651 c = ast_waitfor_nandfds(&chan, 1, &fd, nfds, NULL, &outfd, &ms); 03652 03653 if (c) { 03654 char dtmfstr[2] = ""; 03655 03656 if (c->fds[0] != origfd || (user->dahdichannel && (c->audiohooks || c->monitor))) { 03657 if (using_pseudo) { 03658 /* Kill old pseudo */ 03659 close(fd); 03660 using_pseudo = 0; 03661 } 03662 ast_debug(1, "Ooh, something swapped out under us, starting over\n"); 03663 retrydahdi = (strcasecmp(c->tech->type, "DAHDI") || (c->audiohooks || c->monitor) ? 1 : 0); 03664 user->dahdichannel = !retrydahdi; 03665 goto dahdiretry; 03666 } 03667 if (ast_test_flag64(confflags, CONFFLAG_MONITOR) || (user->adminflags & (ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED))) { 03668 f = ast_read_noaudio(c); 03669 } else { 03670 f = ast_read(c); 03671 } 03672 if (!f) { 03673 break; 03674 } 03675 if (f->frametype == AST_FRAME_DTMF) { 03676 dtmfstr[0] = f->subclass.integer; 03677 dtmfstr[1] = '\0'; 03678 } 03679 03680 if ((f->frametype == AST_FRAME_VOICE) && (f->subclass.codec == AST_FORMAT_SLINEAR)) { 03681 if (user->talk.actual) { 03682 ast_frame_adjust_volume(f, user->talk.actual); 03683 } 03684 03685 if (ast_test_flag64(confflags, (CONFFLAG_OPTIMIZETALKER | CONFFLAG_MONITORTALKER))) { 03686 if (user->talking == -1) { 03687 user->talking = 0; 03688 } 03689 03690 res = ast_dsp_silence(dsp, f, &totalsilence); 03691 if (!user->talking && totalsilence < MEETME_DELAYDETECTTALK) { 03692 set_user_talking(chan, conf, user, 1, ast_test_flag64(confflags, CONFFLAG_MONITORTALKER)); 03693 } 03694 03695 if (user->talking && totalsilence > MEETME_DELAYDETECTENDTALK) { 03696 set_user_talking(chan, conf, user, 0, ast_test_flag64(confflags, CONFFLAG_MONITORTALKER)); 03697 } 03698 } 03699 if (using_pseudo) { 03700 /* Absolutely do _not_ use careful_write here... 03701 it is important that we read data from the channel 03702 as fast as it arrives, and feed it into the conference. 03703 The buffering in the pseudo channel will take care of any 03704 timing differences, unless they are so drastic as to lose 03705 audio frames (in which case carefully writing would only 03706 have delayed the audio even further). 03707 */ 03708 /* As it turns out, we do want to use careful write. We just 03709 don't want to block, but we do want to at least *try* 03710 to write out all the samples. 03711 */ 03712 if (user->talking || !ast_test_flag64(confflags, CONFFLAG_OPTIMIZETALKER)) { 03713 careful_write(fd, f->data.ptr, f->datalen, 0); 03714 } 03715 } 03716 } else if (((f->frametype == AST_FRAME_DTMF) && (f->subclass.integer == '*') && ast_test_flag64(confflags, CONFFLAG_STARMENU)) || ((f->frametype == AST_FRAME_DTMF) && menu_mode)) { 03717 if (ast_test_flag64(confflags, CONFFLAG_PASS_DTMF)) { 03718 conf_queue_dtmf(conf, user, f); 03719 } 03720 if (ioctl(fd, DAHDI_SETCONF, &dahdic_empty)) { 03721 ast_log(LOG_WARNING, "Error setting conference\n"); 03722 close(fd); 03723 ast_frfree(f); 03724 goto outrun; 03725 } 03726 03727 /* if we are entering the menu, and the user has a channel-driver 03728 volume adjustment, clear it 03729 */ 03730 if (!menu_mode && user->talk.desired && !user->talk.actual) { 03731 set_talk_volume(user, 0); 03732 } 03733 03734 if (musiconhold) { 03735 ast_moh_stop(chan); 03736 } else if (!menu_mode) { 03737 char *menu_to_play; 03738 if (ast_test_flag64(confflags, CONFFLAG_ADMIN)) { 03739 menu_mode = MENU_ADMIN; 03740 menu_to_play = "conf-adminmenu-18"; 03741 } else { 03742 menu_mode = MENU_NORMAL; 03743 menu_to_play = "conf-usermenu-162"; 03744 } 03745 03746 if (!ast_streamfile(chan, menu_to_play, chan->language)) { 03747 dtmf = ast_waitstream(chan, AST_DIGIT_ANY); 03748 ast_stopstream(chan); 03749 } else { 03750 dtmf = 0; 03751 } 03752 } else { 03753 dtmf = f->subclass.integer; 03754 } 03755 03756 if (dtmf > 0) { 03757 meetme_menu(&menu_mode, &dtmf, conf, confflags, chan, user, recordingtmp, &dahdic); 03758 } 03759 03760 if (musiconhold && !menu_mode) { 03761 conf_start_moh(chan, optargs[OPT_ARG_MOH_CLASS]); 03762 } 03763 03764 if (ioctl(fd, DAHDI_SETCONF, &dahdic)) { 03765 ast_log(LOG_WARNING, "Error setting conference\n"); 03766 close(fd); 03767 ast_frfree(f); 03768 goto outrun; 03769 } 03770 03771 conf_flush(fd, chan); 03772 /* 03773 * Since options using DTMF could absorb DTMF meant for the 03774 * conference menu, we have to check them after the menu. 03775 */ 03776 } else if ((f->frametype == AST_FRAME_DTMF) && ast_test_flag64(confflags, CONFFLAG_EXIT_CONTEXT) && ast_exists_extension(chan, exitcontext, dtmfstr, 1, "")) { 03777 if (ast_test_flag64(confflags, CONFFLAG_PASS_DTMF)) { 03778 conf_queue_dtmf(conf, user, f); 03779 } 03780 03781 if (!ast_goto_if_exists(chan, exitcontext, dtmfstr, 1)) { 03782 ast_debug(1, "Got DTMF %c, goto context %s\n", dtmfstr[0], exitcontext); 03783 ret = 0; 03784 ast_frfree(f); 03785 break; 03786 } else { 03787 ast_debug(2, "Exit by single digit did not work in meetme. Extension %s does not exist in context %s\n", dtmfstr, exitcontext); 03788 } 03789 } else if ((f->frametype == AST_FRAME_DTMF) && ast_test_flag64(confflags, CONFFLAG_KEYEXIT) && 03790 (strchr(exitkeys, f->subclass.integer))) { 03791 pbx_builtin_setvar_helper(chan, "MEETME_EXIT_KEY", dtmfstr); 03792 03793 if (ast_test_flag64(confflags, CONFFLAG_PASS_DTMF)) { 03794 conf_queue_dtmf(conf, user, f); 03795 } 03796 ret = 0; 03797 ast_frfree(f); 03798 break; 03799 } else if ((f->frametype == AST_FRAME_DTMF_BEGIN || f->frametype == AST_FRAME_DTMF_END) 03800 && ast_test_flag64(confflags, CONFFLAG_PASS_DTMF)) { 03801 conf_queue_dtmf(conf, user, f); 03802 } else if (ast_test_flag64(confflags, CONFFLAG_SLA_STATION) && f->frametype == AST_FRAME_CONTROL) { 03803 switch (f->subclass.integer) { 03804 case AST_CONTROL_HOLD: 03805 sla_queue_event_conf(SLA_EVENT_HOLD, chan, conf); 03806 break; 03807 default: 03808 break; 03809 } 03810 } else if (f->frametype == AST_FRAME_NULL) { 03811 /* Ignore NULL frames. It is perfectly normal to get these if the person is muted. */ 03812 } else if (f->frametype == AST_FRAME_CONTROL) { 03813 switch (f->subclass.integer) { 03814 case AST_CONTROL_BUSY: 03815 case AST_CONTROL_CONGESTION: 03816 ast_frfree(f); 03817 goto outrun; 03818 break; 03819 default: 03820 ast_debug(1, 03821 "Got ignored control frame on channel %s, f->frametype=%d,f->subclass=%d\n", 03822 chan->name, f->frametype, f->subclass.integer); 03823 } 03824 } else { 03825 ast_debug(1, 03826 "Got unrecognized frame on channel %s, f->frametype=%d,f->subclass=%d\n", 03827 chan->name, f->frametype, f->subclass.integer); 03828 } 03829 ast_frfree(f); 03830 } else if (outfd > -1) { 03831 res = read(outfd, buf, CONF_SIZE); 03832 if (res > 0) { 03833 memset(&fr, 0, sizeof(fr)); 03834 fr.frametype = AST_FRAME_VOICE; 03835 fr.subclass.codec = AST_FORMAT_SLINEAR; 03836 fr.datalen = res; 03837 fr.samples = res / 2; 03838 fr.data.ptr = buf; 03839 fr.offset = AST_FRIENDLY_OFFSET; 03840 if (!user->listen.actual && 03841 (ast_test_flag64(confflags, CONFFLAG_MONITOR) || 03842 (user->adminflags & (ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED)) || 03843 (!user->talking && ast_test_flag64(confflags, CONFFLAG_OPTIMIZETALKER)) 03844 )) { 03845 int idx; 03846 for (idx = 0; idx < AST_FRAME_BITS; idx++) { 03847 if (chan->rawwriteformat & (1 << idx)) { 03848 break; 03849 } 03850 } 03851 if (idx >= AST_FRAME_BITS) { 03852 goto bailoutandtrynormal; 03853 } 03854 ast_mutex_lock(&conf->listenlock); 03855 if (!conf->transframe[idx]) { 03856 if (conf->origframe) { 03857 if (musiconhold && !ast_dsp_silence(dsp, conf->origframe, &confsilence) && confsilence < MEETME_DELAYDETECTTALK) { 03858 ast_moh_stop(chan); 03859 mohtempstopped = 1; 03860 } 03861 if (!conf->transpath[idx]) { 03862 conf->transpath[idx] = ast_translator_build_path((1 << idx), AST_FORMAT_SLINEAR); 03863 } 03864 if (conf->transpath[idx]) { 03865 conf->transframe[idx] = ast_translate(conf->transpath[idx], conf->origframe, 0); 03866 if (!conf->transframe[idx]) { 03867 conf->transframe[idx] = &ast_null_frame; 03868 } 03869 } 03870 } 03871 } 03872 if (conf->transframe[idx]) { 03873 if ((conf->transframe[idx]->frametype != AST_FRAME_NULL) && 03874 can_write(chan, confflags)) { 03875 struct ast_frame *cur; 03876 /* the translator may have returned a list of frames, so 03877 write each one onto the channel 03878 */ 03879 for (cur = conf->transframe[idx]; cur; cur = AST_LIST_NEXT(cur, frame_list)) { 03880 if (ast_write(chan, cur)) { 03881 ast_log(LOG_WARNING, "Unable to write frame to channel %s\n", chan->name); 03882 break; 03883 } 03884 } 03885 if (musiconhold && mohtempstopped && confsilence > MEETME_DELAYDETECTENDTALK) { 03886 mohtempstopped = 0; 03887 conf_start_moh(chan, optargs[OPT_ARG_MOH_CLASS]); 03888 } 03889 } 03890 } else { 03891 ast_mutex_unlock(&conf->listenlock); 03892 goto bailoutandtrynormal; 03893 } 03894 ast_mutex_unlock(&conf->listenlock); 03895 } else { 03896 bailoutandtrynormal: 03897 if (musiconhold && !ast_dsp_silence(dsp, &fr, &confsilence) && confsilence < MEETME_DELAYDETECTTALK) { 03898 ast_moh_stop(chan); 03899 mohtempstopped = 1; 03900 } 03901 if (user->listen.actual) { 03902 ast_frame_adjust_volume(&fr, user->listen.actual); 03903 } 03904 if (can_write(chan, confflags) && ast_write(chan, &fr) < 0) { 03905 ast_log(LOG_WARNING, "Unable to write frame to channel %s\n", chan->name); 03906 } 03907 if (musiconhold && mohtempstopped && confsilence > MEETME_DELAYDETECTENDTALK) { 03908 mohtempstopped = 0; 03909 conf_start_moh(chan, optargs[OPT_ARG_MOH_CLASS]); 03910 } 03911 } 03912 } else { 03913 ast_log(LOG_WARNING, "Failed to read frame: %s\n", strerror(errno)); 03914 } 03915 } 03916 lastmarked = currentmarked; 03917 } 03918 } 03919 03920 if (musiconhold) { 03921 ast_moh_stop(chan); 03922 } 03923 03924 if (using_pseudo) { 03925 close(fd); 03926 } else { 03927 /* Take out of conference */ 03928 dahdic.chan = 0; 03929 dahdic.confno = 0; 03930 dahdic.confmode = 0; 03931 if (ioctl(fd, DAHDI_SETCONF, &dahdic)) { 03932 ast_log(LOG_WARNING, "Error setting conference\n"); 03933 } 03934 } 03935 03936 reset_volumes(user); 03937 03938 if (!ast_test_flag64(confflags, CONFFLAG_QUIET) && !ast_test_flag64(confflags, CONFFLAG_MONITOR) && 03939 !ast_test_flag64(confflags, CONFFLAG_ADMIN)) { 03940 conf_play(chan, conf, LEAVE); 03941 } 03942 03943 if (!ast_test_flag64(confflags, CONFFLAG_QUIET) && (ast_test_flag64(confflags, CONFFLAG_INTROUSER) || ast_test_flag64(confflags, CONFFLAG_INTROUSERNOREVIEW)) && conf->users > 1) { 03944 struct announce_listitem *item; 03945 if (!(item = ao2_alloc(sizeof(*item), NULL))) 03946 goto outrun; 03947 ast_copy_string(item->namerecloc, user->namerecloc, sizeof(item->namerecloc)); 03948 ast_copy_string(item->language, chan->language, sizeof(item->language)); 03949 item->confchan = conf->chan; 03950 item->confusers = conf->users; 03951 item->announcetype = CONF_HASLEFT; 03952 ast_mutex_lock(&conf->announcelistlock); 03953 AST_LIST_INSERT_TAIL(&conf->announcelist, item, entry); 03954 ast_cond_signal(&conf->announcelist_addition); 03955 ast_mutex_unlock(&conf->announcelistlock); 03956 } else if (!ast_test_flag64(confflags, CONFFLAG_QUIET) && (ast_test_flag64(confflags, CONFFLAG_INTROUSER) || 03957 ast_test_flag64(confflags, CONFFLAG_INTROUSERNOREVIEW)) && conf->users == 1) { 03958 /* Last person is leaving, so no reason to try and announce, but should delete the name recording */ 03959 ast_filedelete(user->namerecloc, NULL); 03960 } 03961 03962 outrun: 03963 AST_LIST_LOCK(&confs); 03964 03965 if (dsp) { 03966 ast_dsp_free(dsp); 03967 } 03968 03969 if (user->user_no) { 03970 /* Only cleanup users who really joined! */ 03971 now = ast_tvnow(); 03972 03973 if (sent_event) { 03974 ast_manager_event(chan, EVENT_FLAG_CALL, "MeetmeLeave", 03975 "Channel: %s\r\n" 03976 "Uniqueid: %s\r\n" 03977 "Meetme: %s\r\n" 03978 "Usernum: %d\r\n" 03979 "CallerIDNum: %s\r\n" 03980 "CallerIDName: %s\r\n" 03981 "ConnectedLineNum: %s\r\n" 03982 "ConnectedLineName: %s\r\n" 03983 "Duration: %ld\r\n", 03984 chan->name, chan->uniqueid, conf->confno, 03985 user->user_no, 03986 S_COR(user->chan->caller.id.number.valid, user->chan->caller.id.number.str, "<unknown>"), 03987 S_COR(user->chan->caller.id.name.valid, user->chan->caller.id.name.str, "<unknown>"), 03988 S_COR(user->chan->connected.id.number.valid, user->chan->connected.id.number.str, "<unknown>"), 03989 S_COR(user->chan->connected.id.name.valid, user->chan->connected.id.name.str, "<unknown>"), 03990 (long)(now.tv_sec - user->jointime)); 03991 } 03992 03993 if (setusercount) { 03994 conf->users--; 03995 if (rt_log_members) { 03996 /* Update table */ 03997 snprintf(members, sizeof(members), "%d", conf->users); 03998 ast_realtime_require_field("meetme", 03999 "confno", strlen(conf->confno) > 7 ? RQ_UINTEGER4 : strlen(conf->confno) > 4 ? RQ_UINTEGER3 : RQ_UINTEGER2, strlen(conf->confno), 04000 "members", RQ_UINTEGER1, strlen(members), 04001 NULL); 04002 ast_update_realtime("meetme", "confno", conf->confno, "members", members, NULL); 04003 } 04004 if (ast_test_flag64(confflags, CONFFLAG_MARKEDUSER)) { 04005 conf->markedusers--; 04006 } 04007 } 04008 /* Remove ourselves from the container */ 04009 ao2_unlink(conf->usercontainer, user); 04010 04011 /* Change any states */ 04012 if (!conf->users) { 04013 ast_devstate_changed(AST_DEVICE_NOT_INUSE, (conf->isdynamic ? AST_DEVSTATE_NOT_CACHABLE : AST_DEVSTATE_CACHABLE), "meetme:%s", conf->confno); 04014 } 04015 04016 /* Return the number of seconds the user was in the conf */ 04017 snprintf(meetmesecs, sizeof(meetmesecs), "%d", (int) (time(NULL) - user->jointime)); 04018 pbx_builtin_setvar_helper(chan, "MEETMESECS", meetmesecs); 04019 04020 /* Return the RealTime bookid for CDR linking */ 04021 if (rt_schedule) { 04022 pbx_builtin_setvar_helper(chan, "MEETMEBOOKID", conf->bookid); 04023 } 04024 } 04025 ao2_ref(user, -1); 04026 AST_LIST_UNLOCK(&confs); 04027 04028 return ret; 04029 }
static void conf_start_moh | ( | struct ast_channel * | chan, | |
const char * | musicclass | |||
) | [static] |
Definition at line 2141 of file app_meetme.c.
References ast_channel_lock, ast_channel_unlock, ast_moh_start(), ast_strdupa, and ast_string_field_set.
Referenced by conf_run().
02142 { 02143 char *original_moh; 02144 02145 ast_channel_lock(chan); 02146 original_moh = ast_strdupa(chan->musicclass); 02147 ast_string_field_set(chan, musicclass, musicclass); 02148 ast_channel_unlock(chan); 02149 02150 ast_moh_start(chan, original_moh, NULL); 02151 02152 ast_channel_lock(chan); 02153 ast_string_field_set(chan, musicclass, original_moh); 02154 ast_channel_unlock(chan); 02155 }
static int count_exec | ( | struct ast_channel * | chan, | |
const char * | data | |||
) | [static] |
The MeetmeCount application.
Definition at line 4323 of file app_meetme.c.
References ast_channel::_state, args, ast_answer(), AST_APP_ARG, AST_DECLARE_APP_ARGS, ast_log(), 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().
04324 { 04325 int res = 0; 04326 struct ast_conference *conf; 04327 int count; 04328 char *localdata; 04329 char val[80] = "0"; 04330 AST_DECLARE_APP_ARGS(args, 04331 AST_APP_ARG(confno); 04332 AST_APP_ARG(varname); 04333 ); 04334 04335 if (ast_strlen_zero(data)) { 04336 ast_log(LOG_WARNING, "MeetMeCount requires an argument (conference number)\n"); 04337 return -1; 04338 } 04339 04340 localdata = ast_strdupa(data); 04341 04342 AST_STANDARD_APP_ARGS(args, localdata); 04343 04344 conf = find_conf(chan, args.confno, 0, 0, NULL, 0, 1, NULL); 04345 04346 if (conf) { 04347 count = conf->users; 04348 dispose_conf(conf); 04349 conf = NULL; 04350 } else 04351 count = 0; 04352 04353 if (!ast_strlen_zero(args.varname)) { 04354 /* have var so load it and exit */ 04355 snprintf(val, sizeof(val), "%d", count); 04356 pbx_builtin_setvar_helper(chan, args.varname, val); 04357 } else { 04358 if (chan->_state != AST_STATE_UP) { 04359 ast_answer(chan); 04360 } 04361 res = ast_say_number(chan, count, "", chan->language, (char *) NULL); /* Needs gender */ 04362 } 04363 04364 return res; 04365 }
static struct sla_trunk_ref* create_trunk_ref | ( | struct sla_trunk * | trunk | ) | [static, read] |
Definition at line 6572 of file app_meetme.c.
References ast_calloc.
Referenced by sla_add_trunk_to_station().
06573 { 06574 struct sla_trunk_ref *trunk_ref; 06575 06576 if (!(trunk_ref = ast_calloc(1, sizeof(*trunk_ref)))) 06577 return NULL; 06578 06579 trunk_ref->trunk = trunk; 06580 06581 return trunk_ref; 06582 }
static void destroy_station | ( | struct sla_station * | station | ) | [static] |
Definition at line 6780 of file app_meetme.c.
References ast_context_remove_extension(), ast_free, AST_LIST_REMOVE_HEAD, AST_LIST_TRAVERSE, AST_MAX_APP, AST_MAX_EXTENSION, AST_RWLIST_RDLOCK, AST_RWLIST_UNLOCK, ast_string_field_free_memory, ast_strlen_zero(), exten, PRIORITY_HINT, and sla_registrar.
Referenced by sla_build_station(), and sla_destroy().
06781 { 06782 struct sla_trunk_ref *trunk_ref; 06783 06784 if (!ast_strlen_zero(station->autocontext)) { 06785 AST_RWLIST_RDLOCK(&sla_trunks); 06786 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) { 06787 char exten[AST_MAX_EXTENSION]; 06788 char hint[AST_MAX_APP]; 06789 snprintf(exten, sizeof(exten), "%s_%s", station->name, trunk_ref->trunk->name); 06790 snprintf(hint, sizeof(hint), "SLA:%s", exten); 06791 ast_context_remove_extension(station->autocontext, exten, 06792 1, sla_registrar); 06793 ast_context_remove_extension(station->autocontext, hint, 06794 PRIORITY_HINT, sla_registrar); 06795 } 06796 AST_RWLIST_UNLOCK(&sla_trunks); 06797 } 06798 06799 while ((trunk_ref = AST_LIST_REMOVE_HEAD(&station->trunks, entry))) 06800 ast_free(trunk_ref); 06801 06802 ast_string_field_free_memory(station); 06803 ast_free(station); 06804 }
static void destroy_trunk | ( | struct sla_trunk * | trunk | ) | [static] |
Definition at line 6766 of file app_meetme.c.
References ast_context_remove_extension(), ast_free, AST_LIST_REMOVE_HEAD, ast_string_field_free_memory, ast_strlen_zero(), and sla_registrar.
Referenced by sla_build_trunk(), and sla_destroy().
06767 { 06768 struct sla_station_ref *station_ref; 06769 06770 if (!ast_strlen_zero(trunk->autocontext)) 06771 ast_context_remove_extension(trunk->autocontext, "s", 1, sla_registrar); 06772 06773 while ((station_ref = AST_LIST_REMOVE_HEAD(&trunk->stations, entry))) 06774 ast_free(station_ref); 06775 06776 ast_string_field_free_memory(trunk); 06777 ast_free(trunk); 06778 }
static void* dial_trunk | ( | void * | data | ) | [static] |
Definition at line 6262 of file app_meetme.c.
References ALL_TRUNK_REFS, args, ast_cond_signal, AST_CONTROL_PROGRESS, AST_CONTROL_RINGING, ast_debug, AST_DEVICE_NOT_INUSE, ast_dial_answered(), ast_dial_append(), ast_dial_create(), ast_dial_destroy(), ast_dial_join(), AST_DIAL_RESULT_ANSWERED, AST_DIAL_RESULT_FAILED, AST_DIAL_RESULT_HANGUP, AST_DIAL_RESULT_INVALID, AST_DIAL_RESULT_PROCEEDING, AST_DIAL_RESULT_PROGRESS, AST_DIAL_RESULT_RINGING, AST_DIAL_RESULT_TIMEOUT, AST_DIAL_RESULT_TRYING, AST_DIAL_RESULT_UNANSWERED, ast_dial_run(), ast_dial_state(), ast_indicate(), ast_mutex_lock, ast_mutex_unlock, ast_party_caller_free(), ast_party_caller_init(), ast_safe_sleep(), ast_set_flag64, ast_strdupa, build_conf(), 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(), MAX_CONFNUM, sla, sla_change_trunk_state(), SLA_TRUNK_STATE_IDLE, dial_trunk_args::station, and dial_trunk_args::trunk_ref.
Referenced by sla_station_exec().
06263 { 06264 struct dial_trunk_args *args = data; 06265 struct ast_dial *dial; 06266 char *tech, *tech_data; 06267 enum ast_dial_result dial_res; 06268 char conf_name[MAX_CONFNUM]; 06269 struct ast_conference *conf; 06270 struct ast_flags64 conf_flags = { 0 }; 06271 struct sla_trunk_ref *trunk_ref = args->trunk_ref; 06272 int caller_is_saved; 06273 struct ast_party_caller caller; 06274 int last_state = 0; 06275 int current_state = 0; 06276 06277 if (!(dial = ast_dial_create())) { 06278 ast_mutex_lock(args->cond_lock); 06279 ast_cond_signal(args->cond); 06280 ast_mutex_unlock(args->cond_lock); 06281 return NULL; 06282 } 06283 06284 tech_data = ast_strdupa(trunk_ref->trunk->device); 06285 tech = strsep(&tech_data, "/"); 06286 if (ast_dial_append(dial, tech, tech_data) == -1) { 06287 ast_mutex_lock(args->cond_lock); 06288 ast_cond_signal(args->cond); 06289 ast_mutex_unlock(args->cond_lock); 06290 ast_dial_destroy(dial); 06291 return NULL; 06292 } 06293 06294 /* Do we need to save of the caller ID data? */ 06295 caller_is_saved = 0; 06296 if (!sla.attempt_callerid) { 06297 caller_is_saved = 1; 06298 caller = trunk_ref->chan->caller; 06299 ast_party_caller_init(&trunk_ref->chan->caller); 06300 } 06301 06302 dial_res = ast_dial_run(dial, trunk_ref->chan, 1); 06303 06304 /* Restore saved caller ID */ 06305 if (caller_is_saved) { 06306 ast_party_caller_free(&trunk_ref->chan->caller); 06307 trunk_ref->chan->caller = caller; 06308 } 06309 06310 if (dial_res != AST_DIAL_RESULT_TRYING) { 06311 ast_mutex_lock(args->cond_lock); 06312 ast_cond_signal(args->cond); 06313 ast_mutex_unlock(args->cond_lock); 06314 ast_dial_destroy(dial); 06315 return NULL; 06316 } 06317 06318 for (;;) { 06319 unsigned int done = 0; 06320 switch ((dial_res = ast_dial_state(dial))) { 06321 case AST_DIAL_RESULT_ANSWERED: 06322 trunk_ref->trunk->chan = ast_dial_answered(dial); 06323 case AST_DIAL_RESULT_HANGUP: 06324 case AST_DIAL_RESULT_INVALID: 06325 case AST_DIAL_RESULT_FAILED: 06326 case AST_DIAL_RESULT_TIMEOUT: 06327 case AST_DIAL_RESULT_UNANSWERED: 06328 done = 1; 06329 break; 06330 case AST_DIAL_RESULT_TRYING: 06331 current_state = AST_CONTROL_PROGRESS; 06332 break; 06333 case AST_DIAL_RESULT_RINGING: 06334 case AST_DIAL_RESULT_PROGRESS: 06335 case AST_DIAL_RESULT_PROCEEDING: 06336 current_state = AST_CONTROL_RINGING; 06337 break; 06338 } 06339 if (done) 06340 break; 06341 06342 /* check that SLA station that originated trunk call is still alive */ 06343 if (args->station && ast_device_state(args->station->device) == AST_DEVICE_NOT_INUSE) { 06344 ast_debug(3, "Originating station device %s no longer active\n", args->station->device); 06345 trunk_ref->trunk->chan = NULL; 06346 break; 06347 } 06348 06349 /* If trunk line state changed, send indication back to originating SLA Station channel */ 06350 if (current_state != last_state) { 06351 ast_debug(3, "Indicating State Change %d to channel %s\n", current_state, trunk_ref->chan->name); 06352 ast_indicate(trunk_ref->chan, current_state); 06353 last_state = current_state; 06354 } 06355 06356 /* avoid tight loop... sleep for 1/10th second */ 06357 ast_safe_sleep(trunk_ref->chan, 100); 06358 } 06359 06360 if (!trunk_ref->trunk->chan) { 06361 ast_mutex_lock(args->cond_lock); 06362 ast_cond_signal(args->cond); 06363 ast_mutex_unlock(args->cond_lock); 06364 ast_dial_join(dial); 06365 ast_dial_destroy(dial); 06366 return NULL; 06367 } 06368 06369 snprintf(conf_name, sizeof(conf_name), "SLA_%s", trunk_ref->trunk->name); 06370 ast_set_flag64(&conf_flags, 06371 CONFFLAG_QUIET | CONFFLAG_MARKEDEXIT | CONFFLAG_MARKEDUSER | 06372 CONFFLAG_PASS_DTMF | CONFFLAG_SLA_TRUNK); 06373 conf = build_conf(conf_name, "", "", 1, 1, 1, trunk_ref->trunk->chan, NULL); 06374 06375 ast_mutex_lock(args->cond_lock); 06376 ast_cond_signal(args->cond); 06377 ast_mutex_unlock(args->cond_lock); 06378 06379 if (conf) { 06380 conf_run(trunk_ref->trunk->chan, conf, &conf_flags, NULL); 06381 dispose_conf(conf); 06382 conf = NULL; 06383 } 06384 06385 /* If the trunk is going away, it is definitely now IDLE. */ 06386 sla_change_trunk_state(trunk_ref->trunk, SLA_TRUNK_STATE_IDLE, ALL_TRUNK_REFS, NULL); 06387 06388 trunk_ref->trunk->chan = NULL; 06389 trunk_ref->trunk->on_hold = 0; 06390 06391 ast_dial_join(dial); 06392 ast_dial_destroy(dial); 06393 06394 return NULL; 06395 }
static int dispose_conf | ( | struct ast_conference * | conf | ) | [static] |
Decrement reference counts, as incremented by find_conf().
Definition at line 2060 of file app_meetme.c.
References ast_atomic_dec_and_test(), 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().
02061 { 02062 int res = 0; 02063 int confno_int = 0; 02064 02065 AST_LIST_LOCK(&confs); 02066 if (ast_atomic_dec_and_test(&conf->refcount)) { 02067 /* Take the conference room number out of an inuse state */ 02068 if ((sscanf(conf->confno, "%4d", &confno_int) == 1) && (confno_int >= 0 && confno_int < 1024)) { 02069 conf_map[confno_int] = 0; 02070 } 02071 conf_free(conf); 02072 res = 1; 02073 } 02074 AST_LIST_UNLOCK(&confs); 02075 02076 return res; 02077 }
static void filename_parse | ( | char * | filename, | |
char * | buffer | |||
) | [static] |
Definition at line 5115 of file app_meetme.c.
References ast_config_AST_SPOOL_DIR, ast_copy_string(), ast_log(), ast_mkdir(), ast_strlen_zero(), and LOG_WARNING.
Referenced by recordthread().
05116 { 05117 char *slash; 05118 if (ast_strlen_zero(filename)) { 05119 ast_log(LOG_WARNING, "No file name was provided for a file save option.\n"); 05120 } else if (filename[0] != '/') { 05121 snprintf(buffer, PATH_MAX, "%s/meetme/%s", ast_config_AST_SPOOL_DIR, filename); 05122 } else { 05123 ast_copy_string(buffer, filename, PATH_MAX); 05124 } 05125 05126 slash = buffer; 05127 if ((slash = strrchr(slash, '/'))) { 05128 *slash = '\0'; 05129 ast_mkdir(buffer, 0777); 05130 *slash = '/'; 05131 } 05132 }
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_flags64 * | confflags | |||
) | [static, read] |
Definition at line 4219 of file app_meetme.c.
References args, AST_APP_ARG, ast_app_getdata(), ast_clear_flag64, ast_config_destroy(), ast_config_load, ast_copy_string(), ast_debug, AST_DECLARE_APP_ARGS, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), AST_STANDARD_APP_ARGS, ast_test_flag64, ast_variable_browse(), build_conf(), ast_conference::chan, CONFFLAG_INTROUSER, CONFFLAG_INTROUSERNOREVIEW, CONFFLAG_QUIET, CONFFLAG_RECORDCONF, CONFIG_FILE_NAME, CONFIG_STATUS_FILEINVALID, ast_conference::confno, LOG_ERROR, LOG_WARNING, MAX_SETTINGS, 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().
04221 { 04222 struct ast_config *cfg; 04223 struct ast_variable *var; 04224 struct ast_flags config_flags = { 0 }; 04225 struct ast_conference *cnf; 04226 04227 AST_DECLARE_APP_ARGS(args, 04228 AST_APP_ARG(confno); 04229 AST_APP_ARG(pin); 04230 AST_APP_ARG(pinadmin); 04231 ); 04232 04233 /* Check first in the conference list */ 04234 ast_debug(1, "The requested confno is '%s'?\n", confno); 04235 AST_LIST_LOCK(&confs); 04236 AST_LIST_TRAVERSE(&confs, cnf, list) { 04237 ast_debug(3, "Does conf %s match %s?\n", confno, cnf->confno); 04238 if (!strcmp(confno, cnf->confno)) 04239 break; 04240 } 04241 if (cnf) { 04242 cnf->refcount += refcount; 04243 } 04244 AST_LIST_UNLOCK(&confs); 04245 04246 if (!cnf) { 04247 if (dynamic) { 04248 /* No need to parse meetme.conf */ 04249 ast_debug(1, "Building dynamic conference '%s'\n", confno); 04250 if (dynamic_pin) { 04251 if (dynamic_pin[0] == 'q') { 04252 /* Query the user to enter a PIN */ 04253 if (ast_app_getdata(chan, "conf-getpin", dynamic_pin, pin_buf_len - 1, 0) < 0) 04254 return NULL; 04255 } 04256 cnf = build_conf(confno, dynamic_pin, "", make, dynamic, refcount, chan, NULL); 04257 } else { 04258 cnf = build_conf(confno, "", "", make, dynamic, refcount, chan, NULL); 04259 } 04260 } else { 04261 /* Check the config */ 04262 cfg = ast_config_load(CONFIG_FILE_NAME, config_flags); 04263 if (!cfg) { 04264 ast_log(LOG_WARNING, "No %s file :(\n", CONFIG_FILE_NAME); 04265 return NULL; 04266 } else if (cfg == CONFIG_STATUS_FILEINVALID) { 04267 ast_log(LOG_ERROR, "Config file " CONFIG_FILE_NAME " is in an invalid format. Aborting.\n"); 04268 return NULL; 04269 } 04270 04271 for (var = ast_variable_browse(cfg, "rooms"); var; var = var->next) { 04272 char parse[MAX_SETTINGS]; 04273 04274 if (strcasecmp(var->name, "conf")) 04275 continue; 04276 04277 ast_copy_string(parse, var->value, sizeof(parse)); 04278 04279 AST_STANDARD_APP_ARGS(args, parse); 04280 ast_debug(3, "Will conf %s match %s?\n", confno, args.confno); 04281 if (!strcasecmp(args.confno, confno)) { 04282 /* Bingo it's a valid conference */ 04283 cnf = build_conf(args.confno, 04284 S_OR(args.pin, ""), 04285 S_OR(args.pinadmin, ""), 04286 make, dynamic, refcount, chan, NULL); 04287 break; 04288 } 04289 } 04290 if (!var) { 04291 ast_debug(1, "%s isn't a valid conference\n", confno); 04292 } 04293 ast_config_destroy(cfg); 04294 } 04295 } else if (dynamic_pin) { 04296 /* Correct for the user selecting 'D' instead of 'd' to have 04297 someone join into a conference that has already been created 04298 with a pin. */ 04299 if (dynamic_pin[0] == 'q') { 04300 dynamic_pin[0] = '\0'; 04301 } 04302 } 04303 04304 if (cnf) { 04305 if (confflags && !cnf->chan && 04306 !ast_test_flag64(confflags, CONFFLAG_QUIET) && 04307 ast_test_flag64(confflags, CONFFLAG_INTROUSER | CONFFLAG_INTROUSERNOREVIEW)) { 04308 ast_log(LOG_WARNING, "No DAHDI channel available for conference, user introduction disabled (is chan_dahdi loaded?)\n"); 04309 ast_clear_flag64(confflags, CONFFLAG_INTROUSER | CONFFLAG_INTROUSERNOREVIEW); 04310 } 04311 04312 if (confflags && !cnf->chan && 04313 ast_test_flag64(confflags, CONFFLAG_RECORDCONF)) { 04314 ast_log(LOG_WARNING, "No DAHDI channel available for conference, conference recording disabled (is chan_dahdi loaded?)\n"); 04315 ast_clear_flag64(confflags, CONFFLAG_RECORDCONF); 04316 } 04317 } 04318 04319 return cnf; 04320 }
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_flags64 * | confflags, | |||
int * | too_early, | |||
char ** | optargs | |||
) | [static, read] |
Definition at line 4031 of file app_meetme.c.
References ast_conference::adminopts, ast_app_parse_options64(), ast_channel_lock, ast_channel_unlock, ast_clear_flag64, ast_copy_flags64, ast_copy_string(), ast_debug, ast_free, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_load_realtime(), ast_localtime(), ast_log(), AST_MAX_EXTENSION, ast_mktime(), ast_strdup, ast_strdupa, ast_streamfile(), ast_strftime(), ast_strlen_zero(), ast_strptime(), ast_test_flag64, ast_tvnow(), ast_variables_destroy(), ast_verb, ast_waitstream(), ast_conference::bookid, build_conf(), ast_conference::chan, CONFFLAG_INTROUSER, CONFFLAG_INTROUSERNOREVIEW, CONFFLAG_QUIET, CONFFLAG_RECORDCONF, ast_conference::confno, DATE_FORMAT, ast_conference::endalert, ast_conference::endtime, ast_flags64::flags, LOG_WARNING, ast_conference::maxusers, ast_variable::name, ast_variable::next, OPTIONS_LEN, pbx_builtin_getvar_helper(), ast_conference::pin, ast_conference::pinadmin, ast_conference::recordingfilename, ast_conference::recordingformat, ast_conference::refcount, ast_conference::useropts, ast_variable::value, and var.
Referenced by conf_exec().
04033 { 04034 struct ast_variable *var, *origvar; 04035 struct ast_conference *cnf; 04036 04037 *too_early = 0; 04038 04039 /* Check first in the conference list */ 04040 AST_LIST_LOCK(&confs); 04041 AST_LIST_TRAVERSE(&confs, cnf, list) { 04042 if (!strcmp(confno, cnf->confno)) { 04043 break; 04044 } 04045 } 04046 if (cnf) { 04047 cnf->refcount += refcount; 04048 } 04049 AST_LIST_UNLOCK(&confs); 04050 04051 if (!cnf) { 04052 char *pin = NULL, *pinadmin = NULL; /* For temp use */ 04053 int maxusers = 0; 04054 struct timeval now; 04055 char recordingfilename[256] = ""; 04056 char recordingformat[11] = ""; 04057 char currenttime[32] = ""; 04058 char eatime[32] = ""; 04059 char bookid[51] = ""; 04060 char recordingtmp[AST_MAX_EXTENSION] = ""; 04061 char useropts[OPTIONS_LEN + 1] = ""; /* Used for RealTime conferences */ 04062 char adminopts[OPTIONS_LEN + 1] = ""; 04063 struct ast_tm tm, etm; 04064 struct timeval endtime = { .tv_sec = 0 }; 04065 const char *var2; 04066 04067 if (rt_schedule) { 04068 now = ast_tvnow(); 04069 04070 ast_localtime(&now, &tm, NULL); 04071 ast_strftime(currenttime, sizeof(currenttime), DATE_FORMAT, &tm); 04072 04073 ast_debug(1, "Looking for conference %s that starts after %s\n", confno, currenttime); 04074 04075 var = ast_load_realtime("meetme", "confno", 04076 confno, "starttime <= ", currenttime, "endtime >= ", 04077 currenttime, NULL); 04078 04079 if (!var && fuzzystart) { 04080 now = ast_tvnow(); 04081 now.tv_sec += fuzzystart; 04082 04083 ast_localtime(&now, &tm, NULL); 04084 ast_strftime(currenttime, sizeof(currenttime), DATE_FORMAT, &tm); 04085 var = ast_load_realtime("meetme", "confno", 04086 confno, "starttime <= ", currenttime, "endtime >= ", 04087 currenttime, NULL); 04088 } 04089 04090 if (!var && earlyalert) { 04091 now = ast_tvnow(); 04092 now.tv_sec += earlyalert; 04093 ast_localtime(&now, &etm, NULL); 04094 ast_strftime(eatime, sizeof(eatime), DATE_FORMAT, &etm); 04095 var = ast_load_realtime("meetme", "confno", 04096 confno, "starttime <= ", eatime, "endtime >= ", 04097 currenttime, NULL); 04098 if (var) { 04099 *too_early = 1; 04100 } 04101 } 04102 04103 } else { 04104 var = ast_load_realtime("meetme", "confno", confno, NULL); 04105 } 04106 04107 if (!var) { 04108 return NULL; 04109 } 04110 04111 if (rt_schedule && *too_early) { 04112 /* Announce that the caller is early and exit */ 04113 if (!ast_streamfile(chan, "conf-has-not-started", chan->language)) { 04114 ast_waitstream(chan, ""); 04115 } 04116 ast_variables_destroy(var); 04117 return NULL; 04118 } 04119 04120 for (origvar = var; var; var = var->next) { 04121 if (!strcasecmp(var->name, "pin")) { 04122 pin = ast_strdupa(var->value); 04123 } else if (!strcasecmp(var->name, "adminpin")) { 04124 pinadmin = ast_strdupa(var->value); 04125 } else if (!strcasecmp(var->name, "bookId")) { 04126 ast_copy_string(bookid, var->value, sizeof(bookid)); 04127 } else if (!strcasecmp(var->name, "opts")) { 04128 ast_copy_string(useropts, var->value, sizeof(char[OPTIONS_LEN + 1])); 04129 } else if (!strcasecmp(var->name, "maxusers")) { 04130 maxusers = atoi(var->value); 04131 } else if (!strcasecmp(var->name, "adminopts")) { 04132 ast_copy_string(adminopts, var->value, sizeof(char[OPTIONS_LEN + 1])); 04133 } else if (!strcasecmp(var->name, "recordingfilename")) { 04134 ast_copy_string(recordingfilename, var->value, sizeof(recordingfilename)); 04135 } else if (!strcasecmp(var->name, "recordingformat")) { 04136 ast_copy_string(recordingformat, var->value, sizeof(recordingformat)); 04137 } else if (!strcasecmp(var->name, "endtime")) { 04138 struct ast_tm endtime_tm; 04139 ast_strptime(var->value, "%Y-%m-%d %H:%M:%S", &endtime_tm); 04140 endtime = ast_mktime(&endtime_tm, NULL); 04141 } 04142 } 04143 04144 ast_variables_destroy(origvar); 04145 04146 cnf = build_conf(confno, pin ? pin : "", pinadmin ? pinadmin : "", make, dynamic, refcount, chan, NULL); 04147 04148 if (cnf) { 04149 struct ast_flags64 tmp_flags; 04150 04151 cnf->maxusers = maxusers; 04152 cnf->endalert = endalert; 04153 cnf->endtime = endtime.tv_sec; 04154 cnf->useropts = ast_strdup(useropts); 04155 cnf->adminopts = ast_strdup(adminopts); 04156 cnf->bookid = ast_strdup(bookid); 04157 if (!ast_strlen_zero(recordingfilename)) { 04158 cnf->recordingfilename = ast_strdup(recordingfilename); 04159 } 04160 if (!ast_strlen_zero(recordingformat)) { 04161 cnf->recordingformat = ast_strdup(recordingformat); 04162 } 04163 04164 /* Parse the other options into confflags -- need to do this in two 04165 * steps, because the parse_options routine zeroes the buffer. */ 04166 ast_app_parse_options64(meetme_opts, &tmp_flags, optargs, useropts); 04167 ast_copy_flags64(confflags, &tmp_flags, tmp_flags.flags); 04168 04169 if (strchr(cnf->useropts, 'r')) { 04170 if (ast_strlen_zero(recordingfilename)) { /* If the recordingfilename in the database is empty, use the channel definition or use the default. */ 04171 ast_channel_lock(chan); 04172 if ((var2 = pbx_builtin_getvar_helper(chan, "MEETME_RECORDINGFILE"))) { 04173 ast_free(cnf->recordingfilename); 04174 cnf->recordingfilename = ast_strdup(var2); 04175 } 04176 ast_channel_unlock(chan); 04177 if (ast_strlen_zero(cnf->recordingfilename)) { 04178 snprintf(recordingtmp, sizeof(recordingtmp), "meetme-conf-rec-%s-%s", cnf->confno, chan->uniqueid); 04179 ast_free(cnf->recordingfilename); 04180 cnf->recordingfilename = ast_strdup(recordingtmp); 04181 } 04182 } 04183 if (ast_strlen_zero(cnf->recordingformat)) {/* If the recording format is empty, use the wav as default */ 04184 ast_channel_lock(chan); 04185 if ((var2 = pbx_builtin_getvar_helper(chan, "MEETME_RECORDINGFORMAT"))) { 04186 ast_free(cnf->recordingformat); 04187 cnf->recordingformat = ast_strdup(var2); 04188 } 04189 ast_channel_unlock(chan); 04190 if (ast_strlen_zero(cnf->recordingformat)) { 04191 ast_free(cnf->recordingformat); 04192 cnf->recordingformat = ast_strdup("wav"); 04193 } 04194 } 04195 ast_verb(4, "Starting recording of MeetMe Conference %s into file %s.%s.\n", cnf->confno, cnf->recordingfilename, cnf->recordingformat); 04196 } 04197 } 04198 } 04199 04200 if (cnf) { 04201 if (confflags->flags && !cnf->chan && 04202 !ast_test_flag64(confflags, CONFFLAG_QUIET) && 04203 ast_test_flag64(confflags, CONFFLAG_INTROUSER | CONFFLAG_INTROUSERNOREVIEW)) { 04204 ast_log(LOG_WARNING, "No DAHDI channel available for conference, user introduction disabled (is chan_dahdi loaded?)\n"); 04205 ast_clear_flag64(confflags, CONFFLAG_INTROUSER | CONFFLAG_INTROUSERNOREVIEW); 04206 } 04207 04208 if (confflags && !cnf->chan && 04209 ast_test_flag64(confflags, CONFFLAG_RECORDCONF)) { 04210 ast_log(LOG_WARNING, "No DAHDI channel available for conference, conference recording disabled (is chan_dahdi loaded?)\n"); 04211 ast_clear_flag64(confflags, CONFFLAG_RECORDCONF); 04212 } 04213 } 04214 04215 return cnf; 04216 }
static struct ast_conf_user* find_user | ( | struct ast_conference * | conf, | |
const char * | callerident | |||
) | [static, read] |
Definition at line 4693 of file app_meetme.c.
References ao2_find, and ast_conference::usercontainer.
Referenced by admin_exec().
04694 { 04695 struct ast_conf_user *user = NULL; 04696 int cid; 04697 04698 if (conf && callerident && sscanf(callerident, "%30d", &cid) == 1) { 04699 user = ao2_find(conf->usercontainer, &cid, 0); 04700 /* reference decremented later in admin_exec */ 04701 return user; 04702 } 04703 return NULL; 04704 }
static const char* get_announce_filename | ( | enum announcetypes | type | ) | [static] |
Definition at line 2157 of file app_meetme.c.
References CONF_HASJOIN, and CONF_HASLEFT.
Referenced by announce_thread().
02158 { 02159 switch (type) { 02160 case CONF_HASLEFT: 02161 return "conf-hasleft"; 02162 break; 02163 case CONF_HASJOIN: 02164 return "conf-hasjoin"; 02165 break; 02166 default: 02167 return ""; 02168 } 02169 }
static const char* istalking | ( | int | x | ) | [static] |
Definition at line 995 of file app_meetme.c.
Referenced by meetme_show_cmd().
static int load_config | ( | int | reload | ) | [static] |
Definition at line 7234 of file app_meetme.c.
References ast_log(), AST_PTHREADT_NULL, load_config_meetme(), LOG_NOTICE, sla, SLA_EVENT_RELOAD, sla_load_config(), and sla_queue_event().
Referenced by load_module(), and reload().
07235 { 07236 load_config_meetme(); 07237 07238 if (reload && sla.thread != AST_PTHREADT_NULL) { 07239 sla_queue_event(SLA_EVENT_RELOAD); 07240 ast_log(LOG_NOTICE, "A reload of the SLA configuration has been requested " 07241 "and will be completed when the system is idle.\n"); 07242 return 0; 07243 } 07244 07245 return sla_load_config(0); 07246 }
static void load_config_meetme | ( | void | ) | [static] |
Definition at line 5225 of file app_meetme.c.
References ast_config_destroy(), ast_config_load, ast_log(), ast_true(), ast_variable_retrieve(), CONFIG_FILE_NAME, CONFIG_STATUS_FILEINVALID, DEFAULT_AUDIO_BUFFERS, LOG_ERROR, LOG_NOTICE, and LOG_WARNING.
Referenced by load_config().
05226 { 05227 struct ast_config *cfg; 05228 struct ast_flags config_flags = { 0 }; 05229 const char *val; 05230 05231 if (!(cfg = ast_config_load(CONFIG_FILE_NAME, config_flags))) { 05232 return; 05233 } else if (cfg == CONFIG_STATUS_FILEINVALID) { 05234 ast_log(LOG_ERROR, "Config file " CONFIG_FILE_NAME " is in an invalid format. Aborting.\n"); 05235 return; 05236 } 05237 05238 audio_buffers = DEFAULT_AUDIO_BUFFERS; 05239 05240 /* Scheduling support is off by default */ 05241 rt_schedule = 0; 05242 fuzzystart = 0; 05243 earlyalert = 0; 05244 endalert = 0; 05245 extendby = 0; 05246 05247 /* Logging of participants defaults to ON for compatibility reasons */ 05248 rt_log_members = 1; 05249 05250 if ((val = ast_variable_retrieve(cfg, "general", "audiobuffers"))) { 05251 if ((sscanf(val, "%30d", &audio_buffers) != 1)) { 05252 ast_log(LOG_WARNING, "audiobuffers setting must be a number, not '%s'\n", val); 05253 audio_buffers = DEFAULT_AUDIO_BUFFERS; 05254 } else if ((audio_buffers < DAHDI_DEFAULT_NUM_BUFS) || (audio_buffers > DAHDI_MAX_NUM_BUFS)) { 05255 ast_log(LOG_WARNING, "audiobuffers setting must be between %d and %d\n", 05256 DAHDI_DEFAULT_NUM_BUFS, DAHDI_MAX_NUM_BUFS); 05257 audio_buffers = DEFAULT_AUDIO_BUFFERS; 05258 } 05259 if (audio_buffers != DEFAULT_AUDIO_BUFFERS) 05260 ast_log(LOG_NOTICE, "Audio buffers per channel set to %d\n", audio_buffers); 05261 } 05262 05263 if ((val = ast_variable_retrieve(cfg, "general", "schedule"))) 05264 rt_schedule = ast_true(val); 05265 if ((val = ast_variable_retrieve(cfg, "general", "logmembercount"))) 05266 rt_log_members = ast_true(val); 05267 if ((val = ast_variable_retrieve(cfg, "general", "fuzzystart"))) { 05268 if ((sscanf(val, "%30d", &fuzzystart) != 1)) { 05269 ast_log(LOG_WARNING, "fuzzystart must be a number, not '%s'\n", val); 05270 fuzzystart = 0; 05271 } 05272 } 05273 if ((val = ast_variable_retrieve(cfg, "general", "earlyalert"))) { 05274 if ((sscanf(val, "%30d", &earlyalert) != 1)) { 05275 ast_log(LOG_WARNING, "earlyalert must be a number, not '%s'\n", val); 05276 earlyalert = 0; 05277 } 05278 } 05279 if ((val = ast_variable_retrieve(cfg, "general", "endalert"))) { 05280 if ((sscanf(val, "%30d", &endalert) != 1)) { 05281 ast_log(LOG_WARNING, "endalert must be a number, not '%s'\n", val); 05282 endalert = 0; 05283 } 05284 } 05285 if ((val = ast_variable_retrieve(cfg, "general", "extendby"))) { 05286 if ((sscanf(val, "%30d", &extendby) != 1)) { 05287 ast_log(LOG_WARNING, "extendby must be a number, not '%s'\n", val); 05288 extendby = 0; 05289 } 05290 } 05291 05292 ast_config_destroy(cfg); 05293 }
static int load_module | ( | void | ) | [static] |
Definition at line 7459 of file app_meetme.c.
References action_meetmelist(), action_meetmemute(), action_meetmeunmute(), admin_exec(), ARRAY_LEN, ast_cli_register_multiple(), ast_custom_function_register, ast_data_register_multiple, ast_devstate_prov_add(), ast_manager_register_xml, ast_realtime_require_field(), ast_register_application_xml, AST_TEST_REGISTER, channel_admin_exec(), conf_exec(), count_exec(), EVENT_FLAG_CALL, EVENT_FLAG_REPORTING, load_config(), meetmestate(), RQ_UINTEGER1, RQ_UINTEGER2, sla_state(), sla_station_exec(), and sla_trunk_exec().
07460 { 07461 int res = 0; 07462 07463 res |= load_config(0); 07464 07465 ast_cli_register_multiple(cli_meetme, ARRAY_LEN(cli_meetme)); 07466 res |= ast_manager_register_xml("MeetmeMute", EVENT_FLAG_CALL, action_meetmemute); 07467 res |= ast_manager_register_xml("MeetmeUnmute", EVENT_FLAG_CALL, action_meetmeunmute); 07468 res |= ast_manager_register_xml("MeetmeList", EVENT_FLAG_REPORTING, action_meetmelist); 07469 res |= ast_register_application_xml(app4, channel_admin_exec); 07470 res |= ast_register_application_xml(app3, admin_exec); 07471 res |= ast_register_application_xml(app2, count_exec); 07472 res |= ast_register_application_xml(app, conf_exec); 07473 res |= ast_register_application_xml(slastation_app, sla_station_exec); 07474 res |= ast_register_application_xml(slatrunk_app, sla_trunk_exec); 07475 07476 #ifdef TEST_FRAMEWORK 07477 AST_TEST_REGISTER(test_meetme_data_provider); 07478 #endif 07479 ast_data_register_multiple(meetme_data_providers, ARRAY_LEN(meetme_data_providers)); 07480 07481 res |= ast_devstate_prov_add("Meetme", meetmestate); 07482 res |= ast_devstate_prov_add("SLA", sla_state); 07483 07484 res |= ast_custom_function_register(&meetme_info_acf); 07485 ast_realtime_require_field("meetme", "confno", RQ_UINTEGER2, 3, "members", RQ_UINTEGER1, 3, NULL); 07486 07487 return res; 07488 }
static char* meetme_cmd_helper | ( | struct ast_cli_args * | a | ) | [static] |
Definition at line 1583 of file app_meetme.c.
References admin_exec(), ast_cli_args::argv, ast_debug, ast_free, ast_str_append(), ast_str_buffer(), ast_str_create(), ast_str_set(), CLI_FAILURE, CLI_SHOWUSAGE, CLI_SUCCESS, and MAX_CONFNUM.
Referenced by meetme_kick_cmd(), meetme_lock_cmd(), and meetme_mute_cmd().
01584 { 01585 /* Process the command */ 01586 struct ast_str *cmdline; 01587 01588 /* Max confno length */ 01589 if (!(cmdline = ast_str_create(MAX_CONFNUM))) { 01590 return CLI_FAILURE; 01591 } 01592 01593 ast_str_set(&cmdline, 0, "%s", a->argv[2]); /* Argv 2: conference number */ 01594 if (strcasestr(a->argv[1], "lock")) { 01595 if (strcasecmp(a->argv[1], "lock") == 0) { 01596 /* Lock */ 01597 ast_str_append(&cmdline, 0, ",L"); 01598 } else { 01599 /* Unlock */ 01600 ast_str_append(&cmdline, 0, ",l"); 01601 } 01602 } else if (strcasestr(a->argv[1], "mute")) { 01603 if (strcasecmp(a->argv[1], "mute") == 0) { 01604 /* Mute */ 01605 if (strcasecmp(a->argv[3], "all") == 0) { 01606 ast_str_append(&cmdline, 0, ",N"); 01607 } else { 01608 ast_str_append(&cmdline, 0, ",M,%s", a->argv[3]); 01609 } 01610 } else { 01611 /* Unmute */ 01612 if (strcasecmp(a->argv[3], "all") == 0) { 01613 ast_str_append(&cmdline, 0, ",n"); 01614 } else { 01615 ast_str_append(&cmdline, 0, ",m,%s", a->argv[3]); 01616 } 01617 } 01618 } else if (strcasecmp(a->argv[1], "kick") == 0) { 01619 if (strcasecmp(a->argv[3], "all") == 0) { 01620 /* Kick all */ 01621 ast_str_append(&cmdline, 0, ",K"); 01622 } else { 01623 /* Kick a single user */ 01624 ast_str_append(&cmdline, 0, ",k,%s", a->argv[3]); 01625 } 01626 } else { 01627 /* 01628 * Should never get here because it is already filtered by the 01629 * callers. 01630 */ 01631 ast_free(cmdline); 01632 return CLI_SHOWUSAGE; 01633 } 01634 01635 ast_debug(1, "Cmdline: %s\n", ast_str_buffer(cmdline)); 01636 01637 admin_exec(NULL, ast_str_buffer(cmdline)); 01638 ast_free(cmdline); 01639 01640 return CLI_SUCCESS; 01641 }
static int meetme_data_provider_get | ( | const struct ast_data_search * | search, | |
struct ast_data * | data_root | |||
) | [static] |
Definition at line 7323 of file app_meetme.c.
References ao2_callback, ao2_container_count(), ast_data_add_node(), ast_data_add_structure, ast_data_remove_node(), ast_data_search_match(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, OBJ_NODATA, user_add_provider_cb(), and ast_conference::usercontainer.
07325 { 07326 struct ast_conference *cnf; 07327 struct ast_data *data_meetme, *data_meetme_users; 07328 07329 AST_LIST_LOCK(&confs); 07330 AST_LIST_TRAVERSE(&confs, cnf, list) { 07331 data_meetme = ast_data_add_node(data_root, "meetme"); 07332 if (!data_meetme) { 07333 continue; 07334 } 07335 07336 ast_data_add_structure(ast_conference, data_meetme, cnf); 07337 07338 if (ao2_container_count(cnf->usercontainer)) { 07339 data_meetme_users = ast_data_add_node(data_meetme, "users"); 07340 if (!data_meetme_users) { 07341 ast_data_remove_node(data_root, data_meetme); 07342 continue; 07343 } 07344 07345 ao2_callback(cnf->usercontainer, OBJ_NODATA, user_add_provider_cb, data_meetme_users); 07346 } 07347 07348 if (!ast_data_search_match(search, data_meetme)) { 07349 ast_data_remove_node(data_root, data_meetme); 07350 } 07351 } 07352 AST_LIST_UNLOCK(&confs); 07353 07354 return 0; 07355 }
static char* meetme_kick_cmd | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 1663 of file app_meetme.c.
References ast_cli_args::argc, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, ast_cli_entry::command, complete_meetmecmd_mute_kick(), ast_cli_args::line, meetme_cmd_helper(), ast_cli_args::n, ast_cli_args::pos, ast_cli_entry::usage, and ast_cli_args::word.
01664 { 01665 switch (cmd) { 01666 case CLI_INIT: 01667 e->command = "meetme kick"; 01668 e->usage = 01669 "Usage: meetme kick <confno> all|<userno>\n" 01670 " Kick a conference or a user in a conference.\n"; 01671 return NULL; 01672 case CLI_GENERATE: 01673 return complete_meetmecmd_mute_kick(a->line, a->word, a->pos, a->n); 01674 } 01675 01676 if (a->argc != 4) { 01677 return CLI_SHOWUSAGE; 01678 } 01679 01680 return meetme_cmd_helper(a); 01681 }
static char* meetme_lock_cmd | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 1643 of file app_meetme.c.
References ast_cli_args::argc, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, ast_cli_entry::command, complete_meetmecmd_lock(), meetme_cmd_helper(), ast_cli_args::n, ast_cli_args::pos, ast_cli_entry::usage, and ast_cli_args::word.
01644 { 01645 switch (cmd) { 01646 case CLI_INIT: 01647 e->command = "meetme {lock|unlock}"; 01648 e->usage = 01649 "Usage: meetme lock|unlock <confno>\n" 01650 " Lock or unlock a conference to new users.\n"; 01651 return NULL; 01652 case CLI_GENERATE: 01653 return complete_meetmecmd_lock(a->word, a->pos, a->n); 01654 } 01655 01656 if (a->argc != 3) { 01657 return CLI_SHOWUSAGE; 01658 } 01659 01660 return meetme_cmd_helper(a); 01661 }
static void meetme_menu | ( | enum menu_modes * | menu_mode, | |
int * | dtmf, | |||
struct ast_conference * | conf, | |||
struct ast_flags64 * | confflags, | |||
struct ast_channel * | chan, | |||
struct ast_conf_user * | user, | |||
char * | recordingtmp, | |||
struct dahdi_confinfo * | dahdic | |||
) | [static] |
Definition at line 2697 of file app_meetme.c.
References meetme_menu_admin(), meetme_menu_admin_extended(), meetme_menu_normal(), MENU_ADMIN, MENU_ADMIN_EXTENDED, MENU_DISABLED, and MENU_NORMAL.
Referenced by conf_run().
02698 { 02699 switch (*menu_mode) { 02700 case MENU_DISABLED: 02701 break; 02702 case MENU_NORMAL: 02703 meetme_menu_normal(menu_mode, dtmf, conf, confflags, chan, user); 02704 break; 02705 case MENU_ADMIN: 02706 meetme_menu_admin(menu_mode, dtmf, conf, confflags, chan, user); 02707 /* Admin Menu is capable of branching into another menu, in which case it will reset dtmf and change the menu mode. */ 02708 if (*menu_mode != MENU_ADMIN_EXTENDED || (*dtmf <= 0)) { 02709 break; 02710 } 02711 case MENU_ADMIN_EXTENDED: 02712 meetme_menu_admin_extended(menu_mode, dtmf, conf, confflags, chan, user, recordingtmp, dahdic); 02713 break; 02714 } 02715 }
static void meetme_menu_admin | ( | enum menu_modes * | menu_mode, | |
int * | dtmf, | |||
struct ast_conference * | conf, | |||
struct ast_flags64 * | confflags, | |||
struct ast_channel * | chan, | |||
struct ast_conf_user * | user | |||
) | [static] |
Definition at line 2392 of file app_meetme.c.
References ADMINFLAG_KICKME, ADMINFLAG_MUTED, ADMINFLAG_SELFMUTED, ast_conf_user::adminflags, ao2_callback, ao2_find, ao2_ref, AST_DIGIT_ANY, ast_stopstream(), ast_streamfile(), ast_test_flag64, ast_waitstream(), ast_conf_user::chan, CONFFLAG_ADMIN, CONFFLAG_MONITOR, ast_conference::confno, ast_conference::locked, MENU_ADMIN_EXTENDED, MENU_DISABLED, OBJ_NODATA, rt_extend_conf(), tweak_listen_volume(), tweak_talk_volume(), user_max_cmp(), ast_conference::usercontainer, ast_conf_user::userflags, VOL_DOWN, and VOL_UP.
Referenced by meetme_menu().
02393 { 02394 switch(*dtmf) { 02395 case '1': /* Un/Mute */ 02396 *menu_mode = MENU_DISABLED; 02397 /* for admin, change both admin and use flags */ 02398 if (user->adminflags & (ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED)) { 02399 user->adminflags &= ~(ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED); 02400 } else { 02401 user->adminflags |= (ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED); 02402 } 02403 02404 if (ast_test_flag64(confflags, CONFFLAG_MONITOR) || (user->adminflags & (ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED))) { 02405 if (!ast_streamfile(chan, "conf-muted", chan->language)) { 02406 ast_waitstream(chan, ""); 02407 } 02408 } else { 02409 if (!ast_streamfile(chan, "conf-unmuted", chan->language)) { 02410 ast_waitstream(chan, ""); 02411 } 02412 } 02413 break; 02414 02415 case '2': /* Un/Lock the Conference */ 02416 *menu_mode = MENU_DISABLED; 02417 if (conf->locked) { 02418 conf->locked = 0; 02419 if (!ast_streamfile(chan, "conf-unlockednow", chan->language)) { 02420 ast_waitstream(chan, ""); 02421 } 02422 } else { 02423 conf->locked = 1; 02424 if (!ast_streamfile(chan, "conf-lockednow", chan->language)) { 02425 ast_waitstream(chan, ""); 02426 } 02427 } 02428 break; 02429 02430 case '3': /* Eject last user */ 02431 { 02432 struct ast_conf_user *usr = NULL; 02433 int max_no = 0; 02434 ao2_callback(conf->usercontainer, OBJ_NODATA, user_max_cmp, &max_no); 02435 *menu_mode = MENU_DISABLED; 02436 usr = ao2_find(conf->usercontainer, &max_no, 0); 02437 if ((usr->chan->name == chan->name) || ast_test_flag64(&usr->userflags, CONFFLAG_ADMIN)) { 02438 if (!ast_streamfile(chan, "conf-errormenu", chan->language)) { 02439 ast_waitstream(chan, ""); 02440 } 02441 } else { 02442 usr->adminflags |= ADMINFLAG_KICKME; 02443 } 02444 ao2_ref(usr, -1); 02445 ast_stopstream(chan); 02446 break; 02447 } 02448 02449 case '4': 02450 tweak_listen_volume(user, VOL_DOWN); 02451 break; 02452 02453 case '5': 02454 /* Extend RT conference */ 02455 if (rt_schedule) { 02456 if (!rt_extend_conf(conf->confno)) { 02457 if (!ast_streamfile(chan, "conf-extended", chan->language)) { 02458 ast_waitstream(chan, ""); 02459 } 02460 } else { 02461 if (!ast_streamfile(chan, "conf-nonextended", chan->language)) { 02462 ast_waitstream(chan, ""); 02463 } 02464 } 02465 ast_stopstream(chan); 02466 } 02467 *menu_mode = MENU_DISABLED; 02468 break; 02469 02470 case '6': 02471 tweak_listen_volume(user, VOL_UP); 02472 break; 02473 02474 case '7': 02475 tweak_talk_volume(user, VOL_DOWN); 02476 break; 02477 02478 case '8': 02479 if (!ast_streamfile(chan, "conf-adminmenu-menu8", chan->language)) { 02480 /* If the user provides DTMF while playing the sound, we want to drop right into the extended menu function with new DTMF once we get out of here. */ 02481 *dtmf = ast_waitstream(chan, AST_DIGIT_ANY); 02482 ast_stopstream(chan); 02483 } 02484 *menu_mode = MENU_ADMIN_EXTENDED; 02485 break; 02486 02487 case '9': 02488 tweak_talk_volume(user, VOL_UP); 02489 break; 02490 default: 02491 menu_mode = MENU_DISABLED; 02492 /* Play an error message! */ 02493 if (!ast_streamfile(chan, "conf-errormenu", chan->language)) { 02494 ast_waitstream(chan, ""); 02495 } 02496 break; 02497 } 02498 02499 }
static void meetme_menu_admin_extended | ( | enum menu_modes * | menu_mode, | |
int * | dtmf, | |||
struct ast_conference * | conf, | |||
struct ast_flags64 * | confflags, | |||
struct ast_channel * | chan, | |||
struct ast_conf_user * | user, | |||
char * | recordingtmp, | |||
struct dahdi_confinfo * | dahdic | |||
) | [static] |
Definition at line 2513 of file app_meetme.c.
References ao2_callback, ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_ref, ast_channel_lock, ast_channel_unlock, AST_DIGIT_ANY, ast_fileexists(), AST_FORMAT_SLINEAR, ast_hangup(), ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_pthread_create_detached_background, AST_PTHREADT_NULL, ast_request(), ast_say_number(), ast_set_flag64, ast_set_read_format(), ast_set_write_format(), ast_stopstream(), ast_strdup, ast_streamfile(), ast_test_flag64, ast_verb, ast_waitstream(), CONFFLAG_RECORDCONF, ast_conference::confno, ast_conference::dahdiconf, ast_channel::fds, ast_conference::gmuted, ast_conference::lchan, LOG_WARNING, MEETME_RECORD_ACTIVE, MENU_DISABLED, ast_conf_user::namerecloc, OBJ_NODATA, pbx_builtin_getvar_helper(), ast_conference::recordingfilename, ast_conference::recordingformat, ast_conference::recordthread, ast_conference::recordthreadlock, user_set_kickme_cb(), user_set_muted_cb(), user_set_unmuted_cb(), ast_conference::usercontainer, ast_conference::users, and var.
Referenced by meetme_menu().
02514 { 02515 int keepplaying; 02516 int playednamerec; 02517 int res; 02518 struct ao2_iterator user_iter; 02519 struct ast_conf_user *usr = NULL; 02520 02521 switch(*dtmf) { 02522 case '1': /* *81 Roll call */ 02523 keepplaying = 1; 02524 playednamerec = 0; 02525 if (conf->users == 1) { 02526 if (keepplaying && !ast_streamfile(chan, "conf-onlyperson", chan->language)) { 02527 res = ast_waitstream(chan, AST_DIGIT_ANY); 02528 ast_stopstream(chan); 02529 if (res > 0) { 02530 keepplaying = 0; 02531 } 02532 } 02533 } else if (conf->users == 2) { 02534 if (keepplaying && !ast_streamfile(chan, "conf-onlyone", chan->language)) { 02535 res = ast_waitstream(chan, AST_DIGIT_ANY); 02536 ast_stopstream(chan); 02537 if (res > 0) { 02538 keepplaying = 0; 02539 } 02540 } 02541 } else { 02542 if (keepplaying && !ast_streamfile(chan, "conf-thereare", chan->language)) { 02543 res = ast_waitstream(chan, AST_DIGIT_ANY); 02544 ast_stopstream(chan); 02545 if (res > 0) { 02546 keepplaying = 0; 02547 } 02548 } 02549 if (keepplaying) { 02550 res = ast_say_number(chan, conf->users - 1, AST_DIGIT_ANY, chan->language, (char *) NULL); 02551 ast_stopstream(chan); 02552 if (res > 0) { 02553 keepplaying = 0; 02554 } 02555 } 02556 if (keepplaying && !ast_streamfile(chan, "conf-otherinparty", chan->language)) { 02557 res = ast_waitstream(chan, AST_DIGIT_ANY); 02558 ast_stopstream(chan); 02559 if (res > 0) { 02560 keepplaying = 0; 02561 } 02562 } 02563 } 02564 user_iter = ao2_iterator_init(conf->usercontainer, 0); 02565 while((usr = ao2_iterator_next(&user_iter))) { 02566 if (ast_fileexists(usr->namerecloc, NULL, NULL)) { 02567 if (keepplaying && !ast_streamfile(chan, usr->namerecloc, chan->language)) { 02568 res = ast_waitstream(chan, AST_DIGIT_ANY); 02569 ast_stopstream(chan); 02570 if (res > 0) { 02571 keepplaying = 0; 02572 } 02573 } 02574 playednamerec = 1; 02575 } 02576 ao2_ref(usr, -1); 02577 } 02578 ao2_iterator_destroy(&user_iter); 02579 if (keepplaying && playednamerec && !ast_streamfile(chan, "conf-roll-callcomplete", chan->language)) { 02580 res = ast_waitstream(chan, AST_DIGIT_ANY); 02581 ast_stopstream(chan); 02582 if (res > 0) { 02583 keepplaying = 0; 02584 } 02585 } 02586 02587 *menu_mode = MENU_DISABLED; 02588 break; 02589 02590 case '2': /* *82 Eject all non-admins */ 02591 if (conf->users == 1) { 02592 if(!ast_streamfile(chan, "conf-errormenu", chan->language)) { 02593 ast_waitstream(chan, ""); 02594 } 02595 } else { 02596 ao2_callback(conf->usercontainer, OBJ_NODATA, user_set_kickme_cb, &conf); 02597 } 02598 ast_stopstream(chan); 02599 *menu_mode = MENU_DISABLED; 02600 break; 02601 02602 case '3': /* *83 (Admin) mute/unmute all non-admins */ 02603 if(conf->gmuted) { 02604 conf->gmuted = 0; 02605 ao2_callback(conf->usercontainer, OBJ_NODATA, user_set_unmuted_cb, &conf); 02606 if (!ast_streamfile(chan, "conf-now-unmuted", chan->language)) { 02607 ast_waitstream(chan, ""); 02608 } 02609 } else { 02610 conf->gmuted = 1; 02611 ao2_callback(conf->usercontainer, OBJ_NODATA, user_set_muted_cb, &conf); 02612 if (!ast_streamfile(chan, "conf-now-muted", chan->language)) { 02613 ast_waitstream(chan, ""); 02614 } 02615 } 02616 ast_stopstream(chan); 02617 *menu_mode = MENU_DISABLED; 02618 break; 02619 02620 case '4': /* *84 Record conference */ 02621 if (conf->recording != MEETME_RECORD_ACTIVE) { 02622 ast_set_flag64(confflags, CONFFLAG_RECORDCONF); 02623 if (!conf->recordingfilename) { 02624 const char *var; 02625 ast_channel_lock(chan); 02626 if ((var = pbx_builtin_getvar_helper(chan, "MEETME_RECORDINGFILE"))) { 02627 conf->recordingfilename = ast_strdup(var); 02628 } 02629 if ((var = pbx_builtin_getvar_helper(chan, "MEETME_RECORDINGFORMAT"))) { 02630 conf->recordingformat = ast_strdup(var); 02631 } 02632 ast_channel_unlock(chan); 02633 if (!conf->recordingfilename) { 02634 snprintf(recordingtmp, sizeof(recordingtmp), "meetme-conf-rec-%s-%s", conf->confno, chan->uniqueid); 02635 conf->recordingfilename = ast_strdup(recordingtmp); 02636 } 02637 if (!conf->recordingformat) { 02638 conf->recordingformat = ast_strdup("wav"); 02639 } 02640 ast_verb(4, "Starting recording of MeetMe Conference %s into file %s.%s.\n", 02641 conf->confno, conf->recordingfilename, conf->recordingformat); 02642 } 02643 02644 ast_mutex_lock(&conf->recordthreadlock); 02645 if ((conf->recordthread == AST_PTHREADT_NULL) && ast_test_flag64(confflags, CONFFLAG_RECORDCONF) && ((conf->lchan = ast_request("DAHDI", AST_FORMAT_SLINEAR, chan, "pseudo", NULL)))) { 02646 ast_set_read_format(conf->lchan, AST_FORMAT_SLINEAR); 02647 ast_set_write_format(conf->lchan, AST_FORMAT_SLINEAR); 02648 dahdic->chan = 0; 02649 dahdic->confno = conf->dahdiconf; 02650 dahdic->confmode = DAHDI_CONF_CONFANN | DAHDI_CONF_CONFANNMON; 02651 if (ioctl(conf->lchan->fds[0], DAHDI_SETCONF, dahdic)) { 02652 ast_log(LOG_WARNING, "Error starting listen channel\n"); 02653 ast_hangup(conf->lchan); 02654 conf->lchan = NULL; 02655 } else { 02656 ast_pthread_create_detached_background(&conf->recordthread, NULL, recordthread, conf); 02657 } 02658 } 02659 ast_mutex_unlock(&conf->recordthreadlock); 02660 if (!ast_streamfile(chan, "conf-now-recording", chan->language)) { 02661 ast_waitstream(chan, ""); 02662 } 02663 } 02664 02665 ast_stopstream(chan); 02666 *menu_mode = MENU_DISABLED; 02667 break; 02668 02669 case '8': /* *88 Exit the menu and return to the conference... without an error message */ 02670 ast_stopstream(chan); 02671 *menu_mode = MENU_DISABLED; 02672 break; 02673 02674 default: 02675 if (!ast_streamfile(chan, "conf-errormenu", chan->language)) { 02676 ast_waitstream(chan, ""); 02677 } 02678 ast_stopstream(chan); 02679 *menu_mode = MENU_DISABLED; 02680 break; 02681 } 02682 }
static void meetme_menu_normal | ( | enum menu_modes * | menu_mode, | |
int * | dtmf, | |||
struct ast_conference * | conf, | |||
struct ast_flags64 * | confflags, | |||
struct ast_channel * | chan, | |||
struct ast_conf_user * | user | |||
) | [static] |
Definition at line 2312 of file app_meetme.c.
References ADMINFLAG_MUTED, ADMINFLAG_SELFMUTED, ADMINFLAG_T_REQUEST, ast_conf_user::adminflags, ast_streamfile(), ast_test_flag64, ast_waitstream(), CONFFLAG_MONITOR, ast_conference::confno, MENU_DISABLED, rt_extend_conf(), tweak_listen_volume(), tweak_talk_volume(), VOL_DOWN, and VOL_UP.
Referenced by meetme_menu().
02313 { 02314 switch (*dtmf) { 02315 case '1': /* Un/Mute */ 02316 *menu_mode = MENU_DISABLED; 02317 02318 /* user can only toggle the self-muted state */ 02319 user->adminflags ^= ADMINFLAG_SELFMUTED; 02320 02321 /* they can't override the admin mute state */ 02322 if (ast_test_flag64(confflags, CONFFLAG_MONITOR) || (user->adminflags & (ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED))) { 02323 if (!ast_streamfile(chan, "conf-muted", chan->language)) { 02324 ast_waitstream(chan, ""); 02325 } 02326 } else { 02327 if (!ast_streamfile(chan, "conf-unmuted", chan->language)) { 02328 ast_waitstream(chan, ""); 02329 } 02330 } 02331 break; 02332 02333 case '2': 02334 *menu_mode = MENU_DISABLED; 02335 if (user->adminflags & (ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED)) { 02336 user->adminflags |= ADMINFLAG_T_REQUEST; 02337 } 02338 02339 if (user->adminflags & ADMINFLAG_T_REQUEST) { 02340 if (!ast_streamfile(chan, "beep", chan->language)) { 02341 ast_waitstream(chan, ""); 02342 } 02343 } 02344 break; 02345 02346 case '4': 02347 tweak_listen_volume(user, VOL_DOWN); 02348 break; 02349 case '5': 02350 /* Extend RT conference */ 02351 if (rt_schedule) { 02352 rt_extend_conf(conf->confno); 02353 } 02354 *menu_mode = MENU_DISABLED; 02355 break; 02356 02357 case '6': 02358 tweak_listen_volume(user, VOL_UP); 02359 break; 02360 02361 case '7': 02362 tweak_talk_volume(user, VOL_DOWN); 02363 break; 02364 02365 case '8': 02366 *menu_mode = MENU_DISABLED; 02367 break; 02368 02369 case '9': 02370 tweak_talk_volume(user, VOL_UP); 02371 break; 02372 02373 default: 02374 *menu_mode = MENU_DISABLED; 02375 if (!ast_streamfile(chan, "conf-errormenu", chan->language)) { 02376 ast_waitstream(chan, ""); 02377 } 02378 break; 02379 } 02380 }
static char* meetme_mute_cmd | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 1683 of file app_meetme.c.
References ast_cli_args::argc, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, ast_cli_entry::command, complete_meetmecmd_mute_kick(), ast_cli_args::line, meetme_cmd_helper(), ast_cli_args::n, ast_cli_args::pos, ast_cli_entry::usage, and ast_cli_args::word.
01684 { 01685 switch (cmd) { 01686 case CLI_INIT: 01687 e->command = "meetme {mute|unmute}"; 01688 e->usage = 01689 "Usage: meetme mute|unmute <confno> all|<userno>\n" 01690 " Mute or unmute a conference or a user in a conference.\n"; 01691 return NULL; 01692 case CLI_GENERATE: 01693 return complete_meetmecmd_mute_kick(a->line, a->word, a->pos, a->n); 01694 } 01695 01696 if (a->argc != 4) { 01697 return CLI_SHOWUSAGE; 01698 } 01699 01700 return meetme_cmd_helper(a); 01701 }
static char* meetme_show_cmd | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 1440 of file app_meetme.c.
References ADMINFLAG_MUTED, ADMINFLAG_SELFMUTED, ADMINFLAG_T_REQUEST, ast_conf_user::adminflags, ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_ref, ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_free, AST_LIST_EMPTY, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_str_buffer(), ast_str_create(), ast_str_set(), ast_test_flag64, ast_channel::caller, ast_conf_user::chan, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_meetmecmd_list(), CONFFLAG_ADMIN, CONFFLAG_MONITOR, ast_conference::confno, ast_cli_args::fd, ast_party_caller::id, ast_conference::isdynamic, istalking(), ast_conf_user::jointime, ast_cli_args::line, ast_conference::locked, ast_conference::markedusers, MC_DATA_FORMAT, MC_HEADER_FORMAT, ast_cli_args::n, ast_party_id::name, ast_party_id::number, ast_cli_args::pos, S_COR, ast_conference::start, ast_party_name::str, ast_party_number::str, STR_CONCISE, ast_conf_user::talking, total, ast_cli_entry::usage, ast_conf_user::user_no, ast_conference::usercontainer, ast_conf_user::userflags, ast_conference::users, ast_party_name::valid, ast_party_number::valid, and ast_cli_args::word.
01441 { 01442 /* Process the command */ 01443 struct ast_conf_user *user; 01444 struct ast_conference *cnf; 01445 int hr, min, sec; 01446 int total = 0; 01447 time_t now; 01448 #define MC_HEADER_FORMAT "%-14s %-14s %-10s %-8s %-8s %-6s\n" 01449 #define MC_DATA_FORMAT "%-12.12s %4.4d %4.4s %02d:%02d:%02d %-8s %-6s\n" 01450 01451 switch (cmd) { 01452 case CLI_INIT: 01453 e->command = "meetme list"; 01454 e->usage = 01455 "Usage: meetme list [<confno>] [" STR_CONCISE "]\n" 01456 " List all conferences or a specific conference.\n"; 01457 return NULL; 01458 case CLI_GENERATE: 01459 return complete_meetmecmd_list(a->line, a->word, a->pos, a->n); 01460 } 01461 01462 if (a->argc == 2 || (a->argc == 3 && !strcasecmp(a->argv[2], STR_CONCISE))) { 01463 /* List all the conferences */ 01464 int concise = (a->argc == 3); 01465 struct ast_str *marked_users; 01466 01467 if (!(marked_users = ast_str_create(30))) { 01468 return CLI_FAILURE; 01469 } 01470 01471 now = time(NULL); 01472 AST_LIST_LOCK(&confs); 01473 if (AST_LIST_EMPTY(&confs)) { 01474 if (!concise) { 01475 ast_cli(a->fd, "No active MeetMe conferences.\n"); 01476 } 01477 AST_LIST_UNLOCK(&confs); 01478 ast_free(marked_users); 01479 return CLI_SUCCESS; 01480 } 01481 if (!concise) { 01482 ast_cli(a->fd, MC_HEADER_FORMAT, "Conf Num", "Parties", "Marked", "Activity", "Creation", "Locked"); 01483 } 01484 AST_LIST_TRAVERSE(&confs, cnf, list) { 01485 hr = (now - cnf->start) / 3600; 01486 min = ((now - cnf->start) % 3600) / 60; 01487 sec = (now - cnf->start) % 60; 01488 if (!concise) { 01489 if (cnf->markedusers == 0) { 01490 ast_str_set(&marked_users, 0, "N/A "); 01491 } else { 01492 ast_str_set(&marked_users, 0, "%4.4d", cnf->markedusers); 01493 } 01494 ast_cli(a->fd, MC_DATA_FORMAT, cnf->confno, cnf->users, 01495 ast_str_buffer(marked_users), hr, min, sec, 01496 cnf->isdynamic ? "Dynamic" : "Static", cnf->locked ? "Yes" : "No"); 01497 } else { 01498 ast_cli(a->fd, "%s!%d!%d!%02d:%02d:%02d!%d!%d\n", 01499 cnf->confno, 01500 cnf->users, 01501 cnf->markedusers, 01502 hr, min, sec, 01503 cnf->isdynamic, 01504 cnf->locked); 01505 } 01506 01507 total += cnf->users; 01508 } 01509 AST_LIST_UNLOCK(&confs); 01510 if (!concise) { 01511 ast_cli(a->fd, "* Total number of MeetMe users: %d\n", total); 01512 } 01513 ast_free(marked_users); 01514 return CLI_SUCCESS; 01515 } 01516 if (a->argc == 3 || (a->argc == 4 && !strcasecmp(a->argv[3], STR_CONCISE))) { 01517 struct ao2_iterator user_iter; 01518 int concise = (a->argc == 4); 01519 01520 /* List all the users in a conference */ 01521 if (AST_LIST_EMPTY(&confs)) { 01522 if (!concise) { 01523 ast_cli(a->fd, "No active MeetMe conferences.\n"); 01524 } 01525 return CLI_SUCCESS; 01526 } 01527 /* Find the right conference */ 01528 AST_LIST_LOCK(&confs); 01529 AST_LIST_TRAVERSE(&confs, cnf, list) { 01530 if (strcmp(cnf->confno, a->argv[2]) == 0) { 01531 break; 01532 } 01533 } 01534 if (!cnf) { 01535 if (!concise) 01536 ast_cli(a->fd, "No such conference: %s.\n", a->argv[2]); 01537 AST_LIST_UNLOCK(&confs); 01538 return CLI_SUCCESS; 01539 } 01540 /* Show all the users */ 01541 time(&now); 01542 user_iter = ao2_iterator_init(cnf->usercontainer, 0); 01543 while((user = ao2_iterator_next(&user_iter))) { 01544 hr = (now - user->jointime) / 3600; 01545 min = ((now - user->jointime) % 3600) / 60; 01546 sec = (now - user->jointime) % 60; 01547 if (!concise) { 01548 ast_cli(a->fd, "User #: %-2.2d %12.12s %-20.20s Channel: %s %s %s %s %s %s %02d:%02d:%02d\n", 01549 user->user_no, 01550 S_COR(user->chan->caller.id.number.valid, user->chan->caller.id.number.str, "<unknown>"), 01551 S_COR(user->chan->caller.id.name.valid, user->chan->caller.id.name.str, "<no name>"), 01552 user->chan->name, 01553 ast_test_flag64(&user->userflags, CONFFLAG_ADMIN) ? "(Admin)" : "", 01554 ast_test_flag64(&user->userflags, CONFFLAG_MONITOR) ? "(Listen only)" : "", 01555 user->adminflags & ADMINFLAG_MUTED ? "(Admin Muted)" : user->adminflags & ADMINFLAG_SELFMUTED ? "(Muted)" : "", 01556 user->adminflags & ADMINFLAG_T_REQUEST ? "(Request to Talk)" : "", 01557 istalking(user->talking), hr, min, sec); 01558 } else { 01559 ast_cli(a->fd, "%d!%s!%s!%s!%s!%s!%s!%s!%d!%02d:%02d:%02d\n", 01560 user->user_no, 01561 S_COR(user->chan->caller.id.number.valid, user->chan->caller.id.number.str, ""), 01562 S_COR(user->chan->caller.id.name.valid, user->chan->caller.id.name.str, ""), 01563 user->chan->name, 01564 ast_test_flag64(&user->userflags, CONFFLAG_ADMIN) ? "1" : "", 01565 ast_test_flag64(&user->userflags, CONFFLAG_MONITOR) ? "1" : "", 01566 user->adminflags & (ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED) ? "1" : "", 01567 user->adminflags & ADMINFLAG_T_REQUEST ? "1" : "", 01568 user->talking, hr, min, sec); 01569 } 01570 ao2_ref(user, -1); 01571 } 01572 ao2_iterator_destroy(&user_iter); 01573 if (!concise) { 01574 ast_cli(a->fd, "%d users in that conference.\n", cnf->users); 01575 } 01576 AST_LIST_UNLOCK(&confs); 01577 return CLI_SUCCESS; 01578 } 01579 return CLI_SHOWUSAGE; 01580 }
static int meetmemute | ( | struct mansession * | s, | |
const struct message * | m, | |||
int | mute | |||
) | [static] |
Definition at line 4964 of file app_meetme.c.
References ADMINFLAG_MUTED, ADMINFLAG_SELFMUTED, ADMINFLAG_T_REQUEST, ast_conf_user::adminflags, ao2_find, ao2_ref, 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, ast_conf_user::user_no, and ast_conference::usercontainer.
Referenced by action_meetmemute(), and action_meetmeunmute().
04965 { 04966 struct ast_conference *conf; 04967 struct ast_conf_user *user; 04968 const char *confid = astman_get_header(m, "Meetme"); 04969 char *userid = ast_strdupa(astman_get_header(m, "Usernum")); 04970 int userno; 04971 04972 if (ast_strlen_zero(confid)) { 04973 astman_send_error(s, m, "Meetme conference not specified"); 04974 return 0; 04975 } 04976 04977 if (ast_strlen_zero(userid)) { 04978 astman_send_error(s, m, "Meetme user number not specified"); 04979 return 0; 04980 } 04981 04982 userno = strtoul(userid, &userid, 10); 04983 04984 if (*userid) { 04985 astman_send_error(s, m, "Invalid user number"); 04986 return 0; 04987 } 04988 04989 /* Look in the conference list */ 04990 AST_LIST_LOCK(&confs); 04991 AST_LIST_TRAVERSE(&confs, conf, list) { 04992 if (!strcmp(confid, conf->confno)) 04993 break; 04994 } 04995 04996 if (!conf) { 04997 AST_LIST_UNLOCK(&confs); 04998 astman_send_error(s, m, "Meetme conference does not exist"); 04999 return 0; 05000 } 05001 05002 user = ao2_find(conf->usercontainer, &userno, 0); 05003 05004 if (!user) { 05005 AST_LIST_UNLOCK(&confs); 05006 astman_send_error(s, m, "User number not found"); 05007 return 0; 05008 } 05009 05010 if (mute) 05011 user->adminflags |= ADMINFLAG_MUTED; /* request user muting */ 05012 else 05013 user->adminflags &= ~(ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED | ADMINFLAG_T_REQUEST); /* request user unmuting */ 05014 05015 AST_LIST_UNLOCK(&confs); 05016 05017 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); 05018 05019 ao2_ref(user, -1); 05020 astman_send_ack(s, m, mute ? "User muted" : "User unmuted"); 05021 return 0; 05022 }
static enum ast_device_state meetmestate | ( | const char * | data | ) | [static] |
Callback for devicestate providers.
Definition at line 5203 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().
05204 { 05205 struct ast_conference *conf; 05206 05207 /* Find conference */ 05208 AST_LIST_LOCK(&confs); 05209 AST_LIST_TRAVERSE(&confs, conf, list) { 05210 if (!strcmp(data, conf->confno)) 05211 break; 05212 } 05213 AST_LIST_UNLOCK(&confs); 05214 if (!conf) 05215 return AST_DEVICE_INVALID; 05216 05217 05218 /* SKREP to fill */ 05219 if (!conf->users) 05220 return AST_DEVICE_NOT_INUSE; 05221 05222 return AST_DEVICE_INUSE; 05223 }
static struct sla_ringing_trunk* queue_ringing_trunk | ( | struct sla_trunk * | trunk | ) | [static, read] |
Definition at line 6584 of file app_meetme.c.
References ALL_TRUNK_REFS, ast_calloc, AST_LIST_INSERT_HEAD, ast_mutex_lock, ast_mutex_unlock, ast_tvnow(), 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().
06585 { 06586 struct sla_ringing_trunk *ringing_trunk; 06587 06588 if (!(ringing_trunk = ast_calloc(1, sizeof(*ringing_trunk)))) 06589 return NULL; 06590 06591 ringing_trunk->trunk = trunk; 06592 ringing_trunk->ring_begin = ast_tvnow(); 06593 06594 sla_change_trunk_state(trunk, SLA_TRUNK_STATE_RINGING, ALL_TRUNK_REFS, NULL); 06595 06596 ast_mutex_lock(&sla.lock); 06597 AST_LIST_INSERT_HEAD(&sla.ringing_trunks, ringing_trunk, entry); 06598 ast_mutex_unlock(&sla.lock); 06599 06600 sla_queue_event(SLA_EVENT_RINGING_TRUNK); 06601 06602 return ringing_trunk; 06603 }
static void * recordthread | ( | void * | args | ) | [static] |
Definition at line 5134 of file app_meetme.c.
References ast_closestream(), AST_FILE_MODE, 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_strlen_zero(), ast_waitfor(), ast_writefile(), ast_writestream(), f, filename_parse(), ast_frame::flags, 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, and ast_conference::transframe.
05135 { 05136 struct ast_conference *cnf = args; 05137 struct ast_frame *f = NULL; 05138 int flags; 05139 struct ast_filestream *s = NULL; 05140 int res = 0; 05141 int x; 05142 const char *oldrecordingfilename = NULL; 05143 char filename_buffer[PATH_MAX]; 05144 05145 if (!cnf || !cnf->lchan) { 05146 pthread_exit(0); 05147 } 05148 05149 filename_buffer[0] = '\0'; 05150 filename_parse(cnf->recordingfilename, filename_buffer); 05151 05152 ast_stopstream(cnf->lchan); 05153 flags = O_CREAT | O_TRUNC | O_WRONLY; 05154 05155 05156 cnf->recording = MEETME_RECORD_ACTIVE; 05157 while (ast_waitfor(cnf->lchan, -1) > -1) { 05158 if (cnf->recording == MEETME_RECORD_TERMINATE) { 05159 AST_LIST_LOCK(&confs); 05160 AST_LIST_UNLOCK(&confs); 05161 break; 05162 } 05163 if (!s && !(ast_strlen_zero(filename_buffer)) && (filename_buffer != oldrecordingfilename)) { 05164 s = ast_writefile(filename_buffer, cnf->recordingformat, NULL, flags, 0, AST_FILE_MODE); 05165 oldrecordingfilename = filename_buffer; 05166 } 05167 05168 f = ast_read(cnf->lchan); 05169 if (!f) { 05170 res = -1; 05171 break; 05172 } 05173 if (f->frametype == AST_FRAME_VOICE) { 05174 ast_mutex_lock(&cnf->listenlock); 05175 for (x = 0; x < AST_FRAME_BITS; x++) { 05176 /* Free any translations that have occured */ 05177 if (cnf->transframe[x]) { 05178 ast_frfree(cnf->transframe[x]); 05179 cnf->transframe[x] = NULL; 05180 } 05181 } 05182 if (cnf->origframe) 05183 ast_frfree(cnf->origframe); 05184 cnf->origframe = ast_frdup(f); 05185 ast_mutex_unlock(&cnf->listenlock); 05186 if (s) 05187 res = ast_writestream(s, f); 05188 if (res) { 05189 ast_frfree(f); 05190 break; 05191 } 05192 } 05193 ast_frfree(f); 05194 } 05195 cnf->recording = MEETME_RECORD_OFF; 05196 if (s) 05197 ast_closestream(s); 05198 05199 pthread_exit(0); 05200 }
static int reload | ( | void | ) | [static] |
Definition at line 7490 of file app_meetme.c.
References ast_unload_realtime(), and load_config().
07491 { 07492 ast_unload_realtime("meetme"); 07493 return load_config(1); 07494 }
static void reset_volumes | ( | struct ast_conf_user * | user | ) | [static] |
Definition at line 1115 of file app_meetme.c.
References ast_channel_setoption(), AST_OPTION_RXGAIN, AST_OPTION_TXGAIN, and ast_conf_user::chan.
Referenced by admin_exec(), conf_run(), and user_reset_vol_cb().
01116 { 01117 signed char zero_volume = 0; 01118 01119 ast_channel_setoption(user->chan, AST_OPTION_TXGAIN, &zero_volume, sizeof(zero_volume), 0); 01120 ast_channel_setoption(user->chan, AST_OPTION_RXGAIN, &zero_volume, sizeof(zero_volume), 0); 01121 }
static int rt_extend_conf | ( | const char * | confno | ) | [static] |
Definition at line 2079 of file app_meetme.c.
References ast_copy_string(), ast_debug, ast_load_realtime(), ast_localtime(), ast_mktime(), ast_strftime(), ast_strptime(), ast_tvnow(), ast_update_realtime(), ast_variables_destroy(), ast_conference::bookid, DATE_FORMAT, ast_conference::endtime, ast_variable::name, ast_variable::next, ast_variable::value, and var.
Referenced by admin_exec(), meetme_menu_admin(), and meetme_menu_normal().
02080 { 02081 char currenttime[32]; 02082 char endtime[32]; 02083 struct timeval now; 02084 struct ast_tm tm; 02085 struct ast_variable *var, *orig_var; 02086 char bookid[51]; 02087 02088 if (!extendby) { 02089 return 0; 02090 } 02091 02092 now = ast_tvnow(); 02093 02094 ast_localtime(&now, &tm, NULL); 02095 ast_strftime(currenttime, sizeof(currenttime), DATE_FORMAT, &tm); 02096 02097 var = ast_load_realtime("meetme", "confno", 02098 confno, "startTime<= ", currenttime, 02099 "endtime>= ", currenttime, NULL); 02100 02101 orig_var = var; 02102 02103 /* Identify the specific RealTime conference */ 02104 while (var) { 02105 if (!strcasecmp(var->name, "bookid")) { 02106 ast_copy_string(bookid, var->value, sizeof(bookid)); 02107 } 02108 if (!strcasecmp(var->name, "endtime")) { 02109 ast_copy_string(endtime, var->value, sizeof(endtime)); 02110 } 02111 02112 var = var->next; 02113 } 02114 ast_variables_destroy(orig_var); 02115 02116 ast_strptime(endtime, DATE_FORMAT, &tm); 02117 now = ast_mktime(&tm, NULL); 02118 02119 now.tv_sec += extendby; 02120 02121 ast_localtime(&now, &tm, NULL); 02122 ast_strftime(currenttime, sizeof(currenttime), DATE_FORMAT, &tm); 02123 strcat(currenttime, "0"); /* Seconds needs to be 00 */ 02124 02125 var = ast_load_realtime("meetme", "confno", 02126 confno, "startTime<= ", currenttime, 02127 "endtime>= ", currenttime, NULL); 02128 02129 /* If there is no conflict with extending the conference, update the DB */ 02130 if (!var) { 02131 ast_debug(3, "Trying to update the endtime of Conference %s to %s\n", confno, currenttime); 02132 ast_update_realtime("meetme", "bookid", bookid, "endtime", currenttime, NULL); 02133 return 0; 02134 02135 } 02136 02137 ast_variables_destroy(var); 02138 return -1; 02139 }
static void* run_station | ( | void * | data | ) | [static] |
Definition at line 5452 of file app_meetme.c.
References admin_exec(), ALL_TRUNK_REFS, answer_trunk_chan(), args, ast_atomic_dec_and_test(), ast_atomic_fetchadd_int(), ast_cond_signal, ast_dial_destroy(), ast_dial_join(), ast_free, ast_mutex_lock, ast_mutex_unlock, ast_set_flag64, ast_str_append(), ast_str_buffer(), ast_str_create(), ast_str_set(), 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(), 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().
05453 { 05454 struct sla_station *station; 05455 struct sla_trunk_ref *trunk_ref; 05456 struct ast_str *conf_name = ast_str_create(16); 05457 struct ast_flags64 conf_flags = { 0 }; 05458 struct ast_conference *conf; 05459 05460 { 05461 struct run_station_args *args = data; 05462 station = args->station; 05463 trunk_ref = args->trunk_ref; 05464 ast_mutex_lock(args->cond_lock); 05465 ast_cond_signal(args->cond); 05466 ast_mutex_unlock(args->cond_lock); 05467 /* args is no longer valid here. */ 05468 } 05469 05470 ast_atomic_fetchadd_int((int *) &trunk_ref->trunk->active_stations, 1); 05471 ast_str_set(&conf_name, 0, "SLA_%s", trunk_ref->trunk->name); 05472 ast_set_flag64(&conf_flags, 05473 CONFFLAG_QUIET | CONFFLAG_MARKEDEXIT | CONFFLAG_PASS_DTMF | CONFFLAG_SLA_STATION); 05474 answer_trunk_chan(trunk_ref->chan); 05475 conf = build_conf(ast_str_buffer(conf_name), "", "", 0, 0, 1, trunk_ref->chan, NULL); 05476 if (conf) { 05477 conf_run(trunk_ref->chan, conf, &conf_flags, NULL); 05478 dispose_conf(conf); 05479 conf = NULL; 05480 } 05481 trunk_ref->chan = NULL; 05482 if (ast_atomic_dec_and_test((int *) &trunk_ref->trunk->active_stations) && 05483 trunk_ref->state != SLA_TRUNK_STATE_ONHOLD_BYME) { 05484 ast_str_append(&conf_name, 0, ",K"); 05485 admin_exec(NULL, ast_str_buffer(conf_name)); 05486 trunk_ref->trunk->hold_stations = 0; 05487 sla_change_trunk_state(trunk_ref->trunk, SLA_TRUNK_STATE_IDLE, ALL_TRUNK_REFS, NULL); 05488 } 05489 05490 ast_dial_join(station->dial); 05491 ast_dial_destroy(station->dial); 05492 station->dial = NULL; 05493 ast_free(conf_name); 05494 05495 return NULL; 05496 }
static void send_talking_event | ( | struct ast_channel * | chan, | |
struct ast_conference * | conf, | |||
struct ast_conf_user * | user, | |||
int | talking | |||
) | [static] |
Definition at line 2233 of file app_meetme.c.
References ast_manager_event, ast_conference::confno, EVENT_FLAG_CALL, and ast_conf_user::user_no.
Referenced by set_user_talking().
02234 { 02235 ast_manager_event(chan, EVENT_FLAG_CALL, "MeetmeTalking", 02236 "Channel: %s\r\n" 02237 "Uniqueid: %s\r\n" 02238 "Meetme: %s\r\n" 02239 "Usernum: %d\r\n" 02240 "Status: %s\r\n", 02241 chan->name, chan->uniqueid, conf->confno, user->user_no, talking ? "on" : "off"); 02242 }
static int set_listen_volume | ( | struct ast_conf_user * | user, | |
int | volume | |||
) | [static] |
Definition at line 1044 of file app_meetme.c.
References ast_channel_setoption(), AST_OPTION_TXGAIN, and ast_conf_user::chan.
Referenced by tweak_listen_volume().
01045 { 01046 char gain_adjust; 01047 01048 /* attempt to make the adjustment in the channel driver; 01049 if successful, don't adjust in the frame reading routine 01050 */ 01051 gain_adjust = gain_map[volume + 5]; 01052 01053 return ast_channel_setoption(user->chan, AST_OPTION_TXGAIN, &gain_adjust, sizeof(gain_adjust), 0); 01054 }
static int set_talk_volume | ( | struct ast_conf_user * | user, | |
int | volume | |||
) | [static] |
Definition at line 1032 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().
01033 { 01034 char gain_adjust; 01035 01036 /* attempt to make the adjustment in the channel driver; 01037 if successful, don't adjust in the frame reading routine 01038 */ 01039 gain_adjust = gain_map[volume + 5]; 01040 01041 return ast_channel_setoption(user->chan, AST_OPTION_RXGAIN, &gain_adjust, sizeof(gain_adjust), 0); 01042 }
static void set_user_talking | ( | struct ast_channel * | chan, | |
struct ast_conference * | conf, | |||
struct ast_conf_user * | user, | |||
int | talking, | |||
int | monitor | |||
) | [static] |
Definition at line 2244 of file app_meetme.c.
References send_talking_event(), and ast_conf_user::talking.
Referenced by conf_run().
02245 { 02246 int last_talking = user->talking; 02247 if (last_talking == talking) 02248 return; 02249 02250 user->talking = talking; 02251 02252 if (monitor) { 02253 /* Check if talking state changed. Take care of -1 which means unmonitored */ 02254 int was_talking = (last_talking > 0); 02255 int now_talking = (talking > 0); 02256 if (was_talking != now_talking) { 02257 send_talking_event(chan, conf, user, now_talking); 02258 } 02259 } 02260 }
static void sla_add_trunk_to_station | ( | struct sla_station * | station, | |
struct ast_variable * | var | |||
) | [static] |
Definition at line 6924 of file app_meetme.c.
References ast_atomic_fetchadd_int(), ast_free, AST_LIST_INSERT_TAIL, ast_log(), AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_strdupa, create_trunk_ref(), LOG_ERROR, LOG_WARNING, name, sla_create_station_ref(), SLA_TRUNK_STATE_IDLE, value, and ast_variable::value.
Referenced by sla_build_station().
06925 { 06926 struct sla_trunk *trunk; 06927 struct sla_trunk_ref *trunk_ref; 06928 struct sla_station_ref *station_ref; 06929 char *trunk_name, *options, *cur; 06930 06931 options = ast_strdupa(var->value); 06932 trunk_name = strsep(&options, ","); 06933 06934 AST_RWLIST_RDLOCK(&sla_trunks); 06935 AST_RWLIST_TRAVERSE(&sla_trunks, trunk, entry) { 06936 if (!strcasecmp(trunk->name, trunk_name)) 06937 break; 06938 } 06939 06940 AST_RWLIST_UNLOCK(&sla_trunks); 06941 if (!trunk) { 06942 ast_log(LOG_ERROR, "Trunk '%s' not found!\n", var->value); 06943 return; 06944 } 06945 if (!(trunk_ref = create_trunk_ref(trunk))) 06946 return; 06947 trunk_ref->state = SLA_TRUNK_STATE_IDLE; 06948 06949 while ((cur = strsep(&options, ","))) { 06950 char *name, *value = cur; 06951 name = strsep(&value, "="); 06952 if (!strcasecmp(name, "ringtimeout")) { 06953 if (sscanf(value, "%30u", &trunk_ref->ring_timeout) != 1) { 06954 ast_log(LOG_WARNING, "Invalid ringtimeout value '%s' for " 06955 "trunk '%s' on station '%s'\n", value, trunk->name, station->name); 06956 trunk_ref->ring_timeout = 0; 06957 } 06958 } else if (!strcasecmp(name, "ringdelay")) { 06959 if (sscanf(value, "%30u", &trunk_ref->ring_delay) != 1) { 06960 ast_log(LOG_WARNING, "Invalid ringdelay value '%s' for " 06961 "trunk '%s' on station '%s'\n", value, trunk->name, station->name); 06962 trunk_ref->ring_delay = 0; 06963 } 06964 } else { 06965 ast_log(LOG_WARNING, "Invalid option '%s' for " 06966 "trunk '%s' on station '%s'\n", name, trunk->name, station->name); 06967 } 06968 } 06969 06970 if (!(station_ref = sla_create_station_ref(station))) { 06971 ast_free(trunk_ref); 06972 return; 06973 } 06974 ast_atomic_fetchadd_int((int *) &trunk->num_stations, 1); 06975 AST_RWLIST_WRLOCK(&sla_trunks); 06976 AST_LIST_INSERT_TAIL(&trunk->stations, station_ref, entry); 06977 AST_RWLIST_UNLOCK(&sla_trunks); 06978 AST_LIST_INSERT_TAIL(&station->trunks, trunk_ref, entry); 06979 }
static int sla_build_station | ( | struct ast_config * | cfg, | |
const char * | cat | |||
) | [static] |
Definition at line 6981 of file app_meetme.c.
References ast_add_extension2(), ast_calloc_with_stringfields, ast_context_find_or_create(), ast_free_ptr(), 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_set, ast_strlen_zero(), ast_variable_browse(), ast_variable_retrieve(), context, destroy_station(), exten, 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().
06982 { 06983 struct sla_station *station; 06984 struct ast_variable *var; 06985 const char *dev; 06986 06987 if (!(dev = ast_variable_retrieve(cfg, cat, "device"))) { 06988 ast_log(LOG_ERROR, "SLA Station '%s' defined with no device!\n", cat); 06989 return -1; 06990 } 06991 06992 if (!(station = ast_calloc_with_stringfields(1, struct sla_station, 32))) { 06993 return -1; 06994 } 06995 06996 ast_string_field_set(station, name, cat); 06997 ast_string_field_set(station, device, dev); 06998 06999 for (var = ast_variable_browse(cfg, cat); var; var = var->next) { 07000 if (!strcasecmp(var->name, "trunk")) 07001 sla_add_trunk_to_station(station, var); 07002 else if (!strcasecmp(var->name, "autocontext")) 07003 ast_string_field_set(station, autocontext, var->value); 07004 else if (!strcasecmp(var->name, "ringtimeout")) { 07005 if (sscanf(var->value, "%30u", &station->ring_timeout) != 1) { 07006 ast_log(LOG_WARNING, "Invalid ringtimeout '%s' specified for station '%s'\n", 07007 var->value, station->name); 07008 station->ring_timeout = 0; 07009 } 07010 } else if (!strcasecmp(var->name, "ringdelay")) { 07011 if (sscanf(var->value, "%30u", &station->ring_delay) != 1) { 07012 ast_log(LOG_WARNING, "Invalid ringdelay '%s' specified for station '%s'\n", 07013 var->value, station->name); 07014 station->ring_delay = 0; 07015 } 07016 } else if (!strcasecmp(var->name, "hold")) { 07017 if (!strcasecmp(var->value, "private")) 07018 station->hold_access = SLA_HOLD_PRIVATE; 07019 else if (!strcasecmp(var->value, "open")) 07020 station->hold_access = SLA_HOLD_OPEN; 07021 else { 07022 ast_log(LOG_WARNING, "Invalid value '%s' for hold on station %s\n", 07023 var->value, station->name); 07024 } 07025 07026 } else if (strcasecmp(var->name, "type") && strcasecmp(var->name, "device")) { 07027 ast_log(LOG_ERROR, "Invalid option '%s' specified at line %d of %s!\n", 07028 var->name, var->lineno, SLA_CONFIG_FILE); 07029 } 07030 } 07031 07032 if (!ast_strlen_zero(station->autocontext)) { 07033 struct ast_context *context; 07034 struct sla_trunk_ref *trunk_ref; 07035 context = ast_context_find_or_create(NULL, NULL, station->autocontext, sla_registrar); 07036 if (!context) { 07037 ast_log(LOG_ERROR, "Failed to automatically find or create " 07038 "context '%s' for SLA!\n", station->autocontext); 07039 destroy_station(station); 07040 return -1; 07041 } 07042 /* The extension for when the handset goes off-hook. 07043 * exten => station1,1,SLAStation(station1) */ 07044 if (ast_add_extension2(context, 0 /* don't replace */, station->name, 1, 07045 NULL, NULL, slastation_app, ast_strdup(station->name), ast_free_ptr, sla_registrar)) { 07046 ast_log(LOG_ERROR, "Failed to automatically create extension " 07047 "for trunk '%s'!\n", station->name); 07048 destroy_station(station); 07049 return -1; 07050 } 07051 AST_RWLIST_RDLOCK(&sla_trunks); 07052 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) { 07053 char exten[AST_MAX_EXTENSION]; 07054 char hint[AST_MAX_APP]; 07055 snprintf(exten, sizeof(exten), "%s_%s", station->name, trunk_ref->trunk->name); 07056 snprintf(hint, sizeof(hint), "SLA:%s", exten); 07057 /* Extension for this line button 07058 * exten => station1_line1,1,SLAStation(station1_line1) */ 07059 if (ast_add_extension2(context, 0 /* don't replace */, exten, 1, 07060 NULL, NULL, slastation_app, ast_strdup(exten), ast_free_ptr, sla_registrar)) { 07061 ast_log(LOG_ERROR, "Failed to automatically create extension " 07062 "for trunk '%s'!\n", station->name); 07063 destroy_station(station); 07064 return -1; 07065 } 07066 /* Hint for this line button 07067 * exten => station1_line1,hint,SLA:station1_line1 */ 07068 if (ast_add_extension2(context, 0 /* don't replace */, exten, PRIORITY_HINT, 07069 NULL, NULL, hint, NULL, NULL, sla_registrar)) { 07070 ast_log(LOG_ERROR, "Failed to automatically create hint " 07071 "for trunk '%s'!\n", station->name); 07072 destroy_station(station); 07073 return -1; 07074 } 07075 } 07076 AST_RWLIST_UNLOCK(&sla_trunks); 07077 } 07078 07079 AST_RWLIST_WRLOCK(&sla_stations); 07080 AST_RWLIST_INSERT_TAIL(&sla_stations, station, entry); 07081 AST_RWLIST_UNLOCK(&sla_stations); 07082 07083 return 0; 07084 }
static int sla_build_trunk | ( | struct ast_config * | cfg, | |
const char * | cat | |||
) | [static] |
Definition at line 6849 of file app_meetme.c.
References ast_add_extension2(), ast_calloc_with_stringfields, ast_context_find_or_create(), ast_false(), ast_free_ptr(), ast_log(), AST_RWLIST_INSERT_TAIL, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_strdup, ast_string_field_set, ast_strlen_zero(), ast_variable_browse(), ast_variable_retrieve(), context, destroy_trunk(), 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().
06850 { 06851 struct sla_trunk *trunk; 06852 struct ast_variable *var; 06853 const char *dev; 06854 06855 if (!(dev = ast_variable_retrieve(cfg, cat, "device"))) { 06856 ast_log(LOG_ERROR, "SLA Trunk '%s' defined with no device!\n", cat); 06857 return -1; 06858 } 06859 06860 if (sla_check_device(dev)) { 06861 ast_log(LOG_ERROR, "SLA Trunk '%s' define with invalid device '%s'!\n", 06862 cat, dev); 06863 return -1; 06864 } 06865 06866 if (!(trunk = ast_calloc_with_stringfields(1, struct sla_trunk, 32))) { 06867 return -1; 06868 } 06869 06870 ast_string_field_set(trunk, name, cat); 06871 ast_string_field_set(trunk, device, dev); 06872 06873 for (var = ast_variable_browse(cfg, cat); var; var = var->next) { 06874 if (!strcasecmp(var->name, "autocontext")) 06875 ast_string_field_set(trunk, autocontext, var->value); 06876 else if (!strcasecmp(var->name, "ringtimeout")) { 06877 if (sscanf(var->value, "%30u", &trunk->ring_timeout) != 1) { 06878 ast_log(LOG_WARNING, "Invalid ringtimeout '%s' specified for trunk '%s'\n", 06879 var->value, trunk->name); 06880 trunk->ring_timeout = 0; 06881 } 06882 } else if (!strcasecmp(var->name, "barge")) 06883 trunk->barge_disabled = ast_false(var->value); 06884 else if (!strcasecmp(var->name, "hold")) { 06885 if (!strcasecmp(var->value, "private")) 06886 trunk->hold_access = SLA_HOLD_PRIVATE; 06887 else if (!strcasecmp(var->value, "open")) 06888 trunk->hold_access = SLA_HOLD_OPEN; 06889 else { 06890 ast_log(LOG_WARNING, "Invalid value '%s' for hold on trunk %s\n", 06891 var->value, trunk->name); 06892 } 06893 } else if (strcasecmp(var->name, "type") && strcasecmp(var->name, "device")) { 06894 ast_log(LOG_ERROR, "Invalid option '%s' specified at line %d of %s!\n", 06895 var->name, var->lineno, SLA_CONFIG_FILE); 06896 } 06897 } 06898 06899 if (!ast_strlen_zero(trunk->autocontext)) { 06900 struct ast_context *context; 06901 context = ast_context_find_or_create(NULL, NULL, trunk->autocontext, sla_registrar); 06902 if (!context) { 06903 ast_log(LOG_ERROR, "Failed to automatically find or create " 06904 "context '%s' for SLA!\n", trunk->autocontext); 06905 destroy_trunk(trunk); 06906 return -1; 06907 } 06908 if (ast_add_extension2(context, 0 /* don't replace */, "s", 1, 06909 NULL, NULL, slatrunk_app, ast_strdup(trunk->name), ast_free_ptr, sla_registrar)) { 06910 ast_log(LOG_ERROR, "Failed to automatically create extension " 06911 "for trunk '%s'!\n", trunk->name); 06912 destroy_trunk(trunk); 06913 return -1; 06914 } 06915 } 06916 06917 AST_RWLIST_WRLOCK(&sla_trunks); 06918 AST_RWLIST_INSERT_TAIL(&sla_trunks, trunk, entry); 06919 AST_RWLIST_UNLOCK(&sla_trunks); 06920 06921 return 0; 06922 }
static int sla_calc_station_delays | ( | unsigned int * | timeout | ) | [static] |
Calculate the ring delay for a station.
Definition at line 6073 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().
06074 { 06075 struct sla_station *station; 06076 int res = 0; 06077 06078 AST_LIST_TRAVERSE(&sla_stations, station, entry) { 06079 struct sla_ringing_trunk *ringing_trunk; 06080 int time_left; 06081 06082 /* Ignore stations already ringing */ 06083 if (sla_check_ringing_station(station)) 06084 continue; 06085 06086 /* Ignore stations already on a call */ 06087 if (sla_check_inuse_station(station)) 06088 continue; 06089 06090 /* Ignore stations that don't have one of their trunks ringing */ 06091 if (!(ringing_trunk = sla_choose_ringing_trunk(station, NULL, 0))) 06092 continue; 06093 06094 if ((time_left = sla_check_station_delay(station, ringing_trunk)) == INT_MAX) 06095 continue; 06096 06097 /* If there is no time left, then the station needs to start ringing. 06098 * Return non-zero so that an event will be queued up an event to 06099 * make that happen. */ 06100 if (time_left <= 0) { 06101 res = 1; 06102 continue; 06103 } 06104 06105 if (time_left < *timeout) 06106 *timeout = time_left; 06107 } 06108 06109 return res; 06110 }
static int sla_calc_station_timeouts | ( | unsigned int * | timeout | ) | [static] |
Process station ring timeouts.
Definition at line 5990 of file app_meetme.c.
References AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_tvdiff_ms(), ast_tvnow(), 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().
05991 { 05992 struct sla_ringing_trunk *ringing_trunk; 05993 struct sla_ringing_station *ringing_station; 05994 int res = 0; 05995 05996 AST_LIST_TRAVERSE_SAFE_BEGIN(&sla.ringing_stations, ringing_station, entry) { 05997 unsigned int ring_timeout = 0; 05998 int time_elapsed, time_left = INT_MAX, final_trunk_time_left = INT_MIN; 05999 struct sla_trunk_ref *trunk_ref; 06000 06001 /* If there are any ring timeouts specified for a specific trunk 06002 * on the station, then use the highest per-trunk ring timeout. 06003 * Otherwise, use the ring timeout set for the entire station. */ 06004 AST_LIST_TRAVERSE(&ringing_station->station->trunks, trunk_ref, entry) { 06005 struct sla_station_ref *station_ref; 06006 int trunk_time_elapsed, trunk_time_left; 06007 06008 AST_LIST_TRAVERSE(&sla.ringing_trunks, ringing_trunk, entry) { 06009 if (ringing_trunk->trunk == trunk_ref->trunk) 06010 break; 06011 } 06012 if (!ringing_trunk) 06013 continue; 06014 06015 /* If there is a trunk that is ringing without a timeout, then the 06016 * only timeout that could matter is a global station ring timeout. */ 06017 if (!trunk_ref->ring_timeout) 06018 break; 06019 06020 /* This trunk on this station is ringing and has a timeout. 06021 * However, make sure this trunk isn't still ringing from a 06022 * previous timeout. If so, don't consider it. */ 06023 AST_LIST_TRAVERSE(&ringing_trunk->timed_out_stations, station_ref, entry) { 06024 if (station_ref->station == ringing_station->station) 06025 break; 06026 } 06027 if (station_ref) 06028 continue; 06029 06030 trunk_time_elapsed = ast_tvdiff_ms(ast_tvnow(), ringing_trunk->ring_begin); 06031 trunk_time_left = (trunk_ref->ring_timeout * 1000) - trunk_time_elapsed; 06032 if (trunk_time_left > final_trunk_time_left) 06033 final_trunk_time_left = trunk_time_left; 06034 } 06035 06036 /* No timeout was found for ringing trunks, and no timeout for the entire station */ 06037 if (final_trunk_time_left == INT_MIN && !ringing_station->station->ring_timeout) 06038 continue; 06039 06040 /* Compute how much time is left for a global station timeout */ 06041 if (ringing_station->station->ring_timeout) { 06042 ring_timeout = ringing_station->station->ring_timeout; 06043 time_elapsed = ast_tvdiff_ms(ast_tvnow(), ringing_station->ring_begin); 06044 time_left = (ring_timeout * 1000) - time_elapsed; 06045 } 06046 06047 /* If the time left based on the per-trunk timeouts is smaller than the 06048 * global station ring timeout, use that. */ 06049 if (final_trunk_time_left > INT_MIN && final_trunk_time_left < time_left) 06050 time_left = final_trunk_time_left; 06051 06052 /* If there is no time left, the station needs to stop ringing */ 06053 if (time_left <= 0) { 06054 AST_LIST_REMOVE_CURRENT(entry); 06055 sla_stop_ringing_station(ringing_station, SLA_STATION_HANGUP_TIMEOUT); 06056 res = 1; 06057 continue; 06058 } 06059 06060 /* There is still some time left for this station to ring, so save that 06061 * timeout if it is the first event scheduled to occur */ 06062 if (time_left < *timeout) 06063 *timeout = time_left; 06064 } 06065 AST_LIST_TRAVERSE_SAFE_END; 06066 06067 return res; 06068 }
static int sla_calc_trunk_timeouts | ( | unsigned int * | timeout | ) | [static] |
Process trunk ring timeouts.
Definition at line 5960 of file app_meetme.c.
References AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_tvdiff_ms(), ast_tvnow(), pbx_builtin_setvar_helper(), sla_ringing_trunk::ring_begin, sla, sla_stop_ringing_trunk(), and sla_ringing_trunk::trunk.
Referenced by sla_process_timers().
05961 { 05962 struct sla_ringing_trunk *ringing_trunk; 05963 int res = 0; 05964 05965 AST_LIST_TRAVERSE_SAFE_BEGIN(&sla.ringing_trunks, ringing_trunk, entry) { 05966 int time_left, time_elapsed; 05967 if (!ringing_trunk->trunk->ring_timeout) 05968 continue; 05969 time_elapsed = ast_tvdiff_ms(ast_tvnow(), ringing_trunk->ring_begin); 05970 time_left = (ringing_trunk->trunk->ring_timeout * 1000) - time_elapsed; 05971 if (time_left <= 0) { 05972 pbx_builtin_setvar_helper(ringing_trunk->trunk->chan, "SLATRUNK_STATUS", "RINGTIMEOUT"); 05973 AST_LIST_REMOVE_CURRENT(entry); 05974 sla_stop_ringing_trunk(ringing_trunk); 05975 res = 1; 05976 continue; 05977 } 05978 if (time_left < *timeout) 05979 *timeout = time_left; 05980 } 05981 AST_LIST_TRAVERSE_SAFE_END; 05982 05983 return res; 05984 }
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 5420 of file app_meetme.c.
References AST_DEVSTATE_CACHABLE, ast_devstate_changed(), AST_LIST_TRAVERSE, and sla_state_to_devstate().
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().
05422 { 05423 struct sla_station *station; 05424 struct sla_trunk_ref *trunk_ref; 05425 05426 AST_LIST_TRAVERSE(&sla_stations, station, entry) { 05427 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) { 05428 if (trunk_ref->trunk != trunk || (inactive_only ? trunk_ref->chan : 0) 05429 || trunk_ref == exclude) 05430 continue; 05431 trunk_ref->state = state; 05432 ast_devstate_changed(sla_state_to_devstate(state), AST_DEVSTATE_CACHABLE, 05433 "SLA:%s_%s", station->name, trunk->name); 05434 break; 05435 } 05436 } 05437 }
static int sla_check_device | ( | const char * | device | ) | [static] |
Definition at line 6836 of file app_meetme.c.
References ast_strdupa, and ast_strlen_zero().
Referenced by sla_build_trunk().
06837 { 06838 char *tech, *tech_data; 06839 06840 tech_data = ast_strdupa(device); 06841 tech = strsep(&tech_data, "/"); 06842 06843 if (ast_strlen_zero(tech) || ast_strlen_zero(tech_data)) 06844 return -1; 06845 06846 return 0; 06847 }
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 5709 of file app_meetme.c.
References ast_free, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_tvdiff_ms(), ast_tvnow(), sla_failed_station::last_try, sla, and sla_failed_station::station.
Referenced by sla_ring_stations().
05710 { 05711 struct sla_failed_station *failed_station; 05712 int res = 0; 05713 05714 AST_LIST_TRAVERSE_SAFE_BEGIN(&sla.failed_stations, failed_station, entry) { 05715 if (station != failed_station->station) 05716 continue; 05717 if (ast_tvdiff_ms(ast_tvnow(), failed_station->last_try) > 1000) { 05718 AST_LIST_REMOVE_CURRENT(entry); 05719 ast_free(failed_station); 05720 break; 05721 } 05722 res = 1; 05723 } 05724 AST_LIST_TRAVERSE_SAFE_END 05725 05726 return res; 05727 }
static int sla_check_inuse_station | ( | const struct sla_station * | station | ) | [static] |
Check to see if a station is in use.
Definition at line 5794 of file app_meetme.c.
References AST_LIST_TRAVERSE.
Referenced by sla_calc_station_delays(), and sla_ring_stations().
05795 { 05796 struct sla_trunk_ref *trunk_ref; 05797 05798 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) { 05799 if (trunk_ref->chan) 05800 return 1; 05801 } 05802 05803 return 0; 05804 }
static void sla_check_reload | ( | void | ) | [static] |
Check if we can do a reload of SLA, and do it if we can.
Definition at line 6152 of file app_meetme.c.
References AST_LIST_EMPTY, ast_mutex_lock, ast_mutex_unlock, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, sla, and sla_load_config().
Referenced by sla_thread().
06153 { 06154 struct sla_station *station; 06155 struct sla_trunk *trunk; 06156 06157 ast_mutex_lock(&sla.lock); 06158 06159 if (!AST_LIST_EMPTY(&sla.event_q) || !AST_LIST_EMPTY(&sla.ringing_trunks) 06160 || !AST_LIST_EMPTY(&sla.ringing_stations)) { 06161 ast_mutex_unlock(&sla.lock); 06162 return; 06163 } 06164 06165 AST_RWLIST_RDLOCK(&sla_stations); 06166 AST_RWLIST_TRAVERSE(&sla_stations, station, entry) { 06167 if (station->ref_count) 06168 break; 06169 } 06170 AST_RWLIST_UNLOCK(&sla_stations); 06171 if (station) { 06172 ast_mutex_unlock(&sla.lock); 06173 return; 06174 } 06175 06176 AST_RWLIST_RDLOCK(&sla_trunks); 06177 AST_RWLIST_TRAVERSE(&sla_trunks, trunk, entry) { 06178 if (trunk->ref_count) 06179 break; 06180 } 06181 AST_RWLIST_UNLOCK(&sla_trunks); 06182 if (trunk) { 06183 ast_mutex_unlock(&sla.lock); 06184 return; 06185 } 06186 06187 /* yay */ 06188 sla_load_config(1); 06189 sla.reload = 0; 06190 06191 ast_mutex_unlock(&sla.lock); 06192 }
static int sla_check_ringing_station | ( | const struct sla_station * | station | ) | [static] |
Check to see if this station is already ringing.
Definition at line 5694 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().
05695 { 05696 struct sla_ringing_station *ringing_station; 05697 05698 AST_LIST_TRAVERSE(&sla.ringing_stations, ringing_station, entry) { 05699 if (station == ringing_station->station) 05700 return 1; 05701 } 05702 05703 return 0; 05704 }
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 | |
ringing_trunk | the trunk. If NULL, the highest priority ringing trunk will be used |
Definition at line 5824 of file app_meetme.c.
References ast_tvdiff_ms(), ast_tvnow(), 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().
05826 { 05827 struct sla_trunk_ref *trunk_ref; 05828 unsigned int delay = UINT_MAX; 05829 int time_left, time_elapsed; 05830 05831 if (!ringing_trunk) 05832 ringing_trunk = sla_choose_ringing_trunk(station, &trunk_ref, 0); 05833 else 05834 trunk_ref = sla_find_trunk_ref(station, ringing_trunk->trunk); 05835 05836 if (!ringing_trunk || !trunk_ref) 05837 return delay; 05838 05839 /* If this station has a ring delay specific to the highest priority 05840 * ringing trunk, use that. Otherwise, use the ring delay specified 05841 * globally for the station. */ 05842 delay = trunk_ref->ring_delay; 05843 if (!delay) 05844 delay = station->ring_delay; 05845 if (!delay) 05846 return INT_MAX; 05847 05848 time_elapsed = ast_tvdiff_ms(ast_tvnow(), ringing_trunk->ring_begin); 05849 time_left = (delay * 1000) - time_elapsed; 05850 05851 return time_left; 05852 }
static int sla_check_station_hold_access | ( | const struct sla_trunk * | trunk, | |
const struct sla_station * | station | |||
) | [static] |
Definition at line 5325 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().
05327 { 05328 struct sla_station_ref *station_ref; 05329 struct sla_trunk_ref *trunk_ref; 05330 05331 /* For each station that has this call on hold, check for private hold. */ 05332 AST_LIST_TRAVERSE(&trunk->stations, station_ref, entry) { 05333 AST_LIST_TRAVERSE(&station_ref->station->trunks, trunk_ref, entry) { 05334 if (trunk_ref->trunk != trunk || station_ref->station == station) 05335 continue; 05336 if (trunk_ref->state == SLA_TRUNK_STATE_ONHOLD_BYME && 05337 station_ref->station->hold_access == SLA_HOLD_PRIVATE) 05338 return 1; 05339 return 0; 05340 } 05341 } 05342 05343 return 0; 05344 }
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 5556 of file app_meetme.c.
References AST_LIST_TRAVERSE.
Referenced by sla_choose_ringing_trunk(), and sla_ring_stations().
05558 { 05559 struct sla_station_ref *timed_out_station; 05560 05561 AST_LIST_TRAVERSE(&ringing_trunk->timed_out_stations, timed_out_station, entry) { 05562 if (station == timed_out_station->station) 05563 return 1; 05564 } 05565 05566 return 0; 05567 }
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 6399 of file app_meetme.c.
References AST_LIST_TRAVERSE, and SLA_TRUNK_STATE_IDLE.
Referenced by sla_station_exec().
06400 { 06401 struct sla_trunk_ref *trunk_ref = NULL; 06402 06403 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) { 06404 if (trunk_ref->state == SLA_TRUNK_STATE_IDLE) 06405 break; 06406 } 06407 06408 return trunk_ref; 06409 }
static struct sla_ringing_trunk* sla_choose_ringing_trunk | ( | struct sla_station * | station, | |
struct sla_trunk_ref ** | trunk_ref, | |||
int | rm | |||
) | [static, read] |
Choose the highest priority ringing trunk for a station.
station | the station | |
rm | 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 5577 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().
05579 { 05580 struct sla_trunk_ref *s_trunk_ref; 05581 struct sla_ringing_trunk *ringing_trunk = NULL; 05582 05583 AST_LIST_TRAVERSE(&station->trunks, s_trunk_ref, entry) { 05584 AST_LIST_TRAVERSE_SAFE_BEGIN(&sla.ringing_trunks, ringing_trunk, entry) { 05585 /* Make sure this is the trunk we're looking for */ 05586 if (s_trunk_ref->trunk != ringing_trunk->trunk) 05587 continue; 05588 05589 /* This trunk on the station is ringing. But, make sure this station 05590 * didn't already time out while this trunk was ringing. */ 05591 if (sla_check_timed_out_station(ringing_trunk, station)) 05592 continue; 05593 05594 if (rm) 05595 AST_LIST_REMOVE_CURRENT(entry); 05596 05597 if (trunk_ref) 05598 *trunk_ref = s_trunk_ref; 05599 05600 break; 05601 } 05602 AST_LIST_TRAVERSE_SAFE_END; 05603 05604 if (ringing_trunk) 05605 break; 05606 } 05607 05608 return ringing_trunk; 05609 }
static struct sla_ringing_station* sla_create_ringing_station | ( | struct sla_station * | station | ) | [static, read] |
Definition at line 5390 of file app_meetme.c.
References ast_calloc, ast_tvnow(), sla_ringing_station::ring_begin, and sla_ringing_station::station.
Referenced by sla_ring_station().
05391 { 05392 struct sla_ringing_station *ringing_station; 05393 05394 if (!(ringing_station = ast_calloc(1, sizeof(*ringing_station)))) 05395 return NULL; 05396 05397 ringing_station->station = station; 05398 ringing_station->ring_begin = ast_tvnow(); 05399 05400 return ringing_station; 05401 }
static struct sla_station_ref* sla_create_station_ref | ( | struct sla_station * | station | ) | [static, read] |
Definition at line 5378 of file app_meetme.c.
References ast_calloc.
Referenced by sla_add_trunk_to_station(), and sla_stop_ringing_station().
05379 { 05380 struct sla_station_ref *station_ref; 05381 05382 if (!(station_ref = ast_calloc(1, sizeof(*station_ref)))) 05383 return NULL; 05384 05385 station_ref->station = station; 05386 05387 return station_ref; 05388 }
static void sla_destroy | ( | void | ) | [static] |
Definition at line 6806 of file app_meetme.c.
References ast_cond_destroy, ast_cond_signal, ast_context_destroy(), 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(), sla, and sla_registrar.
Referenced by unload_module().
06807 { 06808 struct sla_trunk *trunk; 06809 struct sla_station *station; 06810 06811 AST_RWLIST_WRLOCK(&sla_trunks); 06812 while ((trunk = AST_RWLIST_REMOVE_HEAD(&sla_trunks, entry))) 06813 destroy_trunk(trunk); 06814 AST_RWLIST_UNLOCK(&sla_trunks); 06815 06816 AST_RWLIST_WRLOCK(&sla_stations); 06817 while ((station = AST_RWLIST_REMOVE_HEAD(&sla_stations, entry))) 06818 destroy_station(station); 06819 AST_RWLIST_UNLOCK(&sla_stations); 06820 06821 if (sla.thread != AST_PTHREADT_NULL) { 06822 ast_mutex_lock(&sla.lock); 06823 sla.stop = 1; 06824 ast_cond_signal(&sla.cond); 06825 ast_mutex_unlock(&sla.lock); 06826 pthread_join(sla.thread, NULL); 06827 } 06828 06829 /* Drop any created contexts from the dialplan */ 06830 ast_context_destroy(NULL, sla_registrar); 06831 06832 ast_mutex_destroy(&sla.lock); 06833 ast_cond_destroy(&sla.cond); 06834 }
static void sla_dial_state_callback | ( | struct ast_dial * | dial | ) | [static] |
Definition at line 5548 of file app_meetme.c.
References SLA_EVENT_DIAL_STATE, and sla_queue_event().
Referenced by sla_ring_station().
05549 { 05550 sla_queue_event(SLA_EVENT_DIAL_STATE); 05551 }
static struct sla_station* sla_find_station | ( | const char * | name | ) | [static, read] |
Find an SLA station by name.
Definition at line 5313 of file app_meetme.c.
References AST_RWLIST_TRAVERSE.
Referenced by sla_station_exec().
05314 { 05315 struct sla_station *station = NULL; 05316 05317 AST_RWLIST_TRAVERSE(&sla_stations, station, entry) { 05318 if (!strcasecmp(station->name, name)) 05319 break; 05320 } 05321 05322 return station; 05323 }
static struct sla_trunk* sla_find_trunk | ( | const char * | name | ) | [static, read] |
Find an SLA trunk by name.
Definition at line 5298 of file app_meetme.c.
References AST_RWLIST_TRAVERSE.
Referenced by sla_trunk_exec().
05299 { 05300 struct sla_trunk *trunk = NULL; 05301 05302 AST_RWLIST_TRAVERSE(&sla_trunks, trunk, entry) { 05303 if (!strcasecmp(trunk->name, name)) 05304 break; 05305 } 05306 05307 return trunk; 05308 }
static struct sla_trunk_ref* sla_find_trunk_ref | ( | const struct sla_station * | station, | |
const struct sla_trunk * | trunk | |||
) | [static, read] |
Definition at line 5806 of file app_meetme.c.
References AST_LIST_TRAVERSE.
Referenced by sla_check_station_delay().
05808 { 05809 struct sla_trunk_ref *trunk_ref = NULL; 05810 05811 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) { 05812 if (trunk_ref->trunk == trunk) 05813 break; 05814 } 05815 05816 return trunk_ref; 05817 }
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 5353 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().
05355 { 05356 struct sla_trunk_ref *trunk_ref = NULL; 05357 05358 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) { 05359 if (strcasecmp(trunk_ref->trunk->name, name)) 05360 continue; 05361 05362 if ( (trunk_ref->trunk->barge_disabled 05363 && trunk_ref->state == SLA_TRUNK_STATE_UP) || 05364 (trunk_ref->trunk->hold_stations 05365 && trunk_ref->trunk->hold_access == SLA_HOLD_PRIVATE 05366 && trunk_ref->state != SLA_TRUNK_STATE_ONHOLD_BYME) || 05367 sla_check_station_hold_access(trunk_ref->trunk, station) ) 05368 { 05369 trunk_ref = NULL; 05370 } 05371 05372 break; 05373 } 05374 05375 return trunk_ref; 05376 }
static void sla_handle_dial_state_event | ( | void | ) | [static] |
Definition at line 5611 of file app_meetme.c.
References ALL_TRUNK_REFS, answer_trunk_chan(), ast_cond_destroy, ast_cond_init, ast_cond_wait, ast_debug, ast_dial_answered(), ast_dial_destroy(), ast_dial_join(), AST_DIAL_RESULT_ANSWERED, AST_DIAL_RESULT_FAILED, AST_DIAL_RESULT_HANGUP, AST_DIAL_RESULT_INVALID, AST_DIAL_RESULT_PROCEEDING, AST_DIAL_RESULT_PROGRESS, AST_DIAL_RESULT_RINGING, AST_DIAL_RESULT_TIMEOUT, AST_DIAL_RESULT_TRYING, AST_DIAL_RESULT_UNANSWERED, ast_dial_state(), ast_free, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_mutex_destroy, ast_mutex_init, ast_mutex_lock, ast_mutex_unlock, ast_pthread_create_detached_background, run_station_args::cond, run_station_args::cond_lock, 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().
05612 { 05613 struct sla_ringing_station *ringing_station; 05614 05615 AST_LIST_TRAVERSE_SAFE_BEGIN(&sla.ringing_stations, ringing_station, entry) { 05616 struct sla_trunk_ref *s_trunk_ref = NULL; 05617 struct sla_ringing_trunk *ringing_trunk = NULL; 05618 struct run_station_args args; 05619 enum ast_dial_result dial_res; 05620 pthread_t dont_care; 05621 ast_mutex_t cond_lock; 05622 ast_cond_t cond; 05623 05624 switch ((dial_res = ast_dial_state(ringing_station->station->dial))) { 05625 case AST_DIAL_RESULT_HANGUP: 05626 case AST_DIAL_RESULT_INVALID: 05627 case AST_DIAL_RESULT_FAILED: 05628 case AST_DIAL_RESULT_TIMEOUT: 05629 case AST_DIAL_RESULT_UNANSWERED: 05630 AST_LIST_REMOVE_CURRENT(entry); 05631 sla_stop_ringing_station(ringing_station, SLA_STATION_HANGUP_NORMAL); 05632 break; 05633 case AST_DIAL_RESULT_ANSWERED: 05634 AST_LIST_REMOVE_CURRENT(entry); 05635 /* Find the appropriate trunk to answer. */ 05636 ast_mutex_lock(&sla.lock); 05637 ringing_trunk = sla_choose_ringing_trunk(ringing_station->station, &s_trunk_ref, 1); 05638 ast_mutex_unlock(&sla.lock); 05639 if (!ringing_trunk) { 05640 /* This case happens in a bit of a race condition. If two stations answer 05641 * the outbound call at the same time, the first one will get connected to 05642 * the trunk. When the second one gets here, it will not see any trunks 05643 * ringing so we have no idea what to conect it to. So, we just hang up 05644 * on it. */ 05645 ast_debug(1, "Found no ringing trunk for station '%s' to answer!\n", ringing_station->station->name); 05646 ast_dial_join(ringing_station->station->dial); 05647 ast_dial_destroy(ringing_station->station->dial); 05648 ringing_station->station->dial = NULL; 05649 ast_free(ringing_station); 05650 break; 05651 } 05652 /* Track the channel that answered this trunk */ 05653 s_trunk_ref->chan = ast_dial_answered(ringing_station->station->dial); 05654 /* Actually answer the trunk */ 05655 answer_trunk_chan(ringing_trunk->trunk->chan); 05656 sla_change_trunk_state(ringing_trunk->trunk, SLA_TRUNK_STATE_UP, ALL_TRUNK_REFS, NULL); 05657 /* Now, start a thread that will connect this station to the trunk. The rest of 05658 * the code here sets up the thread and ensures that it is able to save the arguments 05659 * before they are no longer valid since they are allocated on the stack. */ 05660 args.trunk_ref = s_trunk_ref; 05661 args.station = ringing_station->station; 05662 args.cond = &cond; 05663 args.cond_lock = &cond_lock; 05664 ast_free(ringing_trunk); 05665 ast_free(ringing_station); 05666 ast_mutex_init(&cond_lock); 05667 ast_cond_init(&cond, NULL); 05668 ast_mutex_lock(&cond_lock); 05669 ast_pthread_create_detached_background(&dont_care, NULL, run_station, &args); 05670 ast_cond_wait(&cond, &cond_lock); 05671 ast_mutex_unlock(&cond_lock); 05672 ast_mutex_destroy(&cond_lock); 05673 ast_cond_destroy(&cond); 05674 break; 05675 case AST_DIAL_RESULT_TRYING: 05676 case AST_DIAL_RESULT_RINGING: 05677 case AST_DIAL_RESULT_PROGRESS: 05678 case AST_DIAL_RESULT_PROCEEDING: 05679 break; 05680 } 05681 if (dial_res == AST_DIAL_RESULT_ANSWERED) { 05682 /* Queue up reprocessing ringing trunks, and then ringing stations again */ 05683 sla_queue_event(SLA_EVENT_RINGING_TRUNK); 05684 sla_queue_event(SLA_EVENT_DIAL_STATE); 05685 break; 05686 } 05687 } 05688 AST_LIST_TRAVERSE_SAFE_END; 05689 }
static void sla_handle_hold_event | ( | struct sla_event * | event | ) | [static] |
Definition at line 5936 of file app_meetme.c.
References ast_atomic_fetchadd_int(), AST_CONTROL_HOLD, AST_DEVICE_ONHOLD, AST_DEVSTATE_CACHABLE, ast_devstate_changed(), ast_indicate(), ast_softhangup(), AST_SOFTHANGUP_DEV, INACTIVE_TRUNK_REFS, 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().
05937 { 05938 ast_atomic_fetchadd_int((int *) &event->trunk_ref->trunk->hold_stations, 1); 05939 event->trunk_ref->state = SLA_TRUNK_STATE_ONHOLD_BYME; 05940 ast_devstate_changed(AST_DEVICE_ONHOLD, AST_DEVSTATE_CACHABLE, "SLA:%s_%s", 05941 event->station->name, event->trunk_ref->trunk->name); 05942 sla_change_trunk_state(event->trunk_ref->trunk, SLA_TRUNK_STATE_ONHOLD, 05943 INACTIVE_TRUNK_REFS, event->trunk_ref); 05944 05945 if (event->trunk_ref->trunk->active_stations == 1) { 05946 /* The station putting it on hold is the only one on the call, so start 05947 * Music on hold to the trunk. */ 05948 event->trunk_ref->trunk->on_hold = 1; 05949 ast_indicate(event->trunk_ref->trunk->chan, AST_CONTROL_HOLD); 05950 } 05951 05952 ast_softhangup(event->trunk_ref->chan, AST_SOFTHANGUP_DEV); 05953 event->trunk_ref->chan = NULL; 05954 }
static void sla_handle_ringing_trunk_event | ( | void | ) | [static] |
Definition at line 5926 of file app_meetme.c.
References ast_mutex_lock, ast_mutex_unlock, sla, sla_hangup_stations(), and sla_ring_stations().
Referenced by sla_thread().
05927 { 05928 ast_mutex_lock(&sla.lock); 05929 sla_ring_stations(); 05930 ast_mutex_unlock(&sla.lock); 05931 05932 /* Find stations that shouldn't be ringing anymore. */ 05933 sla_hangup_stations(); 05934 }
static void sla_hangup_stations | ( | void | ) | [static] |
Definition at line 5898 of file app_meetme.c.
References ast_dial_destroy(), ast_dial_join(), ast_free, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_mutex_lock, ast_mutex_unlock, sla, sla_ringing_station::station, and sla_ringing_trunk::trunk.
Referenced by sla_handle_ringing_trunk_event().
05899 { 05900 struct sla_trunk_ref *trunk_ref; 05901 struct sla_ringing_station *ringing_station; 05902 05903 AST_LIST_TRAVERSE_SAFE_BEGIN(&sla.ringing_stations, ringing_station, entry) { 05904 AST_LIST_TRAVERSE(&ringing_station->station->trunks, trunk_ref, entry) { 05905 struct sla_ringing_trunk *ringing_trunk; 05906 ast_mutex_lock(&sla.lock); 05907 AST_LIST_TRAVERSE(&sla.ringing_trunks, ringing_trunk, entry) { 05908 if (trunk_ref->trunk == ringing_trunk->trunk) 05909 break; 05910 } 05911 ast_mutex_unlock(&sla.lock); 05912 if (ringing_trunk) 05913 break; 05914 } 05915 if (!trunk_ref) { 05916 AST_LIST_REMOVE_CURRENT(entry); 05917 ast_dial_join(ringing_station->station->dial); 05918 ast_dial_destroy(ringing_station->station->dial); 05919 ringing_station->station->dial = NULL; 05920 ast_free(ringing_station); 05921 } 05922 } 05923 AST_LIST_TRAVERSE_SAFE_END 05924 }
static const char* sla_hold_str | ( | unsigned int | hold_access | ) | [static] |
Definition at line 1703 of file app_meetme.c.
References SLA_HOLD_OPEN, and SLA_HOLD_PRIVATE.
Referenced by sla_show_stations(), and sla_show_trunks().
01704 { 01705 const char *hold = "Unknown"; 01706 01707 switch (hold_access) { 01708 case SLA_HOLD_OPEN: 01709 hold = "Open"; 01710 break; 01711 case SLA_HOLD_PRIVATE: 01712 hold = "Private"; 01713 default: 01714 break; 01715 } 01716 01717 return hold; 01718 }
static int sla_load_config | ( | int | reload | ) | [static] |
Definition at line 7086 of file app_meetme.c.
References ast_category_browse(), ast_cond_init, ast_config_destroy(), ast_config_load, ast_free, AST_LIST_EMPTY, ast_log(), ast_mutex_init, ast_pthread_create, AST_PTHREADT_NULL, AST_RWLIST_REMOVE_CURRENT, AST_RWLIST_TRAVERSE_SAFE_BEGIN, AST_RWLIST_TRAVERSE_SAFE_END, ast_true(), ast_variable_retrieve(), CONFIG_FLAG_FILEUNCHANGED, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEUNCHANGED, LOG_ERROR, LOG_WARNING, sla, sla_build_station(), sla_build_trunk(), SLA_CONFIG_FILE, sla_thread(), and type.
Referenced by load_config(), and sla_check_reload().
07087 { 07088 struct ast_config *cfg; 07089 struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; 07090 const char *cat = NULL; 07091 int res = 0; 07092 const char *val; 07093 07094 if (!reload) { 07095 ast_mutex_init(&sla.lock); 07096 ast_cond_init(&sla.cond, NULL); 07097 } 07098 07099 if (!(cfg = ast_config_load(SLA_CONFIG_FILE, config_flags))) { 07100 return 0; /* Treat no config as normal */ 07101 } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) { 07102 return 0; 07103 } else if (cfg == CONFIG_STATUS_FILEINVALID) { 07104 ast_log(LOG_ERROR, "Config file " SLA_CONFIG_FILE " is in an invalid format. Aborting.\n"); 07105 return 0; 07106 } 07107 07108 if (reload) { 07109 struct sla_station *station; 07110 struct sla_trunk *trunk; 07111 07112 /* We need to actually delete the previous versions of trunks and stations now */ 07113 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&sla_stations, station, entry) { 07114 AST_RWLIST_REMOVE_CURRENT(entry); 07115 ast_free(station); 07116 } 07117 AST_RWLIST_TRAVERSE_SAFE_END; 07118 07119 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&sla_trunks, trunk, entry) { 07120 AST_RWLIST_REMOVE_CURRENT(entry); 07121 ast_free(trunk); 07122 } 07123 AST_RWLIST_TRAVERSE_SAFE_END; 07124 } 07125 07126 if ((val = ast_variable_retrieve(cfg, "general", "attemptcallerid"))) 07127 sla.attempt_callerid = ast_true(val); 07128 07129 while ((cat = ast_category_browse(cfg, cat)) && !res) { 07130 const char *type; 07131 if (!strcasecmp(cat, "general")) 07132 continue; 07133 if (!(type = ast_variable_retrieve(cfg, cat, "type"))) { 07134 ast_log(LOG_WARNING, "Invalid entry in %s defined with no type!\n", 07135 SLA_CONFIG_FILE); 07136 continue; 07137 } 07138 if (!strcasecmp(type, "trunk")) 07139 res = sla_build_trunk(cfg, cat); 07140 else if (!strcasecmp(type, "station")) 07141 res = sla_build_station(cfg, cat); 07142 else { 07143 ast_log(LOG_WARNING, "Entry in %s defined with invalid type '%s'!\n", 07144 SLA_CONFIG_FILE, type); 07145 } 07146 } 07147 07148 ast_config_destroy(cfg); 07149 07150 /* Even if we don't have any stations, we may after a reload and we need to 07151 * be able to process the SLA_EVENT_RELOAD event in that case */ 07152 if (sla.thread == AST_PTHREADT_NULL && (!AST_LIST_EMPTY(&sla_stations) || !AST_LIST_EMPTY(&sla_trunks))) { 07153 ast_pthread_create(&sla.thread, NULL, sla_thread, NULL); 07154 } 07155 07156 return res; 07157 }
static int sla_process_timers | ( | struct timespec * | ts | ) | [static] |
Calculate the time until the next known event.
Definition at line 6114 of file app_meetme.c.
References ast_samp2tv(), ast_tvadd(), ast_tvnow(), sla_calc_station_delays(), sla_calc_station_timeouts(), sla_calc_trunk_timeouts(), SLA_EVENT_RINGING_TRUNK, and sla_queue_event_nolock().
Referenced by sla_thread().
06115 { 06116 unsigned int timeout = UINT_MAX; 06117 struct timeval wait; 06118 unsigned int change_made = 0; 06119 06120 /* Check for ring timeouts on ringing trunks */ 06121 if (sla_calc_trunk_timeouts(&timeout)) 06122 change_made = 1; 06123 06124 /* Check for ring timeouts on ringing stations */ 06125 if (sla_calc_station_timeouts(&timeout)) 06126 change_made = 1; 06127 06128 /* Check for station ring delays */ 06129 if (sla_calc_station_delays(&timeout)) 06130 change_made = 1; 06131 06132 /* queue reprocessing of ringing trunks */ 06133 if (change_made) 06134 sla_queue_event_nolock(SLA_EVENT_RINGING_TRUNK); 06135 06136 /* No timeout */ 06137 if (timeout == UINT_MAX) 06138 return 0; 06139 06140 if (ts) { 06141 wait = ast_tvadd(ast_tvnow(), ast_samp2tv(timeout, 1000)); 06142 ts->tv_sec = wait.tv_sec; 06143 ts->tv_nsec = wait.tv_usec * 1000; 06144 } 06145 06146 return 1; 06147 }
static void sla_queue_event | ( | enum sla_event_type | type | ) | [static] |
Definition at line 2020 of file app_meetme.c.
References sla_queue_event_full().
Referenced by load_config(), queue_ringing_trunk(), sla_dial_state_callback(), sla_handle_dial_state_event(), sla_station_exec(), and sla_trunk_exec().
02021 { 02022 sla_queue_event_full(type, NULL, NULL, 1); 02023 }
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 2026 of file app_meetme.c.
References ast_debug, AST_LIST_TRAVERSE, ast_log(), AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_strdupa, ast_strlen_zero(), ast_conference::confno, LOG_ERROR, and sla_queue_event_full().
Referenced by conf_run().
02028 { 02029 struct sla_station *station; 02030 struct sla_trunk_ref *trunk_ref = NULL; 02031 char *trunk_name; 02032 02033 trunk_name = ast_strdupa(conf->confno); 02034 strsep(&trunk_name, "_"); 02035 if (ast_strlen_zero(trunk_name)) { 02036 ast_log(LOG_ERROR, "Invalid conference name for SLA - '%s'!\n", conf->confno); 02037 return; 02038 } 02039 02040 AST_RWLIST_RDLOCK(&sla_stations); 02041 AST_RWLIST_TRAVERSE(&sla_stations, station, entry) { 02042 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) { 02043 if (trunk_ref->chan == chan && !strcmp(trunk_ref->trunk->name, trunk_name)) 02044 break; 02045 } 02046 if (trunk_ref) 02047 break; 02048 } 02049 AST_RWLIST_UNLOCK(&sla_stations); 02050 02051 if (!trunk_ref) { 02052 ast_debug(1, "Trunk not found for event!\n"); 02053 return; 02054 } 02055 02056 sla_queue_event_full(type, trunk_ref, station, 1); 02057 }
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 1988 of file app_meetme.c.
References ast_calloc, ast_cond_signal, AST_LIST_INSERT_TAIL, ast_mutex_lock, ast_mutex_unlock, AST_PTHREADT_NULL, and sla.
Referenced by sla_queue_event(), sla_queue_event_conf(), and sla_queue_event_nolock().
01990 { 01991 struct sla_event *event; 01992 01993 if (sla.thread == AST_PTHREADT_NULL) { 01994 return; 01995 } 01996 01997 if (!(event = ast_calloc(1, sizeof(*event)))) 01998 return; 01999 02000 event->type = type; 02001 event->trunk_ref = trunk_ref; 02002 event->station = station; 02003 02004 if (!lock) { 02005 AST_LIST_INSERT_TAIL(&sla.event_q, event, entry); 02006 return; 02007 } 02008 02009 ast_mutex_lock(&sla.lock); 02010 AST_LIST_INSERT_TAIL(&sla.event_q, event, entry); 02011 ast_cond_signal(&sla.cond); 02012 ast_mutex_unlock(&sla.lock); 02013 }
static void sla_queue_event_nolock | ( | enum sla_event_type | type | ) | [static] |
Definition at line 2015 of file app_meetme.c.
References sla_queue_event_full().
Referenced by sla_process_timers().
02016 { 02017 sla_queue_event_full(type, NULL, NULL, 0); 02018 }
static int sla_ring_station | ( | struct sla_ringing_trunk * | ringing_trunk, | |
struct sla_station * | station | |||
) | [static] |
Ring a station.
Definition at line 5732 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_party_caller_free(), ast_party_caller_init(), ast_strdupa, ast_tvnow(), sla_failed_station::last_try, sla, sla_create_ringing_station(), sla_dial_state_callback(), sla_failed_station::station, and sla_ringing_trunk::trunk.
Referenced by sla_ring_stations().
05733 { 05734 char *tech, *tech_data; 05735 struct ast_dial *dial; 05736 struct sla_ringing_station *ringing_station; 05737 enum ast_dial_result res; 05738 int caller_is_saved; 05739 struct ast_party_caller caller; 05740 05741 if (!(dial = ast_dial_create())) 05742 return -1; 05743 05744 ast_dial_set_state_callback(dial, sla_dial_state_callback); 05745 tech_data = ast_strdupa(station->device); 05746 tech = strsep(&tech_data, "/"); 05747 05748 if (ast_dial_append(dial, tech, tech_data) == -1) { 05749 ast_dial_destroy(dial); 05750 return -1; 05751 } 05752 05753 /* Do we need to save off the caller ID data? */ 05754 caller_is_saved = 0; 05755 if (!sla.attempt_callerid) { 05756 caller_is_saved = 1; 05757 caller = ringing_trunk->trunk->chan->caller; 05758 ast_party_caller_init(&ringing_trunk->trunk->chan->caller); 05759 } 05760 05761 res = ast_dial_run(dial, ringing_trunk->trunk->chan, 1); 05762 05763 /* Restore saved caller ID */ 05764 if (caller_is_saved) { 05765 ast_party_caller_free(&ringing_trunk->trunk->chan->caller); 05766 ringing_trunk->trunk->chan->caller = caller; 05767 } 05768 05769 if (res != AST_DIAL_RESULT_TRYING) { 05770 struct sla_failed_station *failed_station; 05771 ast_dial_destroy(dial); 05772 if (!(failed_station = ast_calloc(1, sizeof(*failed_station)))) 05773 return -1; 05774 failed_station->station = station; 05775 failed_station->last_try = ast_tvnow(); 05776 AST_LIST_INSERT_HEAD(&sla.failed_stations, failed_station, entry); 05777 return -1; 05778 } 05779 if (!(ringing_station = sla_create_ringing_station(station))) { 05780 ast_dial_join(dial); 05781 ast_dial_destroy(dial); 05782 return -1; 05783 } 05784 05785 station->dial = dial; 05786 05787 AST_LIST_INSERT_HEAD(&sla.ringing_stations, ringing_station, entry); 05788 05789 return 0; 05790 }
static void sla_ring_stations | ( | void | ) | [static] |
Ring stations based on current set of ringing trunks.
Definition at line 5857 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().
05858 { 05859 struct sla_station_ref *station_ref; 05860 struct sla_ringing_trunk *ringing_trunk; 05861 05862 /* Make sure that every station that uses at least one of the ringing 05863 * trunks, is ringing. */ 05864 AST_LIST_TRAVERSE(&sla.ringing_trunks, ringing_trunk, entry) { 05865 AST_LIST_TRAVERSE(&ringing_trunk->trunk->stations, station_ref, entry) { 05866 int time_left; 05867 05868 /* Is this station already ringing? */ 05869 if (sla_check_ringing_station(station_ref->station)) 05870 continue; 05871 05872 /* Is this station already in a call? */ 05873 if (sla_check_inuse_station(station_ref->station)) 05874 continue; 05875 05876 /* Did we fail to dial this station earlier? If so, has it been 05877 * a minute since we tried? */ 05878 if (sla_check_failed_station(station_ref->station)) 05879 continue; 05880 05881 /* If this station already timed out while this trunk was ringing, 05882 * do not dial it again for this ringing trunk. */ 05883 if (sla_check_timed_out_station(ringing_trunk, station_ref->station)) 05884 continue; 05885 05886 /* Check for a ring delay in progress */ 05887 time_left = sla_check_station_delay(station_ref->station, ringing_trunk); 05888 if (time_left != INT_MAX && time_left > 0) 05889 continue; 05890 05891 /* It is time to make this station begin to ring. Do it! */ 05892 sla_ring_station(ringing_trunk, station_ref->station); 05893 } 05894 } 05895 /* Now, all of the stations that should be ringing, are ringing. */ 05896 }
static char* sla_show_stations | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 1785 of file app_meetme.c.
References ast_cli(), AST_LIST_TRAVERSE, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, S_OR, sla_hold_str(), trunkstate2str(), and ast_cli_entry::usage.
01786 { 01787 const struct sla_station *station; 01788 01789 switch (cmd) { 01790 case CLI_INIT: 01791 e->command = "sla show stations"; 01792 e->usage = 01793 "Usage: sla show stations\n" 01794 " This will list all stations defined in sla.conf\n"; 01795 return NULL; 01796 case CLI_GENERATE: 01797 return NULL; 01798 } 01799 01800 ast_cli(a->fd, "\n" 01801 "=============================================================\n" 01802 "=== Configured SLA Stations =================================\n" 01803 "=============================================================\n" 01804 "===\n"); 01805 AST_RWLIST_RDLOCK(&sla_stations); 01806 AST_RWLIST_TRAVERSE(&sla_stations, station, entry) { 01807 struct sla_trunk_ref *trunk_ref; 01808 char ring_timeout[16] = "(none)"; 01809 char ring_delay[16] = "(none)"; 01810 if (station->ring_timeout) { 01811 snprintf(ring_timeout, sizeof(ring_timeout), 01812 "%u", station->ring_timeout); 01813 } 01814 if (station->ring_delay) { 01815 snprintf(ring_delay, sizeof(ring_delay), 01816 "%u", station->ring_delay); 01817 } 01818 ast_cli(a->fd, "=== ---------------------------------------------------------\n" 01819 "=== Station Name: %s\n" 01820 "=== ==> Device: %s\n" 01821 "=== ==> AutoContext: %s\n" 01822 "=== ==> RingTimeout: %s\n" 01823 "=== ==> RingDelay: %s\n" 01824 "=== ==> HoldAccess: %s\n" 01825 "=== ==> Trunks ...\n", 01826 station->name, station->device, 01827 S_OR(station->autocontext, "(none)"), 01828 ring_timeout, ring_delay, 01829 sla_hold_str(station->hold_access)); 01830 AST_RWLIST_RDLOCK(&sla_trunks); 01831 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) { 01832 if (trunk_ref->ring_timeout) { 01833 snprintf(ring_timeout, sizeof(ring_timeout), 01834 "%u", trunk_ref->ring_timeout); 01835 } else 01836 strcpy(ring_timeout, "(none)"); 01837 if (trunk_ref->ring_delay) { 01838 snprintf(ring_delay, sizeof(ring_delay), 01839 "%u", trunk_ref->ring_delay); 01840 } else 01841 strcpy(ring_delay, "(none)"); 01842 ast_cli(a->fd, "=== ==> Trunk Name: %s\n" 01843 "=== ==> State: %s\n" 01844 "=== ==> RingTimeout: %s\n" 01845 "=== ==> RingDelay: %s\n", 01846 trunk_ref->trunk->name, 01847 trunkstate2str(trunk_ref->state), 01848 ring_timeout, ring_delay); 01849 } 01850 AST_RWLIST_UNLOCK(&sla_trunks); 01851 ast_cli(a->fd, "=== ---------------------------------------------------------\n" 01852 "===\n"); 01853 } 01854 AST_RWLIST_UNLOCK(&sla_stations); 01855 ast_cli(a->fd, "============================================================\n" 01856 "\n"); 01857 01858 return CLI_SUCCESS; 01859 }
static char* sla_show_trunks | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 1720 of file app_meetme.c.
References ast_cli(), AST_LIST_TRAVERSE, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, S_OR, sla_hold_str(), and ast_cli_entry::usage.
01721 { 01722 const struct sla_trunk *trunk; 01723 01724 switch (cmd) { 01725 case CLI_INIT: 01726 e->command = "sla show trunks"; 01727 e->usage = 01728 "Usage: sla show trunks\n" 01729 " This will list all trunks defined in sla.conf\n"; 01730 return NULL; 01731 case CLI_GENERATE: 01732 return NULL; 01733 } 01734 01735 ast_cli(a->fd, "\n" 01736 "=============================================================\n" 01737 "=== Configured SLA Trunks ===================================\n" 01738 "=============================================================\n" 01739 "===\n"); 01740 AST_RWLIST_RDLOCK(&sla_trunks); 01741 AST_RWLIST_TRAVERSE(&sla_trunks, trunk, entry) { 01742 struct sla_station_ref *station_ref; 01743 char ring_timeout[16] = "(none)"; 01744 if (trunk->ring_timeout) 01745 snprintf(ring_timeout, sizeof(ring_timeout), "%u Seconds", trunk->ring_timeout); 01746 ast_cli(a->fd, "=== ---------------------------------------------------------\n" 01747 "=== Trunk Name: %s\n" 01748 "=== ==> Device: %s\n" 01749 "=== ==> AutoContext: %s\n" 01750 "=== ==> RingTimeout: %s\n" 01751 "=== ==> BargeAllowed: %s\n" 01752 "=== ==> HoldAccess: %s\n" 01753 "=== ==> Stations ...\n", 01754 trunk->name, trunk->device, 01755 S_OR(trunk->autocontext, "(none)"), 01756 ring_timeout, 01757 trunk->barge_disabled ? "No" : "Yes", 01758 sla_hold_str(trunk->hold_access)); 01759 AST_RWLIST_RDLOCK(&sla_stations); 01760 AST_LIST_TRAVERSE(&trunk->stations, station_ref, entry) 01761 ast_cli(a->fd, "=== ==> Station name: %s\n", station_ref->station->name); 01762 AST_RWLIST_UNLOCK(&sla_stations); 01763 ast_cli(a->fd, "=== ---------------------------------------------------------\n===\n"); 01764 } 01765 AST_RWLIST_UNLOCK(&sla_trunks); 01766 ast_cli(a->fd, "=============================================================\n\n"); 01767 01768 return CLI_SUCCESS; 01769 }
static enum ast_device_state sla_state | ( | const char * | data | ) | [static] |
Definition at line 6730 of file app_meetme.c.
References AST_DEVICE_INVALID, AST_LIST_TRAVERSE, ast_log(), AST_RWLIST_RDLOCK, AST_RWLIST_UNLOCK, ast_strdupa, LOG_ERROR, and sla_state_to_devstate().
Referenced by load_module().
06731 { 06732 char *buf, *station_name, *trunk_name; 06733 struct sla_station *station; 06734 struct sla_trunk_ref *trunk_ref; 06735 enum ast_device_state res = AST_DEVICE_INVALID; 06736 06737 trunk_name = buf = ast_strdupa(data); 06738 station_name = strsep(&trunk_name, "_"); 06739 06740 AST_RWLIST_RDLOCK(&sla_stations); 06741 AST_LIST_TRAVERSE(&sla_stations, station, entry) { 06742 if (strcasecmp(station_name, station->name)) 06743 continue; 06744 AST_RWLIST_RDLOCK(&sla_trunks); 06745 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) { 06746 if (!strcasecmp(trunk_name, trunk_ref->trunk->name)) 06747 break; 06748 } 06749 if (!trunk_ref) { 06750 AST_RWLIST_UNLOCK(&sla_trunks); 06751 break; 06752 } 06753 res = sla_state_to_devstate(trunk_ref->state); 06754 AST_RWLIST_UNLOCK(&sla_trunks); 06755 } 06756 AST_RWLIST_UNLOCK(&sla_stations); 06757 06758 if (res == AST_DEVICE_INVALID) { 06759 ast_log(LOG_ERROR, "Could not determine state for trunk %s on station %s!\n", 06760 trunk_name, station_name); 06761 } 06762 06763 return res; 06764 }
static enum ast_device_state sla_state_to_devstate | ( | enum sla_trunk_state | state | ) | [static] |
Definition at line 5403 of file app_meetme.c.
References AST_DEVICE_INUSE, AST_DEVICE_NOT_INUSE, AST_DEVICE_ONHOLD, AST_DEVICE_RINGING, AST_DEVICE_UNKNOWN, 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_change_trunk_state(), and sla_state().
05404 { 05405 switch (state) { 05406 case SLA_TRUNK_STATE_IDLE: 05407 return AST_DEVICE_NOT_INUSE; 05408 case SLA_TRUNK_STATE_RINGING: 05409 return AST_DEVICE_RINGING; 05410 case SLA_TRUNK_STATE_UP: 05411 return AST_DEVICE_INUSE; 05412 case SLA_TRUNK_STATE_ONHOLD: 05413 case SLA_TRUNK_STATE_ONHOLD_BYME: 05414 return AST_DEVICE_ONHOLD; 05415 } 05416 05417 return AST_DEVICE_UNKNOWN; 05418 }
static int sla_station_exec | ( | struct ast_channel * | chan, | |
const char * | data | |||
) | [static] |
Definition at line 6411 of file app_meetme.c.
References admin_exec(), ALL_TRUNK_REFS, answer_trunk_chan(), ast_answer(), ast_atomic_dec_and_test(), ast_atomic_fetchadd_int(), ast_autoservice_start(), ast_autoservice_stop(), ast_cond_destroy, ast_cond_init, ast_cond_wait, AST_CONTROL_UNHOLD, ast_debug, AST_DEVICE_INUSE, AST_DEVSTATE_CACHABLE, ast_devstate_changed(), ast_indicate(), AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_log(), ast_mutex_destroy, ast_mutex_init, ast_mutex_lock, ast_mutex_unlock, ast_pthread_create_detached_background, AST_RWLIST_RDLOCK, AST_RWLIST_UNLOCK, ast_set_flag64, ast_strdupa, ast_strlen_zero(), build_conf(), conf_run(), CONFFLAG_MARKEDEXIT, CONFFLAG_PASS_DTMF, CONFFLAG_QUIET, CONFFLAG_SLA_STATION, dial_trunk(), dispose_conf(), free, LOG_NOTICE, LOG_WARNING, MAX_CONFNUM, pbx_builtin_setvar_helper(), sla, sla_change_trunk_state(), sla_choose_idle_trunk(), SLA_EVENT_CHECK_RELOAD, SLA_EVENT_DIAL_STATE, SLA_EVENT_RINGING_TRUNK, sla_find_station(), sla_find_trunk_ref_byname(), sla_queue_event(), SLA_TRUNK_STATE_IDLE, SLA_TRUNK_STATE_ONHOLD_BYME, SLA_TRUNK_STATE_RINGING, SLA_TRUNK_STATE_UP, sla_ringing_trunk::trunk, and dial_trunk_args::trunk_ref.
Referenced by load_module().
06412 { 06413 char *station_name, *trunk_name; 06414 struct sla_station *station; 06415 struct sla_trunk_ref *trunk_ref = NULL; 06416 char conf_name[MAX_CONFNUM]; 06417 struct ast_flags64 conf_flags = { 0 }; 06418 struct ast_conference *conf; 06419 06420 if (ast_strlen_zero(data)) { 06421 ast_log(LOG_WARNING, "Invalid Arguments to SLAStation!\n"); 06422 pbx_builtin_setvar_helper(chan, "SLASTATION_STATUS", "FAILURE"); 06423 return 0; 06424 } 06425 06426 trunk_name = ast_strdupa(data); 06427 station_name = strsep(&trunk_name, "_"); 06428 06429 if (ast_strlen_zero(station_name)) { 06430 ast_log(LOG_WARNING, "Invalid Arguments to SLAStation!\n"); 06431 pbx_builtin_setvar_helper(chan, "SLASTATION_STATUS", "FAILURE"); 06432 return 0; 06433 } 06434 06435 AST_RWLIST_RDLOCK(&sla_stations); 06436 station = sla_find_station(station_name); 06437 if (station) 06438 ast_atomic_fetchadd_int((int *) &station->ref_count, 1); 06439 AST_RWLIST_UNLOCK(&sla_stations); 06440 06441 if (!station) { 06442 ast_log(LOG_WARNING, "Station '%s' not found!\n", station_name); 06443 pbx_builtin_setvar_helper(chan, "SLASTATION_STATUS", "FAILURE"); 06444 sla_queue_event(SLA_EVENT_CHECK_RELOAD); 06445 return 0; 06446 } 06447 06448 AST_RWLIST_RDLOCK(&sla_trunks); 06449 if (!ast_strlen_zero(trunk_name)) { 06450 trunk_ref = sla_find_trunk_ref_byname(station, trunk_name); 06451 } else 06452 trunk_ref = sla_choose_idle_trunk(station); 06453 AST_RWLIST_UNLOCK(&sla_trunks); 06454 06455 if (!trunk_ref) { 06456 if (ast_strlen_zero(trunk_name)) 06457 ast_log(LOG_NOTICE, "No trunks available for call.\n"); 06458 else { 06459 ast_log(LOG_NOTICE, "Can't join existing call on trunk " 06460 "'%s' due to access controls.\n", trunk_name); 06461 } 06462 pbx_builtin_setvar_helper(chan, "SLASTATION_STATUS", "CONGESTION"); 06463 ast_atomic_fetchadd_int((int *) &station->ref_count, -1); 06464 sla_queue_event(SLA_EVENT_CHECK_RELOAD); 06465 return 0; 06466 } 06467 06468 if (trunk_ref->state == SLA_TRUNK_STATE_ONHOLD_BYME) { 06469 if (ast_atomic_dec_and_test((int *) &trunk_ref->trunk->hold_stations) == 1) 06470 sla_change_trunk_state(trunk_ref->trunk, SLA_TRUNK_STATE_UP, ALL_TRUNK_REFS, NULL); 06471 else { 06472 trunk_ref->state = SLA_TRUNK_STATE_UP; 06473 ast_devstate_changed(AST_DEVICE_INUSE, AST_DEVSTATE_CACHABLE, 06474 "SLA:%s_%s", station->name, trunk_ref->trunk->name); 06475 } 06476 } else if (trunk_ref->state == SLA_TRUNK_STATE_RINGING) { 06477 struct sla_ringing_trunk *ringing_trunk; 06478 06479 ast_mutex_lock(&sla.lock); 06480 AST_LIST_TRAVERSE_SAFE_BEGIN(&sla.ringing_trunks, ringing_trunk, entry) { 06481 if (ringing_trunk->trunk == trunk_ref->trunk) { 06482 AST_LIST_REMOVE_CURRENT(entry); 06483 break; 06484 } 06485 } 06486 AST_LIST_TRAVERSE_SAFE_END 06487 ast_mutex_unlock(&sla.lock); 06488 06489 if (ringing_trunk) { 06490 answer_trunk_chan(ringing_trunk->trunk->chan); 06491 sla_change_trunk_state(ringing_trunk->trunk, SLA_TRUNK_STATE_UP, ALL_TRUNK_REFS, NULL); 06492 06493 free(ringing_trunk); 06494 06495 /* Queue up reprocessing ringing trunks, and then ringing stations again */ 06496 sla_queue_event(SLA_EVENT_RINGING_TRUNK); 06497 sla_queue_event(SLA_EVENT_DIAL_STATE); 06498 } 06499 } 06500 06501 trunk_ref->chan = chan; 06502 06503 if (!trunk_ref->trunk->chan) { 06504 ast_mutex_t cond_lock; 06505 ast_cond_t cond; 06506 pthread_t dont_care; 06507 struct dial_trunk_args args = { 06508 .trunk_ref = trunk_ref, 06509 .station = station, 06510 .cond_lock = &cond_lock, 06511 .cond = &cond, 06512 }; 06513 sla_change_trunk_state(trunk_ref->trunk, SLA_TRUNK_STATE_UP, ALL_TRUNK_REFS, NULL); 06514 /* Create a thread to dial the trunk and dump it into the conference. 06515 * However, we want to wait until the trunk has been dialed and the 06516 * conference is created before continuing on here. */ 06517 ast_autoservice_start(chan); 06518 ast_mutex_init(&cond_lock); 06519 ast_cond_init(&cond, NULL); 06520 ast_mutex_lock(&cond_lock); 06521 ast_pthread_create_detached_background(&dont_care, NULL, dial_trunk, &args); 06522 ast_cond_wait(&cond, &cond_lock); 06523 ast_mutex_unlock(&cond_lock); 06524 ast_mutex_destroy(&cond_lock); 06525 ast_cond_destroy(&cond); 06526 ast_autoservice_stop(chan); 06527 if (!trunk_ref->trunk->chan) { 06528 ast_debug(1, "Trunk didn't get created. chan: %lx\n", (long) trunk_ref->trunk->chan); 06529 pbx_builtin_setvar_helper(chan, "SLASTATION_STATUS", "CONGESTION"); 06530 sla_change_trunk_state(trunk_ref->trunk, SLA_TRUNK_STATE_IDLE, ALL_TRUNK_REFS, NULL); 06531 trunk_ref->chan = NULL; 06532 ast_atomic_fetchadd_int((int *) &station->ref_count, -1); 06533 sla_queue_event(SLA_EVENT_CHECK_RELOAD); 06534 return 0; 06535 } 06536 } 06537 06538 if (ast_atomic_fetchadd_int((int *) &trunk_ref->trunk->active_stations, 1) == 0 && 06539 trunk_ref->trunk->on_hold) { 06540 trunk_ref->trunk->on_hold = 0; 06541 ast_indicate(trunk_ref->trunk->chan, AST_CONTROL_UNHOLD); 06542 sla_change_trunk_state(trunk_ref->trunk, SLA_TRUNK_STATE_UP, ALL_TRUNK_REFS, NULL); 06543 } 06544 06545 snprintf(conf_name, sizeof(conf_name), "SLA_%s", trunk_ref->trunk->name); 06546 ast_set_flag64(&conf_flags, 06547 CONFFLAG_QUIET | CONFFLAG_MARKEDEXIT | CONFFLAG_PASS_DTMF | CONFFLAG_SLA_STATION); 06548 ast_answer(chan); 06549 conf = build_conf(conf_name, "", "", 0, 0, 1, chan, NULL); 06550 if (conf) { 06551 conf_run(chan, conf, &conf_flags, NULL); 06552 dispose_conf(conf); 06553 conf = NULL; 06554 } 06555 trunk_ref->chan = NULL; 06556 if (ast_atomic_dec_and_test((int *) &trunk_ref->trunk->active_stations) && 06557 trunk_ref->state != SLA_TRUNK_STATE_ONHOLD_BYME) { 06558 strncat(conf_name, ",K", sizeof(conf_name) - strlen(conf_name) - 1); 06559 admin_exec(NULL, conf_name); 06560 trunk_ref->trunk->hold_stations = 0; 06561 sla_change_trunk_state(trunk_ref->trunk, SLA_TRUNK_STATE_IDLE, ALL_TRUNK_REFS, NULL); 06562 } 06563 06564 pbx_builtin_setvar_helper(chan, "SLASTATION_STATUS", "SUCCESS"); 06565 06566 ast_atomic_fetchadd_int((int *) &station->ref_count, -1); 06567 sla_queue_event(SLA_EVENT_CHECK_RELOAD); 06568 06569 return 0; 06570 }
static void sla_stop_ringing_station | ( | struct sla_ringing_station * | ringing_station, | |
enum sla_station_hangup | hangup | |||
) | [static] |
Definition at line 5513 of file app_meetme.c.
References ast_dial_destroy(), ast_dial_join(), ast_free, AST_LIST_INSERT_TAIL, AST_LIST_TRAVERSE, 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().
05515 { 05516 struct sla_ringing_trunk *ringing_trunk; 05517 struct sla_trunk_ref *trunk_ref; 05518 struct sla_station_ref *station_ref; 05519 05520 ast_dial_join(ringing_station->station->dial); 05521 ast_dial_destroy(ringing_station->station->dial); 05522 ringing_station->station->dial = NULL; 05523 05524 if (hangup == SLA_STATION_HANGUP_NORMAL) 05525 goto done; 05526 05527 /* If the station is being hung up because of a timeout, then add it to the 05528 * list of timed out stations on each of the ringing trunks. This is so 05529 * that when doing further processing to figure out which stations should be 05530 * ringing, which trunk to answer, determining timeouts, etc., we know which 05531 * ringing trunks we should ignore. */ 05532 AST_LIST_TRAVERSE(&sla.ringing_trunks, ringing_trunk, entry) { 05533 AST_LIST_TRAVERSE(&ringing_station->station->trunks, trunk_ref, entry) { 05534 if (ringing_trunk->trunk == trunk_ref->trunk) 05535 break; 05536 } 05537 if (!trunk_ref) 05538 continue; 05539 if (!(station_ref = sla_create_station_ref(ringing_station->station))) 05540 continue; 05541 AST_LIST_INSERT_TAIL(&ringing_trunk->timed_out_stations, station_ref, entry); 05542 } 05543 05544 done: 05545 ast_free(ringing_station); 05546 }
static void sla_stop_ringing_trunk | ( | struct sla_ringing_trunk * | ringing_trunk | ) | [static] |
Definition at line 5498 of file app_meetme.c.
References admin_exec(), ALL_TRUNK_REFS, ast_free, AST_LIST_REMOVE_HEAD, sla_change_trunk_state(), SLA_TRUNK_STATE_IDLE, and sla_ringing_trunk::trunk.
Referenced by sla_calc_trunk_timeouts().
05499 { 05500 char buf[80]; 05501 struct sla_station_ref *station_ref; 05502 05503 snprintf(buf, sizeof(buf), "SLA_%s,K", ringing_trunk->trunk->name); 05504 admin_exec(NULL, buf); 05505 sla_change_trunk_state(ringing_trunk->trunk, SLA_TRUNK_STATE_IDLE, ALL_TRUNK_REFS, NULL); 05506 05507 while ((station_ref = AST_LIST_REMOVE_HEAD(&ringing_trunk->timed_out_stations, entry))) 05508 ast_free(station_ref); 05509 05510 ast_free(ringing_trunk); 05511 }
static void* sla_thread | ( | void * | data | ) | [static] |
Definition at line 6194 of file app_meetme.c.
References ast_cond_timedwait, ast_cond_wait, ast_free, AST_LIST_EMPTY, AST_LIST_REMOVE_HEAD, ast_mutex_lock, ast_mutex_unlock, sla, sla_check_reload(), SLA_EVENT_CHECK_RELOAD, SLA_EVENT_DIAL_STATE, SLA_EVENT_HOLD, SLA_EVENT_RELOAD, 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().
06195 { 06196 struct sla_failed_station *failed_station; 06197 struct sla_ringing_station *ringing_station; 06198 06199 ast_mutex_lock(&sla.lock); 06200 06201 while (!sla.stop) { 06202 struct sla_event *event; 06203 struct timespec ts = { 0, }; 06204 unsigned int have_timeout = 0; 06205 06206 if (AST_LIST_EMPTY(&sla.event_q)) { 06207 if ((have_timeout = sla_process_timers(&ts))) 06208 ast_cond_timedwait(&sla.cond, &sla.lock, &ts); 06209 else 06210 ast_cond_wait(&sla.cond, &sla.lock); 06211 if (sla.stop) 06212 break; 06213 } 06214 06215 if (have_timeout) 06216 sla_process_timers(NULL); 06217 06218 while ((event = AST_LIST_REMOVE_HEAD(&sla.event_q, entry))) { 06219 ast_mutex_unlock(&sla.lock); 06220 switch (event->type) { 06221 case SLA_EVENT_HOLD: 06222 sla_handle_hold_event(event); 06223 break; 06224 case SLA_EVENT_DIAL_STATE: 06225 sla_handle_dial_state_event(); 06226 break; 06227 case SLA_EVENT_RINGING_TRUNK: 06228 sla_handle_ringing_trunk_event(); 06229 break; 06230 case SLA_EVENT_RELOAD: 06231 sla.reload = 1; 06232 case SLA_EVENT_CHECK_RELOAD: 06233 break; 06234 } 06235 ast_free(event); 06236 ast_mutex_lock(&sla.lock); 06237 } 06238 06239 if (sla.reload) { 06240 sla_check_reload(); 06241 } 06242 } 06243 06244 ast_mutex_unlock(&sla.lock); 06245 06246 while ((ringing_station = AST_LIST_REMOVE_HEAD(&sla.ringing_stations, entry))) 06247 ast_free(ringing_station); 06248 06249 while ((failed_station = AST_LIST_REMOVE_HEAD(&sla.failed_stations, entry))) 06250 ast_free(failed_station); 06251 06252 return NULL; 06253 }
static int sla_trunk_exec | ( | struct ast_channel * | chan, | |
const char * | data | |||
) | [static] |
Definition at line 6618 of file app_meetme.c.
References ALL_TRUNK_REFS, args, AST_APP_ARG, ast_app_parse_options(), ast_atomic_fetchadd_int(), AST_CONTROL_RINGING, AST_DECLARE_APP_ARGS, ast_free, 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_flag64, AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), ast_test_flag, build_conf(), conf_run(), CONFFLAG_MARKEDEXIT, CONFFLAG_MARKEDUSER, CONFFLAG_MOH, CONFFLAG_NO_AUDIO_UNTIL_UP, CONFFLAG_PASS_DTMF, CONFFLAG_QUIET, dispose_conf(), LOG_ERROR, MAX_CONFNUM, parse(), pbx_builtin_getvar_helper(), pbx_builtin_setvar_helper(), queue_ringing_trunk(), sla, sla_change_trunk_state(), SLA_EVENT_CHECK_RELOAD, SLA_EVENT_RINGING_TRUNK, sla_find_trunk(), sla_queue_event(), SLA_TRUNK_OPT_ARG_ARRAY_SIZE, SLA_TRUNK_OPT_MOH, SLA_TRUNK_STATE_IDLE, and sla_ringing_trunk::trunk.
Referenced by load_module().
06619 { 06620 char conf_name[MAX_CONFNUM]; 06621 struct ast_conference *conf; 06622 struct ast_flags64 conf_flags = { 0 }; 06623 struct sla_trunk *trunk; 06624 struct sla_ringing_trunk *ringing_trunk; 06625 AST_DECLARE_APP_ARGS(args, 06626 AST_APP_ARG(trunk_name); 06627 AST_APP_ARG(options); 06628 ); 06629 char *opts[SLA_TRUNK_OPT_ARG_ARRAY_SIZE] = { NULL, }; 06630 struct ast_flags opt_flags = { 0 }; 06631 char *parse; 06632 06633 if (ast_strlen_zero(data)) { 06634 ast_log(LOG_ERROR, "The SLATrunk application requires an argument, the trunk name\n"); 06635 return -1; 06636 } 06637 06638 parse = ast_strdupa(data); 06639 AST_STANDARD_APP_ARGS(args, parse); 06640 if (args.argc == 2) { 06641 if (ast_app_parse_options(sla_trunk_opts, &opt_flags, opts, args.options)) { 06642 ast_log(LOG_ERROR, "Error parsing options for SLATrunk\n"); 06643 return -1; 06644 } 06645 } 06646 06647 AST_RWLIST_RDLOCK(&sla_trunks); 06648 trunk = sla_find_trunk(args.trunk_name); 06649 if (trunk) 06650 ast_atomic_fetchadd_int((int *) &trunk->ref_count, 1); 06651 AST_RWLIST_UNLOCK(&sla_trunks); 06652 06653 if (!trunk) { 06654 ast_log(LOG_ERROR, "SLA Trunk '%s' not found!\n", args.trunk_name); 06655 pbx_builtin_setvar_helper(chan, "SLATRUNK_STATUS", "FAILURE"); 06656 sla_queue_event(SLA_EVENT_CHECK_RELOAD); 06657 return 0; 06658 } 06659 06660 if (trunk->chan) { 06661 ast_log(LOG_ERROR, "Call came in on %s, but the trunk is already in use!\n", 06662 args.trunk_name); 06663 pbx_builtin_setvar_helper(chan, "SLATRUNK_STATUS", "FAILURE"); 06664 ast_atomic_fetchadd_int((int *) &trunk->ref_count, -1); 06665 sla_queue_event(SLA_EVENT_CHECK_RELOAD); 06666 return 0; 06667 } 06668 06669 trunk->chan = chan; 06670 06671 if (!(ringing_trunk = queue_ringing_trunk(trunk))) { 06672 pbx_builtin_setvar_helper(chan, "SLATRUNK_STATUS", "FAILURE"); 06673 ast_atomic_fetchadd_int((int *) &trunk->ref_count, -1); 06674 sla_queue_event(SLA_EVENT_CHECK_RELOAD); 06675 return 0; 06676 } 06677 06678 snprintf(conf_name, sizeof(conf_name), "SLA_%s", args.trunk_name); 06679 conf = build_conf(conf_name, "", "", 1, 1, 1, chan, NULL); 06680 if (!conf) { 06681 pbx_builtin_setvar_helper(chan, "SLATRUNK_STATUS", "FAILURE"); 06682 ast_atomic_fetchadd_int((int *) &trunk->ref_count, -1); 06683 sla_queue_event(SLA_EVENT_CHECK_RELOAD); 06684 return 0; 06685 } 06686 ast_set_flag64(&conf_flags, 06687 CONFFLAG_QUIET | CONFFLAG_MARKEDEXIT | CONFFLAG_MARKEDUSER | CONFFLAG_PASS_DTMF | CONFFLAG_NO_AUDIO_UNTIL_UP); 06688 06689 if (ast_test_flag(&opt_flags, SLA_TRUNK_OPT_MOH)) { 06690 ast_indicate(chan, -1); 06691 ast_set_flag64(&conf_flags, CONFFLAG_MOH); 06692 } else 06693 ast_indicate(chan, AST_CONTROL_RINGING); 06694 06695 conf_run(chan, conf, &conf_flags, opts); 06696 dispose_conf(conf); 06697 conf = NULL; 06698 trunk->chan = NULL; 06699 trunk->on_hold = 0; 06700 06701 sla_change_trunk_state(trunk, SLA_TRUNK_STATE_IDLE, ALL_TRUNK_REFS, NULL); 06702 06703 if (!pbx_builtin_getvar_helper(chan, "SLATRUNK_STATUS")) 06704 pbx_builtin_setvar_helper(chan, "SLATRUNK_STATUS", "SUCCESS"); 06705 06706 /* Remove the entry from the list of ringing trunks if it is still there. */ 06707 ast_mutex_lock(&sla.lock); 06708 AST_LIST_TRAVERSE_SAFE_BEGIN(&sla.ringing_trunks, ringing_trunk, entry) { 06709 if (ringing_trunk->trunk == trunk) { 06710 AST_LIST_REMOVE_CURRENT(entry); 06711 break; 06712 } 06713 } 06714 AST_LIST_TRAVERSE_SAFE_END; 06715 ast_mutex_unlock(&sla.lock); 06716 if (ringing_trunk) { 06717 ast_free(ringing_trunk); 06718 pbx_builtin_setvar_helper(chan, "SLATRUNK_STATUS", "UNANSWERED"); 06719 /* Queue reprocessing of ringing trunks to make stations stop ringing 06720 * that shouldn't be ringing after this trunk stopped. */ 06721 sla_queue_event(SLA_EVENT_RINGING_TRUNK); 06722 } 06723 06724 ast_atomic_fetchadd_int((int *) &trunk->ref_count, -1); 06725 sla_queue_event(SLA_EVENT_CHECK_RELOAD); 06726 06727 return 0; 06728 }
static const char* trunkstate2str | ( | enum sla_trunk_state | state | ) | [static] |
Definition at line 1771 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().
01772 { 01773 #define S(e) case e: return # e; 01774 switch (state) { 01775 S(SLA_TRUNK_STATE_IDLE) 01776 S(SLA_TRUNK_STATE_RINGING) 01777 S(SLA_TRUNK_STATE_UP) 01778 S(SLA_TRUNK_STATE_ONHOLD) 01779 S(SLA_TRUNK_STATE_ONHOLD_BYME) 01780 } 01781 return "Uknown State"; 01782 #undef S 01783 }
static void tweak_listen_volume | ( | struct ast_conf_user * | user, | |
enum volume_action | action | |||
) | [static] |
Definition at line 1103 of file app_meetme.c.
References volume::actual, volume::desired, ast_conf_user::listen, set_listen_volume(), and tweak_volume().
Referenced by admin_exec(), meetme_menu_admin(), meetme_menu_normal(), user_listen_voldown_cb(), and user_listen_volup_cb().
01104 { 01105 tweak_volume(&user->listen, action); 01106 /* attempt to make the adjustment in the channel driver; 01107 if successful, don't adjust in the frame reading routine 01108 */ 01109 if (!set_listen_volume(user, user->listen.desired)) 01110 user->listen.actual = 0; 01111 else 01112 user->listen.actual = user->listen.desired; 01113 }
static void tweak_talk_volume | ( | struct ast_conf_user * | user, | |
enum volume_action | action | |||
) | [static] |
Definition at line 1091 of file app_meetme.c.
References volume::actual, volume::desired, set_talk_volume(), ast_conf_user::talk, and tweak_volume().
Referenced by admin_exec(), meetme_menu_admin(), meetme_menu_normal(), user_talk_voldown_cb(), and user_talk_volup_cb().
01092 { 01093 tweak_volume(&user->talk, action); 01094 /* attempt to make the adjustment in the channel driver; 01095 if successful, don't adjust in the frame reading routine 01096 */ 01097 if (!set_talk_volume(user, user->talk.desired)) 01098 user->talk.actual = 0; 01099 else 01100 user->talk.actual = user->talk.desired; 01101 }
static void tweak_volume | ( | struct volume * | vol, | |
enum volume_action | action | |||
) | [static] |
Definition at line 1056 of file app_meetme.c.
References volume::desired, VOL_DOWN, and VOL_UP.
Referenced by tweak_listen_volume(), and tweak_talk_volume().
01057 { 01058 switch (action) { 01059 case VOL_UP: 01060 switch (vol->desired) { 01061 case 5: 01062 break; 01063 case 0: 01064 vol->desired = 2; 01065 break; 01066 case -2: 01067 vol->desired = 0; 01068 break; 01069 default: 01070 vol->desired++; 01071 break; 01072 } 01073 break; 01074 case VOL_DOWN: 01075 switch (vol->desired) { 01076 case -5: 01077 break; 01078 case 2: 01079 vol->desired = 0; 01080 break; 01081 case 0: 01082 vol->desired = -2; 01083 break; 01084 default: 01085 vol->desired--; 01086 break; 01087 } 01088 } 01089 }
static int unload_module | ( | void | ) | [static] |
Definition at line 7426 of file app_meetme.c.
References ARRAY_LEN, ast_cli_unregister_multiple(), ast_custom_function_unregister(), ast_data_unregister, ast_devstate_prov_del(), ast_manager_unregister(), AST_TEST_UNREGISTER, ast_unload_realtime(), ast_unregister_application(), and sla_destroy().
07427 { 07428 int res = 0; 07429 07430 ast_cli_unregister_multiple(cli_meetme, ARRAY_LEN(cli_meetme)); 07431 res = ast_manager_unregister("MeetmeMute"); 07432 res |= ast_manager_unregister("MeetmeUnmute"); 07433 res |= ast_manager_unregister("MeetmeList"); 07434 res |= ast_unregister_application(app4); 07435 res |= ast_unregister_application(app3); 07436 res |= ast_unregister_application(app2); 07437 res |= ast_unregister_application(app); 07438 res |= ast_unregister_application(slastation_app); 07439 res |= ast_unregister_application(slatrunk_app); 07440 07441 #ifdef TEST_FRAMEWORK 07442 AST_TEST_UNREGISTER(test_meetme_data_provider); 07443 #endif 07444 ast_data_unregister(NULL); 07445 07446 ast_devstate_prov_del("Meetme"); 07447 ast_devstate_prov_del("SLA"); 07448 07449 sla_destroy(); 07450 07451 res |= ast_custom_function_unregister(&meetme_info_acf); 07452 ast_unload_realtime("meetme"); 07453 07454 return res; 07455 }
static int user_add_provider_cb | ( | void * | obj, | |
void * | arg, | |||
int | flags | |||
) | [static] |
Definition at line 7277 of file app_meetme.c.
References volume::actual, ast_channel_data_add_structure(), ast_data_add_int(), ast_data_add_node(), ast_data_add_structure, ast_conf_user::chan, volume::desired, ast_conf_user::listen, and ast_conf_user::talk.
Referenced by meetme_data_provider_get().
07278 { 07279 struct ast_data *data_meetme_user; 07280 struct ast_data *data_meetme_user_channel; 07281 struct ast_data *data_meetme_user_volume; 07282 07283 struct ast_conf_user *user = obj; 07284 struct ast_data *data_meetme_users = arg; 07285 07286 data_meetme_user = ast_data_add_node(data_meetme_users, "user"); 07287 if (!data_meetme_user) { 07288 return 0; 07289 } 07290 /* user structure */ 07291 ast_data_add_structure(ast_conf_user, data_meetme_user, user); 07292 07293 /* user's channel */ 07294 data_meetme_user_channel = ast_data_add_node(data_meetme_user, "channel"); 07295 if (!data_meetme_user_channel) { 07296 return 0; 07297 } 07298 07299 ast_channel_data_add_structure(data_meetme_user_channel, user->chan, 1); 07300 07301 /* volume structure */ 07302 data_meetme_user_volume = ast_data_add_node(data_meetme_user, "listen-volume"); 07303 if (!data_meetme_user_volume) { 07304 return 0; 07305 } 07306 ast_data_add_int(data_meetme_user_volume, "desired", user->listen.desired); 07307 ast_data_add_int(data_meetme_user_volume, "actual", user->listen.actual); 07308 07309 data_meetme_user_volume = ast_data_add_node(data_meetme_user, "talk-volume"); 07310 if (!data_meetme_user_volume) { 07311 return 0; 07312 } 07313 ast_data_add_int(data_meetme_user_volume, "desired", user->talk.desired); 07314 ast_data_add_int(data_meetme_user_volume, "actual", user->talk.actual); 07315 07316 return 0; 07317 }
static int user_chan_cb | ( | void * | obj, | |
void * | args, | |||
int | flags | |||
) | [static] |
Definition at line 4741 of file app_meetme.c.
References ast_conf_user::chan, CMP_MATCH, and CMP_STOP.
Referenced by channel_admin_exec().
static int user_listen_voldown_cb | ( | void * | obj, | |
void * | unused, | |||
int | flags | |||
) | [static] |
Definition at line 4713 of file app_meetme.c.
References tweak_listen_volume(), and VOL_DOWN.
Referenced by admin_exec().
04714 { 04715 struct ast_conf_user *user = obj; 04716 tweak_listen_volume(user, VOL_DOWN); 04717 return 0; 04718 }
static int user_listen_volup_cb | ( | void * | obj, | |
void * | unused, | |||
int | flags | |||
) | [static] |
Definition at line 4706 of file app_meetme.c.
References tweak_listen_volume(), and VOL_UP.
Referenced by admin_exec().
04707 { 04708 struct ast_conf_user *user = obj; 04709 tweak_listen_volume(user, VOL_UP); 04710 return 0; 04711 }
static int user_max_cmp | ( | void * | obj, | |
void * | arg, | |||
int | flags | |||
) | [static] |
Definition at line 1176 of file app_meetme.c.
References ast_conf_user::user_no.
Referenced by admin_exec(), conf_run(), and meetme_menu_admin().
01177 { 01178 struct ast_conf_user *user = obj; 01179 int *max_no = arg; 01180 01181 if (user->user_no > *max_no) { 01182 *max_no = user->user_no; 01183 } 01184 01185 return 0; 01186 }
static int user_no_cmp | ( | void * | obj, | |
void * | arg, | |||
int | flags | |||
) | [static] |
Definition at line 1164 of file app_meetme.c.
References CMP_MATCH, CMP_STOP, and ast_conf_user::user_no.
Referenced by build_conf().
static int user_reset_vol_cb | ( | void * | obj, | |
void * | unused, | |||
int | flags | |||
) | [static] |
Definition at line 4734 of file app_meetme.c.
References reset_volumes().
Referenced by admin_exec().
04735 { 04736 struct ast_conf_user *user = obj; 04737 reset_volumes(user); 04738 return 0; 04739 }
static int user_set_kickme_cb | ( | void * | obj, | |
void * | check_admin_arg, | |||
int | flags | |||
) | [static] |
Definition at line 2262 of file app_meetme.c.
References ADMINFLAG_KICKME, ast_conf_user::adminflags, ast_test_flag64, CONFFLAG_ADMIN, and ast_conf_user::userflags.
Referenced by admin_exec(), and meetme_menu_admin_extended().
02263 { 02264 struct ast_conf_user *user = obj; 02265 /* actual pointer contents of check_admin_arg is irrelevant */ 02266 02267 if (!check_admin_arg || (check_admin_arg && !ast_test_flag64(&user->userflags, CONFFLAG_ADMIN))) { 02268 user->adminflags |= ADMINFLAG_KICKME; 02269 } 02270 return 0; 02271 }
static int user_set_muted_cb | ( | void * | obj, | |
void * | check_admin_arg, | |||
int | flags | |||
) | [static] |
Definition at line 2284 of file app_meetme.c.
References ADMINFLAG_MUTED, ast_conf_user::adminflags, ast_test_flag64, CONFFLAG_ADMIN, and ast_conf_user::userflags.
Referenced by admin_exec(), and meetme_menu_admin_extended().
02285 { 02286 struct ast_conf_user *user = obj; 02287 /* actual pointer contents of check_admin_arg is irrelevant */ 02288 02289 if (!check_admin_arg || !ast_test_flag64(&user->userflags, CONFFLAG_ADMIN)) { 02290 user->adminflags |= ADMINFLAG_MUTED; 02291 } 02292 return 0; 02293 }
static int user_set_unmuted_cb | ( | void * | obj, | |
void * | check_admin_arg, | |||
int | flags | |||
) | [static] |
Definition at line 2273 of file app_meetme.c.
References ADMINFLAG_MUTED, ADMINFLAG_SELFMUTED, ADMINFLAG_T_REQUEST, ast_conf_user::adminflags, ast_test_flag64, CONFFLAG_ADMIN, and ast_conf_user::userflags.
Referenced by admin_exec(), and meetme_menu_admin_extended().
02274 { 02275 struct ast_conf_user *user = obj; 02276 /* actual pointer contents of check_admin_arg is irrelevant */ 02277 02278 if (!check_admin_arg || !ast_test_flag64(&user->userflags, CONFFLAG_ADMIN)) { 02279 user->adminflags &= ~(ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED | ADMINFLAG_T_REQUEST); 02280 } 02281 return 0; 02282 }
static int user_talk_voldown_cb | ( | void * | obj, | |
void * | unused, | |||
int | flags | |||
) | [static] |
Definition at line 4727 of file app_meetme.c.
References tweak_talk_volume(), and VOL_DOWN.
Referenced by admin_exec().
04728 { 04729 struct ast_conf_user *user = obj; 04730 tweak_talk_volume(user, VOL_DOWN); 04731 return 0; 04732 }
static int user_talk_volup_cb | ( | void * | obj, | |
void * | unused, | |||
int | flags | |||
) | [static] |
Definition at line 4720 of file app_meetme.c.
References tweak_talk_volume(), and VOL_UP.
Referenced by admin_exec().
04721 { 04722 struct ast_conf_user *user = obj; 04723 tweak_talk_volume(user, VOL_UP); 04724 return 0; 04725 }
const char* const app = "MeetMe" [static] |
Definition at line 676 of file app_meetme.c.
const char* const app2 = "MeetMeCount" [static] |
Definition at line 677 of file app_meetme.c.
const char* const app3 = "MeetMeAdmin" [static] |
Definition at line 678 of file app_meetme.c.
const char* const app4 = "MeetMeChannelAdmin" [static] |
Definition at line 679 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 968 of file app_meetme.c.
struct ast_cli_entry cli_meetme[] [static] |
Definition at line 1861 of file app_meetme.c.
Definition at line 950 of file app_meetme.c.
Referenced by _macro_exec(), ast_safe_sleep_conditional(), gosubif_exec(), and smdi_message_wait().
unsigned int conf_map[1024] = {0, } [static] |
Definition at line 761 of file app_meetme.c.
Referenced by build_conf(), conf_exec(), and dispose_conf().
int earlyalert [static] |
Definition at line 686 of file app_meetme.c.
int endalert [static] |
Definition at line 687 of file app_meetme.c.
int extendby [static] |
Definition at line 688 of file app_meetme.c.
int fuzzystart [static] |
Definition at line 685 of file app_meetme.c.
const char gain_map[] [static] |
Map 'volume' levels from -5 through +5 into decibel (dB) settings for channel drivers.
Definition at line 977 of file app_meetme.c.
Definition at line 951 of file app_meetme.c.
Referenced by ast_localtime_wakeup_monitor(), reload(), smdi_message_wait(), and write_cdr().
struct ast_data_handler meetme_data_provider [static] |
{ .version = AST_DATA_HANDLER_VERSION, .get = meetme_data_provider_get }
Definition at line 7357 of file app_meetme.c.
struct ast_data_entry meetme_data_providers[] [static] |
{ AST_DATA_ENTRY("asterisk/application/meetme/list", &meetme_data_provider), }
Definition at line 7362 of file app_meetme.c.
struct ast_custom_function meetme_info_acf [static] |
{ .name = "MEETME_INFO", .read = acf_meetme_info, }
Definition at line 7228 of file app_meetme.c.
int rt_log_members [static] |
Log participant count to the RealTime backend
Definition at line 691 of file app_meetme.c.
int rt_schedule [static] |
Definition at line 684 of file app_meetme.c.
struct { ... } sla [static] |
A structure for data used by the sla thread.
Referenced by dial_trunk(), load_config(), queue_ringing_trunk(), sla_calc_station_timeouts(), sla_calc_trunk_timeouts(), sla_check_failed_station(), sla_check_reload(), 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_station_exec(), sla_stop_ringing_station(), sla_thread(), and sla_trunk_exec().
const char sla_registrar[] = "SLA" [static] |
Definition at line 891 of file app_meetme.c.
Referenced by destroy_station(), destroy_trunk(), sla_build_station(), sla_build_trunk(), and sla_destroy().
const char* const slastation_app = "SLAStation" [static] |
Definition at line 680 of file app_meetme.c.
const char* const slatrunk_app = "SLATrunk" [static] |
Definition at line 681 of file app_meetme.c.
pthread_t thread |
The SLA thread ID
Definition at line 949 of file app_meetme.c.
Referenced by __schedule_action(), ast_bridge_depart(), ast_bridge_destroy(), bridge_call_thread_launch(), cleanup_thread_list(), find_idle_thread(), handle_cli_iax2_show_threads(), iax2_process_thread(), iax2_process_thread_cleanup(), launch_monitor_thread(), load_module(), multiplexed_add_or_remove(), socket_read(), start_network_thread(), and unload_module().