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 |
A reference to a station. More... | |
struct | sla_trunk |
struct | sla_trunk_ref |
A station's reference to a trunk. More... | |
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 } |
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 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 * | 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, int recordingtmp_size) |
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, int recordingtmp_size) |
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 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_failed_station * | sla_create_failed_station (struct sla_station *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 void | sla_event_destroy (struct sla_event *event) |
static void | sla_failed_station_destroy (struct sla_failed_station *failed_station) |
static struct sla_station * | sla_find_station (const char *name) |
static struct sla_trunk * | sla_find_trunk (const char *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_in_use (void) |
static int | sla_load_config (int reload) |
static int | sla_process_timers (struct timespec *ts) |
Calculate the time until the next known event. | |
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 void | sla_ringing_station_destroy (struct sla_ringing_station *ringing_station) |
static void | sla_ringing_trunk_destroy (struct sla_ringing_trunk *ringing_trunk) |
static char * | sla_show_stations (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | sla_show_trunks (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static enum ast_device_state | sla_state (const char *data) |
static enum ast_device_state | sla_state_to_devstate (enum sla_trunk_state state) |
static int | sla_station_cmp (void *obj, void *arg, int flags) |
static void | sla_station_destructor (void *obj) |
static int | sla_station_exec (struct ast_channel *chan, const char *data) |
static int | sla_station_hash (const void *obj, const int flags) |
static int | sla_station_is_marked (void *obj, void *arg, int flags) |
static int | sla_station_mark (void *obj, void *arg, int flags) |
static void | sla_station_ref_destructor (void *obj) |
static int | sla_station_release_refs (void *obj, void *arg, int flags) |
static void | sla_stop_ringing_station (struct sla_ringing_station *ringing_station, enum sla_station_hangup hangup) |
static void | sla_stop_ringing_trunk (struct sla_ringing_trunk *ringing_trunk) |
static void * | sla_thread (void *data) |
static int | sla_trunk_cmp (void *obj, void *arg, int flags) |
static void | sla_trunk_destructor (void *obj) |
static int | sla_trunk_exec (struct ast_channel *chan, const char *data) |
static int | sla_trunk_hash (const void *obj, const int flags) |
static int | sla_trunk_is_marked (void *obj, void *arg, int flags) |
static int | sla_trunk_mark (void *obj, void *arg, int flags) |
static void | sla_trunk_ref_destructor (void *obj) |
static int | sla_trunk_release_refs (void *obj, void *arg, int flags) |
static const char * | trunkstate2str (enum sla_trunk_state state) |
static 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 struct ao2_container * | sla_stations |
static struct ao2_container * | sla_trunks |
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 7541 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 7558 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 6738 of file app_meetme.c.
06738 { 06739 SLA_TRUNK_OPT_MOH = (1 << 0), 06740 };
anonymous enum |
Definition at line 6742 of file app_meetme.c.
06742 { 06743 SLA_TRUNK_OPT_ARG_MOH_CLASS = 0, 06744 SLA_TRUNK_OPT_ARG_ARRAY_SIZE = 1, 06745 };
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 2332 of file app_meetme.c.
02332 { 02333 MENU_DISABLED = 0, 02334 MENU_NORMAL, 02335 MENU_ADMIN, 02336 MENU_ADMIN_EXTENDED, 02337 };
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 |
Definition at line 911 of file app_meetme.c.
00911 { 00912 /*! A station has put the call on hold */ 00913 SLA_EVENT_HOLD, 00914 /*! The state of a dial has changed */ 00915 SLA_EVENT_DIAL_STATE, 00916 /*! The state of a ringing trunk has changed */ 00917 SLA_EVENT_RINGING_TRUNK, 00918 };
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 944 of file app_meetme.c.
00944 { 00945 SLA_STATION_HANGUP_NORMAL, 00946 SLA_STATION_HANGUP_TIMEOUT, 00947 };
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 7478 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().
07479 { 07480 struct ast_conference *conf; 07481 char *parse; 07482 int result = -2; /* only non-negative numbers valid, -1 is used elsewhere */ 07483 AST_DECLARE_APP_ARGS(args, 07484 AST_APP_ARG(keyword); 07485 AST_APP_ARG(confno); 07486 ); 07487 07488 if (ast_strlen_zero(data)) { 07489 ast_log(LOG_ERROR, "Syntax: MEETME_INFO() requires two arguments\n"); 07490 return -1; 07491 } 07492 07493 parse = ast_strdupa(data); 07494 AST_STANDARD_APP_ARGS(args, parse); 07495 07496 if (ast_strlen_zero(args.keyword)) { 07497 ast_log(LOG_ERROR, "Syntax: MEETME_INFO() requires a keyword\n"); 07498 return -1; 07499 } 07500 07501 if (ast_strlen_zero(args.confno)) { 07502 ast_log(LOG_ERROR, "Syntax: MEETME_INFO() requires a conference number\n"); 07503 return -1; 07504 } 07505 07506 AST_LIST_LOCK(&confs); 07507 AST_LIST_TRAVERSE(&confs, conf, list) { 07508 if (!strcmp(args.confno, conf->confno)) { 07509 result = acf_meetme_info_eval(args.keyword, conf); 07510 break; 07511 } 07512 } 07513 AST_LIST_UNLOCK(&confs); 07514 07515 if (result > -1) { 07516 snprintf(buf, len, "%d", result); 07517 } else if (result == -1) { 07518 ast_log(LOG_NOTICE, "Error: invalid keyword: '%s'\n", args.keyword); 07519 snprintf(buf, len, "0"); 07520 } else if (result == -2) { 07521 ast_log(LOG_NOTICE, "Error: conference (%s) not found\n", args.confno); 07522 snprintf(buf, len, "0"); 07523 } 07524 07525 return 0; 07526 }
static int acf_meetme_info_eval | ( | const char * | keyword, | |
const struct ast_conference * | conf | |||
) | [static] |
Definition at line 7460 of file app_meetme.c.
References ast_conference::isdynamic, ast_conference::locked, ast_conference::start, and ast_conference::users.
Referenced by acf_meetme_info().
07461 { 07462 if (!strcasecmp("lock", keyword)) { 07463 return conf->locked; 07464 } else if (!strcasecmp("parties", keyword)) { 07465 return conf->users; 07466 } else if (!strcasecmp("activity", keyword)) { 07467 time_t now; 07468 now = time(NULL); 07469 return (now - conf->start); 07470 } else if (!strcasecmp("dynamic", keyword)) { 07471 return conf->isdynamic; 07472 } else { 07473 return -1; 07474 } 07475 07476 }
static int action_meetmelist | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 5105 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().
05106 { 05107 const char *actionid = astman_get_header(m, "ActionID"); 05108 const char *conference = astman_get_header(m, "Conference"); 05109 char idText[80] = ""; 05110 struct ast_conference *cnf; 05111 struct ast_conf_user *user; 05112 struct ao2_iterator user_iter; 05113 int total = 0; 05114 05115 if (!ast_strlen_zero(actionid)) 05116 snprintf(idText, sizeof(idText), "ActionID: %s\r\n", actionid); 05117 05118 if (AST_LIST_EMPTY(&confs)) { 05119 astman_send_error(s, m, "No active conferences."); 05120 return 0; 05121 } 05122 05123 astman_send_listack(s, m, "Meetme user list will follow", "start"); 05124 05125 /* Find the right conference */ 05126 AST_LIST_LOCK(&confs); 05127 AST_LIST_TRAVERSE(&confs, cnf, list) { 05128 /* If we ask for one particular, and this isn't it, skip it */ 05129 if (!ast_strlen_zero(conference) && strcmp(cnf->confno, conference)) 05130 continue; 05131 05132 /* Show all the users */ 05133 user_iter = ao2_iterator_init(cnf->usercontainer, 0); 05134 while ((user = ao2_iterator_next(&user_iter))) { 05135 total++; 05136 astman_append(s, 05137 "Event: MeetmeList\r\n" 05138 "%s" 05139 "Conference: %s\r\n" 05140 "UserNumber: %d\r\n" 05141 "CallerIDNum: %s\r\n" 05142 "CallerIDName: %s\r\n" 05143 "ConnectedLineNum: %s\r\n" 05144 "ConnectedLineName: %s\r\n" 05145 "Channel: %s\r\n" 05146 "Admin: %s\r\n" 05147 "Role: %s\r\n" 05148 "MarkedUser: %s\r\n" 05149 "Muted: %s\r\n" 05150 "Talking: %s\r\n" 05151 "\r\n", 05152 idText, 05153 cnf->confno, 05154 user->user_no, 05155 S_COR(user->chan->caller.id.number.valid, user->chan->caller.id.number.str, "<unknown>"), 05156 S_COR(user->chan->caller.id.name.valid, user->chan->caller.id.name.str, "<no name>"), 05157 S_COR(user->chan->connected.id.number.valid, user->chan->connected.id.number.str, "<unknown>"), 05158 S_COR(user->chan->connected.id.name.valid, user->chan->connected.id.name.str, "<no name>"), 05159 user->chan->name, 05160 ast_test_flag64(&user->userflags, CONFFLAG_ADMIN) ? "Yes" : "No", 05161 ast_test_flag64(&user->userflags, CONFFLAG_MONITOR) ? "Listen only" : ast_test_flag64(&user->userflags, CONFFLAG_TALKER) ? "Talk only" : "Talk and listen", 05162 ast_test_flag64(&user->userflags, CONFFLAG_MARKEDUSER) ? "Yes" : "No", 05163 user->adminflags & ADMINFLAG_MUTED ? "By admin" : user->adminflags & ADMINFLAG_SELFMUTED ? "By self" : "No", 05164 user->talking > 0 ? "Yes" : user->talking == 0 ? "No" : "Not monitored"); 05165 ao2_ref(user, -1); 05166 } 05167 ao2_iterator_destroy(&user_iter); 05168 } 05169 AST_LIST_UNLOCK(&confs); 05170 /* Send final confirmation */ 05171 astman_append(s, 05172 "Event: MeetmeListComplete\r\n" 05173 "EventList: Complete\r\n" 05174 "ListItems: %d\r\n" 05175 "%s" 05176 "\r\n", total, idText); 05177 return 0; 05178 }
static int action_meetmemute | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 5095 of file app_meetme.c.
References meetmemute().
Referenced by load_module().
05096 { 05097 return meetmemute(s, m, 1); 05098 }
static int action_meetmeunmute | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 5100 of file app_meetme.c.
References meetmemute().
Referenced by load_module().
05101 { 05102 return meetmemute(s, m, 0); 05103 }
static int admin_exec | ( | struct ast_channel * | chan, | |
const char * | data | |||
) | [static] |
The MeetMeadmin application.
MeetMeAdmin(confno, command, caller)
Definition at line 4807 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().
04807 { 04808 char *params; 04809 struct ast_conference *cnf; 04810 struct ast_conf_user *user = NULL; 04811 AST_DECLARE_APP_ARGS(args, 04812 AST_APP_ARG(confno); 04813 AST_APP_ARG(command); 04814 AST_APP_ARG(user); 04815 ); 04816 int res = 0; 04817 04818 if (ast_strlen_zero(data)) { 04819 ast_log(LOG_WARNING, "MeetMeAdmin requires an argument!\n"); 04820 pbx_builtin_setvar_helper(chan, "MEETMEADMINSTATUS", "NOPARSE"); 04821 return -1; 04822 } 04823 04824 params = ast_strdupa(data); 04825 AST_STANDARD_APP_ARGS(args, params); 04826 04827 if (!args.command) { 04828 ast_log(LOG_WARNING, "MeetmeAdmin requires a command!\n"); 04829 pbx_builtin_setvar_helper(chan, "MEETMEADMINSTATUS", "NOPARSE"); 04830 return -1; 04831 } 04832 04833 AST_LIST_LOCK(&confs); 04834 AST_LIST_TRAVERSE(&confs, cnf, list) { 04835 if (!strcmp(cnf->confno, args.confno)) 04836 break; 04837 } 04838 04839 if (!cnf) { 04840 ast_log(LOG_WARNING, "Conference number '%s' not found!\n", args.confno); 04841 AST_LIST_UNLOCK(&confs); 04842 pbx_builtin_setvar_helper(chan, "MEETMEADMINSTATUS", "NOTFOUND"); 04843 return 0; 04844 } 04845 04846 ast_atomic_fetchadd_int(&cnf->refcount, 1); 04847 04848 if (args.user) { 04849 user = find_user(cnf, args.user); 04850 if (!user) { 04851 ast_log(LOG_NOTICE, "Specified User not found!\n"); 04852 res = -2; 04853 goto usernotfound; 04854 } 04855 } else { 04856 /* fail for commands that require a user */ 04857 switch (*args.command) { 04858 case 'm': /* Unmute */ 04859 case 'M': /* Mute */ 04860 case 't': /* Lower user's talk volume */ 04861 case 'T': /* Raise user's talk volume */ 04862 case 'u': /* Lower user's listen volume */ 04863 case 'U': /* Raise user's listen volume */ 04864 case 'r': /* Reset user's volume level */ 04865 case 'k': /* Kick user */ 04866 res = -2; 04867 ast_log(LOG_NOTICE, "No user specified!\n"); 04868 goto usernotfound; 04869 default: 04870 break; 04871 } 04872 } 04873 04874 switch (*args.command) { 04875 case 76: /* L: Lock */ 04876 cnf->locked = 1; 04877 break; 04878 case 108: /* l: Unlock */ 04879 cnf->locked = 0; 04880 break; 04881 case 75: /* K: kick all users */ 04882 ao2_callback(cnf->usercontainer, OBJ_NODATA, user_set_kickme_cb, NULL); 04883 break; 04884 case 101: /* e: Eject last user*/ 04885 { 04886 int max_no = 0; 04887 struct ast_conf_user *eject_user; 04888 04889 ao2_callback(cnf->usercontainer, OBJ_NODATA, user_max_cmp, &max_no); 04890 eject_user = ao2_find(cnf->usercontainer, &max_no, 0); 04891 if (!eject_user) { 04892 res = -1; 04893 ast_log(LOG_NOTICE, "No last user to kick!\n"); 04894 break; 04895 } 04896 04897 if (!ast_test_flag64(&eject_user->userflags, CONFFLAG_ADMIN)) { 04898 eject_user->adminflags |= ADMINFLAG_KICKME; 04899 } else { 04900 res = -1; 04901 ast_log(LOG_NOTICE, "Not kicking last user, is an Admin!\n"); 04902 } 04903 04904 ao2_ref(eject_user, -1); 04905 break; 04906 } 04907 case 77: /* M: Mute */ 04908 user->adminflags |= ADMINFLAG_MUTED; 04909 break; 04910 case 78: /* N: Mute all (non-admin) users */ 04911 ao2_callback(cnf->usercontainer, OBJ_NODATA, user_set_muted_cb, &cnf); 04912 break; 04913 case 109: /* m: Unmute */ 04914 user->adminflags &= ~(ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED | ADMINFLAG_T_REQUEST); 04915 break; 04916 case 110: /* n: Unmute all users */ 04917 ao2_callback(cnf->usercontainer, OBJ_NODATA, user_set_unmuted_cb, NULL); 04918 break; 04919 case 107: /* k: Kick user */ 04920 user->adminflags |= ADMINFLAG_KICKME; 04921 break; 04922 case 118: /* v: Lower all users listen volume */ 04923 ao2_callback(cnf->usercontainer, OBJ_NODATA, user_listen_voldown_cb, NULL); 04924 break; 04925 case 86: /* V: Raise all users listen volume */ 04926 ao2_callback(cnf->usercontainer, OBJ_NODATA, user_listen_volup_cb, NULL); 04927 break; 04928 case 115: /* s: Lower all users speaking volume */ 04929 ao2_callback(cnf->usercontainer, OBJ_NODATA, user_talk_voldown_cb, NULL); 04930 break; 04931 case 83: /* S: Raise all users speaking volume */ 04932 ao2_callback(cnf->usercontainer, OBJ_NODATA, user_talk_volup_cb, NULL); 04933 break; 04934 case 82: /* R: Reset all volume levels */ 04935 ao2_callback(cnf->usercontainer, OBJ_NODATA, user_reset_vol_cb, NULL); 04936 break; 04937 case 114: /* r: Reset user's volume level */ 04938 reset_volumes(user); 04939 break; 04940 case 85: /* U: Raise user's listen volume */ 04941 tweak_listen_volume(user, VOL_UP); 04942 break; 04943 case 117: /* u: Lower user's listen volume */ 04944 tweak_listen_volume(user, VOL_DOWN); 04945 break; 04946 case 84: /* T: Raise user's talk volume */ 04947 tweak_talk_volume(user, VOL_UP); 04948 break; 04949 case 116: /* t: Lower user's talk volume */ 04950 tweak_talk_volume(user, VOL_DOWN); 04951 break; 04952 case 'E': /* E: Extend conference */ 04953 if (rt_extend_conf(args.confno)) { 04954 res = -1; 04955 } 04956 break; 04957 } 04958 04959 if (args.user) { 04960 /* decrement reference from find_user */ 04961 ao2_ref(user, -1); 04962 } 04963 usernotfound: 04964 AST_LIST_UNLOCK(&confs); 04965 04966 dispose_conf(cnf); 04967 pbx_builtin_setvar_helper(chan, "MEETMEADMINSTATUS", res == -2 ? "NOTFOUND" : res ? "FAILED" : "OK"); 04968 04969 return 0; 04970 }
static void* announce_thread | ( | void * | data | ) | [static] |
Definition at line 2208 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().
02209 { 02210 struct announce_listitem *current; 02211 struct ast_conference *conf = data; 02212 int res; 02213 char filename[PATH_MAX] = ""; 02214 AST_LIST_HEAD_NOLOCK(, announce_listitem) local_list; 02215 AST_LIST_HEAD_INIT_NOLOCK(&local_list); 02216 02217 while (!conf->announcethread_stop) { 02218 ast_mutex_lock(&conf->announcelistlock); 02219 if (conf->announcethread_stop) { 02220 ast_mutex_unlock(&conf->announcelistlock); 02221 break; 02222 } 02223 if (AST_LIST_EMPTY(&conf->announcelist)) 02224 ast_cond_wait(&conf->announcelist_addition, &conf->announcelistlock); 02225 02226 AST_LIST_APPEND_LIST(&local_list, &conf->announcelist, entry); 02227 AST_LIST_HEAD_INIT_NOLOCK(&conf->announcelist); 02228 02229 ast_mutex_unlock(&conf->announcelistlock); 02230 if (conf->announcethread_stop) { 02231 break; 02232 } 02233 02234 for (res = 1; !conf->announcethread_stop && (current = AST_LIST_REMOVE_HEAD(&local_list, entry)); ao2_ref(current, -1)) { 02235 ast_log(LOG_DEBUG, "About to play %s\n", current->namerecloc); 02236 if (!ast_fileexists(current->namerecloc, NULL, NULL)) 02237 continue; 02238 if ((current->confchan) && (current->confusers > 1) && !ast_check_hangup(current->confchan)) { 02239 if (!ast_streamfile(current->confchan, current->namerecloc, current->language)) 02240 res = ast_waitstream(current->confchan, ""); 02241 if (!res) { 02242 ast_copy_string(filename, get_announce_filename(current->announcetype), sizeof(filename)); 02243 if (!ast_streamfile(current->confchan, filename, current->language)) 02244 ast_waitstream(current->confchan, ""); 02245 } 02246 } 02247 if (current->announcetype == CONF_HASLEFT) { 02248 ast_filedelete(current->namerecloc, NULL); 02249 } 02250 } 02251 } 02252 02253 /* thread marked to stop, clean up */ 02254 while ((current = AST_LIST_REMOVE_HEAD(&local_list, entry))) { 02255 ast_filedelete(current->namerecloc, NULL); 02256 ao2_ref(current, -1); 02257 } 02258 return NULL; 02259 }
static void answer_trunk_chan | ( | struct ast_channel * | chan | ) | [static] |
Definition at line 5585 of file app_meetme.c.
References ast_answer(), and ast_indicate().
Referenced by run_station(), sla_handle_dial_state_event(), and sla_station_exec().
05586 { 05587 ast_answer(chan); 05588 ast_indicate(chan, -1); 05589 }
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 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 1213 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().
01216 { 01217 struct ast_conference *cnf; 01218 struct dahdi_confinfo dahdic = { 0, }; 01219 int confno_int = 0; 01220 01221 AST_LIST_LOCK(&confs); 01222 01223 AST_LIST_TRAVERSE(&confs, cnf, list) { 01224 if (!strcmp(confno, cnf->confno)) 01225 break; 01226 } 01227 01228 if (cnf || (!make && !dynamic)) 01229 goto cnfout; 01230 01231 /* Make a new one */ 01232 if (!(cnf = ast_calloc(1, sizeof(*cnf))) || 01233 !(cnf->usercontainer = ao2_container_alloc(1, NULL, user_no_cmp))) { 01234 goto cnfout; 01235 } 01236 01237 ast_mutex_init(&cnf->playlock); 01238 ast_mutex_init(&cnf->listenlock); 01239 cnf->recordthread = AST_PTHREADT_NULL; 01240 ast_mutex_init(&cnf->recordthreadlock); 01241 cnf->announcethread = AST_PTHREADT_NULL; 01242 ast_mutex_init(&cnf->announcethreadlock); 01243 ast_copy_string(cnf->confno, confno, sizeof(cnf->confno)); 01244 ast_copy_string(cnf->pin, pin, sizeof(cnf->pin)); 01245 ast_copy_string(cnf->pinadmin, pinadmin, sizeof(cnf->pinadmin)); 01246 ast_copy_string(cnf->uniqueid, chan->uniqueid, sizeof(cnf->uniqueid)); 01247 01248 /* Setup a new dahdi conference */ 01249 dahdic.confno = -1; 01250 dahdic.confmode = DAHDI_CONF_CONFANN | DAHDI_CONF_CONFANNMON; 01251 cnf->fd = open("/dev/dahdi/pseudo", O_RDWR); 01252 if (cnf->fd < 0 || ioctl(cnf->fd, DAHDI_SETCONF, &dahdic)) { 01253 if (test) { 01254 /* if we are creating a conference for a unit test, it is not neccesary 01255 * to open a pseudo channel, so, if we fail continue creating 01256 * the conference. */ 01257 ast_test_status_update(test, "Unable to open DAHDI pseudo device\n"); 01258 } else { 01259 ast_log(LOG_WARNING, "Unable to open DAHDI pseudo device\n"); 01260 if (cnf->fd >= 0) 01261 close(cnf->fd); 01262 ao2_ref(cnf->usercontainer, -1); 01263 ast_mutex_destroy(&cnf->playlock); 01264 ast_mutex_destroy(&cnf->listenlock); 01265 ast_mutex_destroy(&cnf->recordthreadlock); 01266 ast_mutex_destroy(&cnf->announcethreadlock); 01267 ast_free(cnf); 01268 cnf = NULL; 01269 goto cnfout; 01270 } 01271 } 01272 01273 cnf->dahdiconf = dahdic.confno; 01274 01275 /* Setup a new channel for playback of audio files */ 01276 cnf->chan = ast_request("DAHDI", AST_FORMAT_SLINEAR, chan, "pseudo", NULL); 01277 if (cnf->chan) { 01278 ast_set_read_format(cnf->chan, AST_FORMAT_SLINEAR); 01279 ast_set_write_format(cnf->chan, AST_FORMAT_SLINEAR); 01280 dahdic.chan = 0; 01281 dahdic.confno = cnf->dahdiconf; 01282 dahdic.confmode = DAHDI_CONF_CONFANN | DAHDI_CONF_CONFANNMON; 01283 if (ioctl(cnf->chan->fds[0], DAHDI_SETCONF, &dahdic)) { 01284 if (test) { 01285 ast_test_status_update(test, "Error setting conference on pseudo channel\n"); 01286 } 01287 ast_log(LOG_WARNING, "Error setting conference\n"); 01288 if (cnf->chan) 01289 ast_hangup(cnf->chan); 01290 else 01291 close(cnf->fd); 01292 ao2_ref(cnf->usercontainer, -1); 01293 ast_mutex_destroy(&cnf->playlock); 01294 ast_mutex_destroy(&cnf->listenlock); 01295 ast_mutex_destroy(&cnf->recordthreadlock); 01296 ast_mutex_destroy(&cnf->announcethreadlock); 01297 ast_free(cnf); 01298 cnf = NULL; 01299 goto cnfout; 01300 } 01301 } 01302 01303 /* Fill the conference struct */ 01304 cnf->start = time(NULL); 01305 cnf->maxusers = 0x7fffffff; 01306 cnf->isdynamic = dynamic ? 1 : 0; 01307 ast_verb(3, "Created MeetMe conference %d for conference '%s'\n", cnf->dahdiconf, cnf->confno); 01308 AST_LIST_INSERT_HEAD(&confs, cnf, list); 01309 01310 /* Reserve conference number in map */ 01311 if ((sscanf(cnf->confno, "%30d", &confno_int) == 1) && (confno_int >= 0 && confno_int < 1024)) 01312 conf_map[confno_int] = 1; 01313 01314 cnfout: 01315 if (cnf) 01316 ast_atomic_fetchadd_int(&cnf->refcount, refcount); 01317 01318 AST_LIST_UNLOCK(&confs); 01319 01320 return cnf; 01321 }
static int can_write | ( | struct ast_channel * | chan, | |
struct ast_flags64 * | confflags | |||
) | [static] |
Definition at line 2261 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().
02262 { 02263 if (!ast_test_flag64(confflags, CONFFLAG_NO_AUDIO_UNTIL_UP)) { 02264 return 1; 02265 } 02266 02267 return (chan->_state == AST_STATE_UP); 02268 }
static int careful_write | ( | int | fd, | |
unsigned char * | data, | |||
int | len, | |||
int | block | |||
) | [static] |
Definition at line 1016 of file app_meetme.c.
References ast_log(), errno, and LOG_WARNING.
Referenced by conf_play(), and conf_run().
01017 { 01018 int res; 01019 int x; 01020 01021 while (len) { 01022 if (block) { 01023 x = DAHDI_IOMUX_WRITE | DAHDI_IOMUX_SIGEVENT; 01024 res = ioctl(fd, DAHDI_IOMUX, &x); 01025 } else 01026 res = 0; 01027 if (res >= 0) 01028 res = write(fd, data, len); 01029 if (res < 1) { 01030 if (errno != EAGAIN) { 01031 ast_log(LOG_WARNING, "Failed to write audio data to conference: %s\n", strerror(errno)); 01032 return -1; 01033 } else 01034 return 0; 01035 } 01036 len -= res; 01037 data += res; 01038 } 01039 01040 return 0; 01041 }
static int channel_admin_exec | ( | struct ast_channel * | chan, | |
const char * | data | |||
) | [static] |
The MeetMeChannelAdmin application MeetMeChannelAdmin(channel, command).
Definition at line 4974 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().
04974 { 04975 char *params; 04976 struct ast_conference *conf = NULL; 04977 struct ast_conf_user *user = NULL; 04978 AST_DECLARE_APP_ARGS(args, 04979 AST_APP_ARG(channel); 04980 AST_APP_ARG(command); 04981 ); 04982 04983 if (ast_strlen_zero(data)) { 04984 ast_log(LOG_WARNING, "MeetMeChannelAdmin requires two arguments!\n"); 04985 return -1; 04986 } 04987 04988 params = ast_strdupa(data); 04989 AST_STANDARD_APP_ARGS(args, params); 04990 04991 if (!args.channel) { 04992 ast_log(LOG_WARNING, "MeetMeChannelAdmin requires a channel name!\n"); 04993 return -1; 04994 } 04995 04996 if (!args.command) { 04997 ast_log(LOG_WARNING, "MeetMeChannelAdmin requires a command!\n"); 04998 return -1; 04999 } 05000 05001 AST_LIST_LOCK(&confs); 05002 AST_LIST_TRAVERSE(&confs, conf, list) { 05003 if ((user = ao2_callback(conf->usercontainer, 0, user_chan_cb, args.channel))) { 05004 break; 05005 } 05006 } 05007 05008 if (!user) { 05009 ast_log(LOG_NOTICE, "Specified user (%s) not found\n", args.channel); 05010 AST_LIST_UNLOCK(&confs); 05011 return 0; 05012 } 05013 05014 /* perform the specified action */ 05015 switch (*args.command) { 05016 case 77: /* M: Mute */ 05017 user->adminflags |= ADMINFLAG_MUTED; 05018 break; 05019 case 109: /* m: Unmute */ 05020 user->adminflags &= ~ADMINFLAG_MUTED; 05021 break; 05022 case 107: /* k: Kick user */ 05023 user->adminflags |= ADMINFLAG_KICKME; 05024 break; 05025 default: /* unknown command */ 05026 ast_log(LOG_WARNING, "Unknown MeetMeChannelAdmin command '%s'\n", args.command); 05027 break; 05028 } 05029 ao2_ref(user, -1); 05030 AST_LIST_UNLOCK(&confs); 05031 05032 return 0; 05033 }
static char* complete_confno | ( | const char * | word, | |
int | state | |||
) | [static] |
Definition at line 1323 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().
01324 { 01325 struct ast_conference *cnf; 01326 char *ret = NULL; 01327 int which = 0; 01328 int len = strlen(word); 01329 01330 AST_LIST_LOCK(&confs); 01331 AST_LIST_TRAVERSE(&confs, cnf, list) { 01332 if (!strncmp(word, cnf->confno, len) && ++which > state) { 01333 /* dup before releasing the lock */ 01334 ret = ast_strdup(cnf->confno); 01335 break; 01336 } 01337 } 01338 AST_LIST_UNLOCK(&confs); 01339 return ret; 01340 }
static char* complete_meetmecmd_list | ( | const char * | line, | |
const char * | word, | |||
int | pos, | |||
int | state | |||
) | [static] |
Definition at line 1412 of file app_meetme.c.
References ast_strdup, ast_strdupa, complete_confno(), ast_conference::confno, len(), and STR_CONCISE.
Referenced by meetme_show_cmd().
01413 { 01414 int len; 01415 01416 if (pos == 2) { 01417 len = strlen(word); 01418 if (!strncasecmp(word, STR_CONCISE, len)) { 01419 if (state == 0) { 01420 return ast_strdup(STR_CONCISE); 01421 } 01422 --state; 01423 } 01424 01425 return complete_confno(word, state); 01426 } 01427 if (pos == 3 && state == 0) { 01428 char *saved = NULL; 01429 char *myline; 01430 char *confno; 01431 01432 /* Extract the confno from the command line. */ 01433 myline = ast_strdupa(line); 01434 strtok_r(myline, " ", &saved); 01435 strtok_r(NULL, " ", &saved); 01436 confno = strtok_r(NULL, " ", &saved); 01437 01438 if (!strcasecmp(confno, STR_CONCISE)) { 01439 /* There is nothing valid in this position now. */ 01440 return NULL; 01441 } 01442 01443 len = strlen(word); 01444 if (!strncasecmp(word, STR_CONCISE, len)) { 01445 return ast_strdup(STR_CONCISE); 01446 } 01447 } 01448 return NULL; 01449 }
static char* complete_meetmecmd_lock | ( | const char * | word, | |
int | pos, | |||
int | state | |||
) | [static] |
Definition at line 1404 of file app_meetme.c.
References complete_confno().
Referenced by meetme_lock_cmd().
01405 { 01406 if (pos == 2) { 01407 return complete_confno(word, state); 01408 } 01409 return NULL; 01410 }
static char* complete_meetmecmd_mute_kick | ( | const char * | line, | |
const char * | word, | |||
int | pos, | |||
int | state | |||
) | [static] |
Definition at line 1364 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().
01365 { 01366 if (pos == 2) { 01367 return complete_confno(word, state); 01368 } 01369 if (pos == 3) { 01370 int len = strlen(word); 01371 char *ret = NULL; 01372 char *saved = NULL; 01373 char *myline; 01374 char *confno; 01375 struct ast_conference *cnf; 01376 01377 if (!strncasecmp(word, "all", len)) { 01378 if (state == 0) { 01379 return ast_strdup("all"); 01380 } 01381 --state; 01382 } 01383 01384 /* Extract the confno from the command line. */ 01385 myline = ast_strdupa(line); 01386 strtok_r(myline, " ", &saved); 01387 strtok_r(NULL, " ", &saved); 01388 confno = strtok_r(NULL, " ", &saved); 01389 01390 AST_LIST_LOCK(&confs); 01391 AST_LIST_TRAVERSE(&confs, cnf, list) { 01392 if (!strcmp(confno, cnf->confno)) { 01393 ret = complete_userno(cnf, word, state); 01394 break; 01395 } 01396 } 01397 AST_LIST_UNLOCK(&confs); 01398 01399 return ret; 01400 } 01401 return NULL; 01402 }
static char* complete_userno | ( | struct ast_conference * | cnf, | |
const char * | word, | |||
int | state | |||
) | [static] |
Definition at line 1342 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().
01343 { 01344 char usrno[50]; 01345 struct ao2_iterator iter; 01346 struct ast_conf_user *usr; 01347 char *ret = NULL; 01348 int which = 0; 01349 int len = strlen(word); 01350 01351 iter = ao2_iterator_init(cnf->usercontainer, 0); 01352 for (; (usr = ao2_iterator_next(&iter)); ao2_ref(usr, -1)) { 01353 snprintf(usrno, sizeof(usrno), "%d", usr->user_no); 01354 if (!strncmp(word, usrno, len) && ++which > state) { 01355 ao2_ref(usr, -1); 01356 ret = ast_strdup(usrno); 01357 break; 01358 } 01359 } 01360 ao2_iterator_destroy(&iter); 01361 return ret; 01362 }
static int conf_exec | ( | struct ast_channel * | chan, | |
const char * | data | |||
) | [static] |
The meetme() application.
Definition at line 4419 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().
04420 { 04421 int res = -1; 04422 char confno[MAX_CONFNUM] = ""; 04423 int allowretry = 0; 04424 int retrycnt = 0; 04425 struct ast_conference *cnf = NULL; 04426 struct ast_flags64 confflags = {0}; 04427 struct ast_flags config_flags = { 0 }; 04428 int dynamic = 0; 04429 int empty = 0, empty_no_pin = 0; 04430 int always_prompt = 0; 04431 const char *notdata; 04432 char *info, the_pin[MAX_PIN] = ""; 04433 AST_DECLARE_APP_ARGS(args, 04434 AST_APP_ARG(confno); 04435 AST_APP_ARG(options); 04436 AST_APP_ARG(pin); 04437 ); 04438 char *optargs[OPT_ARG_ARRAY_SIZE] = { NULL, }; 04439 04440 if (ast_strlen_zero(data)) { 04441 allowretry = 1; 04442 notdata = ""; 04443 } else { 04444 notdata = data; 04445 } 04446 04447 if (chan->_state != AST_STATE_UP) 04448 ast_answer(chan); 04449 04450 info = ast_strdupa(notdata); 04451 04452 AST_STANDARD_APP_ARGS(args, info); 04453 04454 if (args.confno) { 04455 ast_copy_string(confno, args.confno, sizeof(confno)); 04456 if (ast_strlen_zero(confno)) { 04457 allowretry = 1; 04458 } 04459 } 04460 04461 if (args.pin) 04462 ast_copy_string(the_pin, args.pin, sizeof(the_pin)); 04463 04464 if (args.options) { 04465 ast_app_parse_options64(meetme_opts, &confflags, optargs, args.options); 04466 dynamic = ast_test_flag64(&confflags, CONFFLAG_DYNAMIC | CONFFLAG_DYNAMICPIN); 04467 if (ast_test_flag64(&confflags, CONFFLAG_DYNAMICPIN) && ast_strlen_zero(args.pin)) 04468 strcpy(the_pin, "q"); 04469 04470 empty = ast_test_flag64(&confflags, CONFFLAG_EMPTY | CONFFLAG_EMPTYNOPIN); 04471 empty_no_pin = ast_test_flag64(&confflags, CONFFLAG_EMPTYNOPIN); 04472 always_prompt = ast_test_flag64(&confflags, CONFFLAG_ALWAYSPROMPT | CONFFLAG_DYNAMICPIN); 04473 } 04474 04475 do { 04476 if (retrycnt > 3) 04477 allowretry = 0; 04478 if (empty) { 04479 int i; 04480 struct ast_config *cfg; 04481 struct ast_variable *var; 04482 int confno_int; 04483 04484 /* We only need to load the config file for static and empty_no_pin (otherwise we don't care) */ 04485 if ((empty_no_pin) || (!dynamic)) { 04486 cfg = ast_config_load(CONFIG_FILE_NAME, config_flags); 04487 if (cfg && cfg != CONFIG_STATUS_FILEINVALID) { 04488 var = ast_variable_browse(cfg, "rooms"); 04489 while (var) { 04490 char parse[MAX_SETTINGS], *stringp = parse, *confno_tmp; 04491 if (!strcasecmp(var->name, "conf")) { 04492 int found = 0; 04493 ast_copy_string(parse, var->value, sizeof(parse)); 04494 confno_tmp = strsep(&stringp, "|,"); 04495 if (!dynamic) { 04496 /* For static: run through the list and see if this conference is empty */ 04497 AST_LIST_LOCK(&confs); 04498 AST_LIST_TRAVERSE(&confs, cnf, list) { 04499 if (!strcmp(confno_tmp, cnf->confno)) { 04500 /* The conference exists, therefore it's not empty */ 04501 found = 1; 04502 break; 04503 } 04504 } 04505 AST_LIST_UNLOCK(&confs); 04506 cnf = NULL; 04507 if (!found) { 04508 /* At this point, we have a confno_tmp (static conference) that is empty */ 04509 if ((empty_no_pin && ast_strlen_zero(stringp)) || (!empty_no_pin)) { 04510 /* Case 1: empty_no_pin and pin is nonexistent (NULL) 04511 * Case 2: empty_no_pin and pin is blank (but not NULL) 04512 * Case 3: not empty_no_pin 04513 */ 04514 ast_copy_string(confno, confno_tmp, sizeof(confno)); 04515 break; 04516 } 04517 } 04518 } 04519 } 04520 var = var->next; 04521 } 04522 ast_config_destroy(cfg); 04523 } 04524 04525 if (ast_strlen_zero(confno) && (cfg = ast_load_realtime_multientry("meetme", "confno LIKE", "%", SENTINEL))) { 04526 const char *catg; 04527 for (catg = ast_category_browse(cfg, NULL); catg; catg = ast_category_browse(cfg, catg)) { 04528 const char *confno_tmp = ast_variable_retrieve(cfg, catg, "confno"); 04529 const char *pin_tmp = ast_variable_retrieve(cfg, catg, "pin"); 04530 if (ast_strlen_zero(confno_tmp)) { 04531 continue; 04532 } 04533 if (!dynamic) { 04534 int found = 0; 04535 /* For static: run through the list and see if this conference is empty */ 04536 AST_LIST_LOCK(&confs); 04537 AST_LIST_TRAVERSE(&confs, cnf, list) { 04538 if (!strcmp(confno_tmp, cnf->confno)) { 04539 /* The conference exists, therefore it's not empty */ 04540 found = 1; 04541 break; 04542 } 04543 } 04544 AST_LIST_UNLOCK(&confs); 04545 if (!found) { 04546 /* At this point, we have a confno_tmp (realtime conference) that is empty */ 04547 if ((empty_no_pin && ast_strlen_zero(pin_tmp)) || (!empty_no_pin)) { 04548 /* Case 1: empty_no_pin and pin is nonexistent (NULL) 04549 * Case 2: empty_no_pin and pin is blank (but not NULL) 04550 * Case 3: not empty_no_pin 04551 */ 04552 ast_copy_string(confno, confno_tmp, sizeof(confno)); 04553 break; 04554 } 04555 } 04556 } 04557 } 04558 ast_config_destroy(cfg); 04559 } 04560 } 04561 04562 /* Select first conference number not in use */ 04563 if (ast_strlen_zero(confno) && dynamic) { 04564 AST_LIST_LOCK(&confs); 04565 for (i = 0; i < ARRAY_LEN(conf_map); i++) { 04566 if (!conf_map[i]) { 04567 snprintf(confno, sizeof(confno), "%d", i); 04568 conf_map[i] = 1; 04569 break; 04570 } 04571 } 04572 AST_LIST_UNLOCK(&confs); 04573 } 04574 04575 /* Not found? */ 04576 if (ast_strlen_zero(confno)) { 04577 ast_test_suite_event_notify("PLAYBACK", "Message: conf-noempty"); 04578 res = ast_streamfile(chan, "conf-noempty", chan->language); 04579 if (!res) 04580 ast_waitstream(chan, ""); 04581 } else { 04582 if (sscanf(confno, "%30d", &confno_int) == 1) { 04583 if (!ast_test_flag64(&confflags, CONFFLAG_QUIET)) { 04584 res = ast_streamfile(chan, "conf-enteringno", chan->language); 04585 if (!res) { 04586 ast_waitstream(chan, ""); 04587 res = ast_say_digits(chan, confno_int, "", chan->language); 04588 } 04589 } 04590 } else { 04591 ast_log(LOG_ERROR, "Could not scan confno '%s'\n", confno); 04592 } 04593 } 04594 } 04595 04596 while (allowretry && (ast_strlen_zero(confno)) && (++retrycnt < 4)) { 04597 /* Prompt user for conference number */ 04598 res = ast_app_getdata(chan, "conf-getconfno", confno, sizeof(confno) - 1, 0); 04599 if (res < 0) { 04600 /* Don't try to validate when we catch an error */ 04601 confno[0] = '\0'; 04602 allowretry = 0; 04603 break; 04604 } 04605 } 04606 if (!ast_strlen_zero(confno)) { 04607 /* Check the validity of the conference */ 04608 cnf = find_conf(chan, confno, 1, dynamic, the_pin, 04609 sizeof(the_pin), 1, &confflags); 04610 if (!cnf) { 04611 int too_early = 0; 04612 04613 cnf = find_conf_realtime(chan, confno, 1, dynamic, 04614 the_pin, sizeof(the_pin), 1, &confflags, &too_early, optargs); 04615 if (rt_schedule && too_early) 04616 allowretry = 0; 04617 } 04618 04619 if (!cnf) { 04620 if (allowretry) { 04621 confno[0] = '\0'; 04622 res = ast_streamfile(chan, "conf-invalid", chan->language); 04623 if (!res) 04624 ast_waitstream(chan, ""); 04625 res = -1; 04626 } 04627 } else { 04628 /* Conference requires a pin for specified access level */ 04629 int req_pin = !ast_strlen_zero(cnf->pin) || 04630 (!ast_strlen_zero(cnf->pinadmin) && 04631 ast_test_flag64(&confflags, CONFFLAG_ADMIN)); 04632 /* The following logic was derived from a 04633 * 4 variable truth table and defines which 04634 * circumstances are not exempt from pin 04635 * checking. 04636 * If this needs to be modified, write the 04637 * truth table back out from the boolean 04638 * expression AB+A'D+C', change the erroneous 04639 * result, and rederive the expression. 04640 * Variables: 04641 * A: pin provided? 04642 * B: always prompt? 04643 * C: dynamic? 04644 * D: has users? */ 04645 int not_exempt = !cnf->isdynamic; 04646 not_exempt = not_exempt || (!ast_strlen_zero(args.pin) && ast_test_flag64(&confflags, CONFFLAG_ALWAYSPROMPT)); 04647 not_exempt = not_exempt || (ast_strlen_zero(args.pin) && cnf->users); 04648 if (req_pin && not_exempt) { 04649 char pin[MAX_PIN] = ""; 04650 int j; 04651 04652 /* Allow the pin to be retried up to 3 times */ 04653 for (j = 0; j < 3; j++) { 04654 if (*the_pin && (always_prompt == 0)) { 04655 ast_copy_string(pin, the_pin, sizeof(pin)); 04656 res = 0; 04657 } else { 04658 /* Prompt user for pin if pin is required */ 04659 ast_test_suite_event_notify("PLAYBACK", "Message: conf-getpin\r\n" 04660 "Channel: %s", 04661 chan->name); 04662 res = ast_app_getdata(chan, "conf-getpin", pin + strlen(pin), sizeof(pin) - 1 - strlen(pin), 0); 04663 } 04664 if (res >= 0) { 04665 if ((!strcasecmp(pin, cnf->pin) && 04666 (ast_strlen_zero(cnf->pinadmin) || 04667 !ast_test_flag64(&confflags, CONFFLAG_ADMIN))) || 04668 (!ast_strlen_zero(cnf->pinadmin) && 04669 !strcasecmp(pin, cnf->pinadmin))) { 04670 /* Pin correct */ 04671 allowretry = 0; 04672 if (!ast_strlen_zero(cnf->pinadmin) && !strcasecmp(pin, cnf->pinadmin)) { 04673 if (!ast_strlen_zero(cnf->adminopts)) { 04674 char *opts = ast_strdupa(cnf->adminopts); 04675 ast_app_parse_options64(meetme_opts, &confflags, optargs, opts); 04676 } 04677 } else { 04678 if (!ast_strlen_zero(cnf->useropts)) { 04679 char *opts = ast_strdupa(cnf->useropts); 04680 ast_app_parse_options64(meetme_opts, &confflags, optargs, opts); 04681 } 04682 } 04683 /* Run the conference */ 04684 ast_verb(4, "Starting recording of MeetMe Conference %s into file %s.%s.\n", cnf->confno, cnf->recordingfilename, cnf->recordingformat); 04685 res = conf_run(chan, cnf, &confflags, optargs); 04686 break; 04687 } else { 04688 /* Pin invalid */ 04689 if (!ast_streamfile(chan, "conf-invalidpin", chan->language)) { 04690 res = ast_waitstream(chan, AST_DIGIT_ANY); 04691 ast_stopstream(chan); 04692 } else { 04693 ast_log(LOG_WARNING, "Couldn't play invalid pin msg!\n"); 04694 break; 04695 } 04696 if (res < 0) 04697 break; 04698 pin[0] = res; 04699 pin[1] = '\0'; 04700 res = -1; 04701 if (allowretry) 04702 confno[0] = '\0'; 04703 } 04704 } else { 04705 /* failed when getting the pin */ 04706 res = -1; 04707 allowretry = 0; 04708 /* see if we need to get rid of the conference */ 04709 break; 04710 } 04711 04712 /* Don't retry pin with a static pin */ 04713 if (*the_pin && (always_prompt == 0)) { 04714 break; 04715 } 04716 } 04717 } else { 04718 /* No pin required */ 04719 allowretry = 0; 04720 04721 /* For RealTime conferences without a pin 04722 * should still support loading options 04723 */ 04724 if (!ast_strlen_zero(cnf->useropts)) { 04725 char *opts = ast_strdupa(cnf->useropts); 04726 ast_app_parse_options64(meetme_opts, &confflags, optargs, opts); 04727 } 04728 04729 /* Run the conference */ 04730 res = conf_run(chan, cnf, &confflags, optargs); 04731 } 04732 dispose_conf(cnf); 04733 cnf = NULL; 04734 } 04735 } 04736 } while (allowretry); 04737 04738 if (cnf) 04739 dispose_conf(cnf); 04740 04741 return res; 04742 }
static void conf_flush | ( | int | fd, | |
struct ast_channel * | chan | |||
) | [static] |
Definition at line 1894 of file app_meetme.c.
References ast_frfree, ast_log(), ast_read(), ast_waitfor(), f, and LOG_WARNING.
Referenced by conf_run().
01895 { 01896 int x; 01897 01898 /* read any frames that may be waiting on the channel 01899 and throw them away 01900 */ 01901 if (chan) { 01902 struct ast_frame *f; 01903 01904 /* when no frames are available, this will wait 01905 for 1 millisecond maximum 01906 */ 01907 while (ast_waitfor(chan, 1) > 0) { 01908 f = ast_read(chan); 01909 if (f) 01910 ast_frfree(f); 01911 else /* channel was hung up or something else happened */ 01912 break; 01913 } 01914 } 01915 01916 /* flush any data sitting in the pseudo channel */ 01917 x = DAHDI_FLUSH_ALL; 01918 if (ioctl(fd, DAHDI_FLUSH, &x)) 01919 ast_log(LOG_WARNING, "Error flushing channel\n"); 01920 01921 }
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 1926 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().
01927 { 01928 int x; 01929 struct announce_listitem *item; 01930 01931 AST_LIST_REMOVE(&confs, conf, list); 01932 manager_event(EVENT_FLAG_CALL, "MeetmeEnd", "Meetme: %s\r\n", conf->confno); 01933 01934 if (conf->recording == MEETME_RECORD_ACTIVE) { 01935 conf->recording = MEETME_RECORD_TERMINATE; 01936 AST_LIST_UNLOCK(&confs); 01937 while (1) { 01938 usleep(1); 01939 AST_LIST_LOCK(&confs); 01940 if (conf->recording == MEETME_RECORD_OFF) 01941 break; 01942 AST_LIST_UNLOCK(&confs); 01943 } 01944 } 01945 01946 for (x = 0; x < AST_FRAME_BITS; x++) { 01947 if (conf->transframe[x]) 01948 ast_frfree(conf->transframe[x]); 01949 if (conf->transpath[x]) 01950 ast_translator_free_path(conf->transpath[x]); 01951 } 01952 if (conf->announcethread != AST_PTHREADT_NULL) { 01953 ast_mutex_lock(&conf->announcelistlock); 01954 conf->announcethread_stop = 1; 01955 ast_softhangup(conf->chan, AST_SOFTHANGUP_EXPLICIT); 01956 ast_cond_signal(&conf->announcelist_addition); 01957 ast_mutex_unlock(&conf->announcelistlock); 01958 pthread_join(conf->announcethread, NULL); 01959 01960 while ((item = AST_LIST_REMOVE_HEAD(&conf->announcelist, entry))) { 01961 ast_filedelete(item->namerecloc, NULL); 01962 ao2_ref(item, -1); 01963 } 01964 ast_mutex_destroy(&conf->announcelistlock); 01965 } 01966 01967 if (conf->origframe) 01968 ast_frfree(conf->origframe); 01969 if (conf->lchan) 01970 ast_hangup(conf->lchan); 01971 if (conf->chan) 01972 ast_hangup(conf->chan); 01973 if (conf->fd >= 0) 01974 close(conf->fd); 01975 if (conf->recordingfilename) { 01976 ast_free(conf->recordingfilename); 01977 } 01978 if (conf->usercontainer) { 01979 ao2_ref(conf->usercontainer, -1); 01980 } 01981 if (conf->recordingformat) { 01982 ast_free(conf->recordingformat); 01983 } 01984 ast_mutex_destroy(&conf->playlock); 01985 ast_mutex_destroy(&conf->listenlock); 01986 ast_mutex_destroy(&conf->recordthreadlock); 01987 ast_mutex_destroy(&conf->announcethreadlock); 01988 ast_free(conf); 01989 01990 return 0; 01991 }
static void conf_play | ( | struct ast_channel * | chan, | |
struct ast_conference * | conf, | |||
enum entrance_sound | sound | |||
) | [static] |
Definition at line 1134 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().
01135 { 01136 unsigned char *data; 01137 int len; 01138 int res = -1; 01139 01140 ast_test_suite_event_notify("CONFPLAY", "Channel: %s\r\n" 01141 "Conference: %s\r\n" 01142 "Marked: %d", 01143 chan->name, 01144 conf->confno, 01145 conf->markedusers); 01146 01147 if (!ast_check_hangup(chan)) 01148 res = ast_autoservice_start(chan); 01149 01150 AST_LIST_LOCK(&confs); 01151 01152 switch(sound) { 01153 case ENTER: 01154 data = enter; 01155 len = sizeof(enter); 01156 break; 01157 case LEAVE: 01158 data = leave; 01159 len = sizeof(leave); 01160 break; 01161 default: 01162 data = NULL; 01163 len = 0; 01164 } 01165 if (data) { 01166 careful_write(conf->fd, data, len, 1); 01167 } 01168 01169 AST_LIST_UNLOCK(&confs); 01170 01171 if (!res) 01172 ast_autoservice_stop(chan); 01173 }
static void conf_queue_dtmf | ( | const struct ast_conference * | conf, | |
const struct ast_conf_user * | sender, | |||
struct ast_frame * | f | |||
) | [static] |
Definition at line 1993 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().
01995 { 01996 struct ast_conf_user *user; 01997 struct ao2_iterator user_iter; 01998 01999 user_iter = ao2_iterator_init(conf->usercontainer, 0); 02000 while ((user = ao2_iterator_next(&user_iter))) { 02001 if (user == sender) { 02002 ao2_ref(user, -1); 02003 continue; 02004 } 02005 if (ast_write(user->chan, f) < 0) 02006 ast_log(LOG_WARNING, "Error writing frame to channel %s\n", user->chan->name); 02007 ao2_ref(user, -1); 02008 } 02009 ao2_iterator_destroy(&user_iter); 02010 }
static int conf_run | ( | struct ast_channel * | chan, | |
struct ast_conference * | conf, | |||
struct ast_flags64 * | confflags, | |||
char * | optargs[] | |||
) | [static] |
Definition at line 2759 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().
02760 { 02761 struct ast_conf_user *user = NULL; 02762 int fd; 02763 struct dahdi_confinfo dahdic, dahdic_empty; 02764 struct ast_frame *f; 02765 struct ast_channel *c; 02766 struct ast_frame fr; 02767 int outfd; 02768 int ms; 02769 int nfds; 02770 int res; 02771 int retrydahdi; 02772 int origfd; 02773 int musiconhold = 0, mohtempstopped = 0; 02774 int firstpass = 0; 02775 int lastmarked = 0; 02776 int currentmarked = 0; 02777 int ret = -1; 02778 int x; 02779 enum menu_modes menu_mode = MENU_DISABLED; 02780 int talkreq_manager = 0; 02781 int using_pseudo = 0; 02782 int duration = 20; 02783 int sent_event = 0; 02784 int checked = 0; 02785 int announcement_played = 0; 02786 struct timeval now; 02787 struct ast_dsp *dsp = NULL; 02788 struct ast_app *agi_app; 02789 char *agifile, *mod_speex; 02790 const char *agifiledefault = "conf-background.agi", *tmpvar; 02791 char meetmesecs[30] = ""; 02792 char exitcontext[AST_MAX_CONTEXT] = ""; 02793 char recordingtmp[AST_MAX_EXTENSION] = ""; 02794 char members[10] = ""; 02795 int dtmf = 0, opt_waitmarked_timeout = 0; 02796 time_t timeout = 0; 02797 struct dahdi_bufferinfo bi; 02798 char __buf[CONF_SIZE + AST_FRIENDLY_OFFSET]; 02799 char *buf = __buf + AST_FRIENDLY_OFFSET; 02800 char *exitkeys = NULL; 02801 unsigned int calldurationlimit = 0; 02802 long timelimit = 0; 02803 long play_warning = 0; 02804 long warning_freq = 0; 02805 const char *warning_sound = NULL; 02806 const char *end_sound = NULL; 02807 char *parse; 02808 long time_left_ms = 0; 02809 struct timeval nexteventts = { 0, }; 02810 int to; 02811 int setusercount = 0; 02812 int confsilence = 0, totalsilence = 0; 02813 02814 if (!(user = ao2_alloc(sizeof(*user), NULL))) { 02815 return ret; 02816 } 02817 02818 /* Possible timeout waiting for marked user */ 02819 if (ast_test_flag64(confflags, CONFFLAG_WAITMARKED) && 02820 !ast_strlen_zero(optargs[OPT_ARG_WAITMARKED]) && 02821 (sscanf(optargs[OPT_ARG_WAITMARKED], "%30d", &opt_waitmarked_timeout) == 1) && 02822 (opt_waitmarked_timeout > 0)) { 02823 timeout = time(NULL) + opt_waitmarked_timeout; 02824 } 02825 02826 if (ast_test_flag64(confflags, CONFFLAG_DURATION_STOP) && !ast_strlen_zero(optargs[OPT_ARG_DURATION_STOP])) { 02827 calldurationlimit = atoi(optargs[OPT_ARG_DURATION_STOP]); 02828 ast_verb(3, "Setting call duration limit to %u seconds.\n", calldurationlimit); 02829 } 02830 02831 if (ast_test_flag64(confflags, CONFFLAG_DURATION_LIMIT) && !ast_strlen_zero(optargs[OPT_ARG_DURATION_LIMIT])) { 02832 char *limit_str, *warning_str, *warnfreq_str; 02833 const char *var; 02834 02835 parse = optargs[OPT_ARG_DURATION_LIMIT]; 02836 limit_str = strsep(&parse, ":"); 02837 warning_str = strsep(&parse, ":"); 02838 warnfreq_str = parse; 02839 02840 timelimit = atol(limit_str); 02841 if (warning_str) 02842 play_warning = atol(warning_str); 02843 if (warnfreq_str) 02844 warning_freq = atol(warnfreq_str); 02845 02846 if (!timelimit) { 02847 timelimit = play_warning = warning_freq = 0; 02848 warning_sound = NULL; 02849 } else if (play_warning > timelimit) { 02850 if (!warning_freq) { 02851 play_warning = 0; 02852 } else { 02853 while (play_warning > timelimit) 02854 play_warning -= warning_freq; 02855 if (play_warning < 1) 02856 play_warning = warning_freq = 0; 02857 } 02858 } 02859 02860 ast_verb(3, "Setting conference duration limit to: %ldms.\n", timelimit); 02861 if (play_warning) { 02862 ast_verb(3, "Setting warning time to %ldms from the conference duration limit.\n", play_warning); 02863 } 02864 if (warning_freq) { 02865 ast_verb(3, "Setting warning frequency to %ldms.\n", warning_freq); 02866 } 02867 02868 ast_channel_lock(chan); 02869 if ((var = pbx_builtin_getvar_helper(chan, "CONF_LIMIT_WARNING_FILE"))) { 02870 var = ast_strdupa(var); 02871 } 02872 ast_channel_unlock(chan); 02873 02874 warning_sound = var ? var : "timeleft"; 02875 02876 ast_channel_lock(chan); 02877 if ((var = pbx_builtin_getvar_helper(chan, "CONF_LIMIT_TIMEOUT_FILE"))) { 02878 var = ast_strdupa(var); 02879 } 02880 ast_channel_unlock(chan); 02881 02882 end_sound = var ? var : NULL; 02883 02884 /* undo effect of S(x) in case they are both used */ 02885 calldurationlimit = 0; 02886 /* more efficient do it like S(x) does since no advanced opts */ 02887 if (!play_warning && !end_sound && timelimit) { 02888 calldurationlimit = timelimit / 1000; 02889 timelimit = play_warning = warning_freq = 0; 02890 } else { 02891 ast_debug(2, "Limit Data for this call:\n"); 02892 ast_debug(2, "- timelimit = %ld\n", timelimit); 02893 ast_debug(2, "- play_warning = %ld\n", play_warning); 02894 ast_debug(2, "- warning_freq = %ld\n", warning_freq); 02895 ast_debug(2, "- warning_sound = %s\n", warning_sound ? warning_sound : "UNDEF"); 02896 ast_debug(2, "- end_sound = %s\n", end_sound ? end_sound : "UNDEF"); 02897 } 02898 } 02899 02900 /* Get exit keys */ 02901 if (ast_test_flag64(confflags, CONFFLAG_KEYEXIT)) { 02902 if (!ast_strlen_zero(optargs[OPT_ARG_EXITKEYS])) 02903 exitkeys = ast_strdupa(optargs[OPT_ARG_EXITKEYS]); 02904 else 02905 exitkeys = ast_strdupa("#"); /* Default */ 02906 } 02907 02908 if (ast_test_flag64(confflags, CONFFLAG_RECORDCONF)) { 02909 if (!conf->recordingfilename) { 02910 const char *var; 02911 ast_channel_lock(chan); 02912 if ((var = pbx_builtin_getvar_helper(chan, "MEETME_RECORDINGFILE"))) { 02913 conf->recordingfilename = ast_strdup(var); 02914 } 02915 if ((var = pbx_builtin_getvar_helper(chan, "MEETME_RECORDINGFORMAT"))) { 02916 conf->recordingformat = ast_strdup(var); 02917 } 02918 ast_channel_unlock(chan); 02919 if (!conf->recordingfilename) { 02920 snprintf(recordingtmp, sizeof(recordingtmp), "meetme-conf-rec-%s-%s", conf->confno, chan->uniqueid); 02921 conf->recordingfilename = ast_strdup(recordingtmp); 02922 } 02923 if (!conf->recordingformat) { 02924 conf->recordingformat = ast_strdup("wav"); 02925 } 02926 ast_verb(4, "Starting recording of MeetMe Conference %s into file %s.%s.\n", 02927 conf->confno, conf->recordingfilename, conf->recordingformat); 02928 } 02929 } 02930 02931 ast_mutex_lock(&conf->recordthreadlock); 02932 if ((conf->recordthread == AST_PTHREADT_NULL) && ast_test_flag64(confflags, CONFFLAG_RECORDCONF) && 02933 ((conf->lchan = ast_request("DAHDI", AST_FORMAT_SLINEAR, chan, "pseudo", NULL)))) { 02934 ast_set_read_format(conf->lchan, AST_FORMAT_SLINEAR); 02935 ast_set_write_format(conf->lchan, AST_FORMAT_SLINEAR); 02936 dahdic.chan = 0; 02937 dahdic.confno = conf->dahdiconf; 02938 dahdic.confmode = DAHDI_CONF_CONFANN | DAHDI_CONF_CONFANNMON; 02939 if (ioctl(conf->lchan->fds[0], DAHDI_SETCONF, &dahdic)) { 02940 ast_log(LOG_WARNING, "Error starting listen channel\n"); 02941 ast_hangup(conf->lchan); 02942 conf->lchan = NULL; 02943 } else { 02944 ast_pthread_create_detached_background(&conf->recordthread, NULL, recordthread, conf); 02945 } 02946 } 02947 ast_mutex_unlock(&conf->recordthreadlock); 02948 02949 ast_mutex_lock(&conf->announcethreadlock); 02950 if ((conf->announcethread == AST_PTHREADT_NULL) && !ast_test_flag64(confflags, CONFFLAG_QUIET) && 02951 (ast_test_flag64(confflags, CONFFLAG_INTROUSER) || ast_test_flag64(confflags, CONFFLAG_INTROUSERNOREVIEW))) { 02952 ast_mutex_init(&conf->announcelistlock); 02953 AST_LIST_HEAD_INIT_NOLOCK(&conf->announcelist); 02954 ast_pthread_create_background(&conf->announcethread, NULL, announce_thread, conf); 02955 } 02956 ast_mutex_unlock(&conf->announcethreadlock); 02957 02958 time(&user->jointime); 02959 02960 user->timelimit = timelimit; 02961 user->play_warning = play_warning; 02962 user->warning_freq = warning_freq; 02963 user->warning_sound = warning_sound; 02964 user->end_sound = end_sound; 02965 02966 if (calldurationlimit > 0) { 02967 time(&user->kicktime); 02968 user->kicktime = user->kicktime + calldurationlimit; 02969 } 02970 02971 if (ast_tvzero(user->start_time)) 02972 user->start_time = ast_tvnow(); 02973 time_left_ms = user->timelimit; 02974 02975 if (user->timelimit) { 02976 nexteventts = ast_tvadd(user->start_time, ast_samp2tv(user->timelimit, 1000)); 02977 nexteventts = ast_tvsub(nexteventts, ast_samp2tv(user->play_warning, 1000)); 02978 } 02979 02980 if (conf->locked && (!ast_test_flag64(confflags, CONFFLAG_ADMIN))) { 02981 /* Sorry, but this conference is locked! */ 02982 if (!ast_streamfile(chan, "conf-locked", chan->language)) 02983 ast_waitstream(chan, ""); 02984 goto outrun; 02985 } 02986 02987 ast_mutex_lock(&conf->playlock); 02988 02989 if (rt_schedule && conf->maxusers) { 02990 if (conf->users >= conf->maxusers) { 02991 /* Sorry, but this confernce has reached the participant limit! */ 02992 ast_mutex_unlock(&conf->playlock); 02993 if (!ast_streamfile(chan, "conf-full", chan->language)) 02994 ast_waitstream(chan, ""); 02995 goto outrun; 02996 } 02997 } 02998 02999 ao2_lock(conf->usercontainer); 03000 ao2_callback(conf->usercontainer, OBJ_NODATA, user_max_cmp, &user->user_no); 03001 user->user_no++; 03002 ao2_link(conf->usercontainer, user); 03003 ao2_unlock(conf->usercontainer); 03004 03005 user->chan = chan; 03006 user->userflags = *confflags; 03007 user->adminflags = ast_test_flag64(confflags, CONFFLAG_STARTMUTED) ? ADMINFLAG_SELFMUTED : 0; 03008 user->adminflags |= (conf->gmuted) ? ADMINFLAG_MUTED : 0; 03009 user->talking = -1; 03010 03011 ast_mutex_unlock(&conf->playlock); 03012 03013 if (!ast_test_flag64(confflags, CONFFLAG_QUIET) && (ast_test_flag64(confflags, CONFFLAG_INTROUSER) || 03014 ast_test_flag64(confflags, CONFFLAG_INTROUSERNOREVIEW))) { 03015 char destdir[PATH_MAX]; 03016 03017 snprintf(destdir, sizeof(destdir), "%s/meetme", ast_config_AST_SPOOL_DIR); 03018 03019 if (ast_mkdir(destdir, 0777) != 0) { 03020 ast_log(LOG_WARNING, "mkdir '%s' failed: %s\n", destdir, strerror(errno)); 03021 goto outrun; 03022 } 03023 03024 snprintf(user->namerecloc, sizeof(user->namerecloc), 03025 "%s/meetme-username-%s-%d", destdir, 03026 conf->confno, user->user_no); 03027 if (ast_test_flag64(confflags, CONFFLAG_INTROUSERNOREVIEW)) 03028 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); 03029 else 03030 res = ast_record_review(chan, "vm-rec-name", user->namerecloc, 10, "sln", &duration, NULL); 03031 if (res == -1) 03032 goto outrun; 03033 } 03034 03035 ast_mutex_lock(&conf->playlock); 03036 03037 if (ast_test_flag64(confflags, CONFFLAG_MARKEDUSER)) 03038 conf->markedusers++; 03039 conf->users++; 03040 if (rt_log_members) { 03041 /* Update table */ 03042 snprintf(members, sizeof(members), "%d", conf->users); 03043 ast_realtime_require_field("meetme", 03044 "confno", strlen(conf->confno) > 7 ? RQ_UINTEGER4 : strlen(conf->confno) > 4 ? RQ_UINTEGER3 : RQ_UINTEGER2, strlen(conf->confno), 03045 "members", RQ_UINTEGER1, strlen(members), 03046 NULL); 03047 ast_update_realtime("meetme", "confno", conf->confno, "members", members, NULL); 03048 } 03049 setusercount = 1; 03050 03051 /* This device changed state now - if this is the first user */ 03052 if (conf->users == 1) 03053 ast_devstate_changed(AST_DEVICE_INUSE, (conf->isdynamic ? AST_DEVSTATE_NOT_CACHABLE : AST_DEVSTATE_CACHABLE), "meetme:%s", conf->confno); 03054 03055 ast_mutex_unlock(&conf->playlock); 03056 03057 /* return the unique ID of the conference */ 03058 pbx_builtin_setvar_helper(chan, "MEETMEUNIQUEID", conf->uniqueid); 03059 03060 if (ast_test_flag64(confflags, CONFFLAG_EXIT_CONTEXT)) { 03061 ast_channel_lock(chan); 03062 if ((tmpvar = pbx_builtin_getvar_helper(chan, "MEETME_EXIT_CONTEXT"))) { 03063 ast_copy_string(exitcontext, tmpvar, sizeof(exitcontext)); 03064 } else if (!ast_strlen_zero(chan->macrocontext)) { 03065 ast_copy_string(exitcontext, chan->macrocontext, sizeof(exitcontext)); 03066 } else { 03067 ast_copy_string(exitcontext, chan->context, sizeof(exitcontext)); 03068 } 03069 ast_channel_unlock(chan); 03070 } 03071 03072 /* Play an arbitrary intro message */ 03073 if (ast_test_flag64(confflags, CONFFLAG_INTROMSG) && 03074 !ast_strlen_zero(optargs[OPT_ARG_INTROMSG])) { 03075 if (!ast_streamfile(chan, optargs[OPT_ARG_INTROMSG], chan->language)) { 03076 ast_waitstream(chan, ""); 03077 } 03078 } 03079 03080 if (!ast_test_flag64(confflags, (CONFFLAG_QUIET | CONFFLAG_NOONLYPERSON))) { 03081 if (conf->users == 1 && !ast_test_flag64(confflags, CONFFLAG_WAITMARKED)) 03082 if (!ast_streamfile(chan, "conf-onlyperson", chan->language)) 03083 ast_waitstream(chan, ""); 03084 if (ast_test_flag64(confflags, CONFFLAG_WAITMARKED) && conf->markedusers == 0) 03085 if (!ast_streamfile(chan, "conf-waitforleader", chan->language)) 03086 ast_waitstream(chan, ""); 03087 } 03088 03089 if (!ast_test_flag64(confflags, CONFFLAG_QUIET) && ast_test_flag64(confflags, CONFFLAG_ANNOUNCEUSERCOUNT) && 03090 conf->users > 1) { 03091 int keepplaying = 1; 03092 03093 if (conf->users == 2) { 03094 if (!ast_streamfile(chan, "conf-onlyone", chan->language)) { 03095 res = ast_waitstream(chan, AST_DIGIT_ANY); 03096 ast_stopstream(chan); 03097 if (res > 0) 03098 keepplaying = 0; 03099 else if (res == -1) 03100 goto outrun; 03101 } 03102 } else { 03103 if (!ast_streamfile(chan, "conf-thereare", chan->language)) { 03104 res = ast_waitstream(chan, AST_DIGIT_ANY); 03105 ast_stopstream(chan); 03106 if (res > 0) 03107 keepplaying = 0; 03108 else if (res == -1) 03109 goto outrun; 03110 } 03111 if (keepplaying) { 03112 res = ast_say_number(chan, conf->users - 1, AST_DIGIT_ANY, chan->language, (char *) NULL); 03113 if (res > 0) 03114 keepplaying = 0; 03115 else if (res == -1) 03116 goto outrun; 03117 } 03118 if (keepplaying && !ast_streamfile(chan, "conf-otherinparty", chan->language)) { 03119 res = ast_waitstream(chan, AST_DIGIT_ANY); 03120 ast_stopstream(chan); 03121 if (res > 0) 03122 keepplaying = 0; 03123 else if (res == -1) 03124 goto outrun; 03125 } 03126 } 03127 } 03128 03129 if (!ast_test_flag64(confflags, CONFFLAG_NO_AUDIO_UNTIL_UP)) { 03130 /* We're leaving this alone until the state gets changed to up */ 03131 ast_indicate(chan, -1); 03132 } 03133 03134 if (ast_set_write_format(chan, AST_FORMAT_SLINEAR) < 0) { 03135 ast_log(LOG_WARNING, "Unable to set '%s' to write linear mode\n", chan->name); 03136 goto outrun; 03137 } 03138 03139 if (ast_set_read_format(chan, AST_FORMAT_SLINEAR) < 0) { 03140 ast_log(LOG_WARNING, "Unable to set '%s' to read linear mode\n", chan->name); 03141 goto outrun; 03142 } 03143 03144 /* Reduce background noise from each participant */ 03145 if (!ast_test_flag64(confflags, CONFFLAG_DONT_DENOISE) && 03146 (mod_speex = ast_module_helper("", "func_speex", 0, 0, 0, 0))) { 03147 ast_free(mod_speex); 03148 ast_func_write(chan, "DENOISE(rx)", "on"); 03149 } 03150 03151 retrydahdi = (strcasecmp(chan->tech->type, "DAHDI") || (chan->audiohooks || chan->monitor) ? 1 : 0); 03152 user->dahdichannel = !retrydahdi; 03153 03154 dahdiretry: 03155 origfd = chan->fds[0]; 03156 if (retrydahdi) { 03157 /* open pseudo in non-blocking mode */ 03158 fd = open("/dev/dahdi/pseudo", O_RDWR | O_NONBLOCK); 03159 if (fd < 0) { 03160 ast_log(LOG_WARNING, "Unable to open DAHDI pseudo channel: %s\n", strerror(errno)); 03161 goto outrun; 03162 } 03163 using_pseudo = 1; 03164 /* Setup buffering information */ 03165 memset(&bi, 0, sizeof(bi)); 03166 bi.bufsize = CONF_SIZE / 2; 03167 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE; 03168 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE; 03169 bi.numbufs = audio_buffers; 03170 if (ioctl(fd, DAHDI_SET_BUFINFO, &bi)) { 03171 ast_log(LOG_WARNING, "Unable to set buffering information: %s\n", strerror(errno)); 03172 close(fd); 03173 goto outrun; 03174 } 03175 x = 1; 03176 if (ioctl(fd, DAHDI_SETLINEAR, &x)) { 03177 ast_log(LOG_WARNING, "Unable to set linear mode: %s\n", strerror(errno)); 03178 close(fd); 03179 goto outrun; 03180 } 03181 nfds = 1; 03182 } else { 03183 /* XXX Make sure we're not running on a pseudo channel XXX */ 03184 fd = chan->fds[0]; 03185 nfds = 0; 03186 } 03187 memset(&dahdic, 0, sizeof(dahdic)); 03188 memset(&dahdic_empty, 0, sizeof(dahdic_empty)); 03189 /* Check to see if we're in a conference... */ 03190 dahdic.chan = 0; 03191 if (ioctl(fd, DAHDI_GETCONF, &dahdic)) { 03192 ast_log(LOG_WARNING, "Error getting conference\n"); 03193 close(fd); 03194 goto outrun; 03195 } 03196 if (dahdic.confmode) { 03197 /* Whoa, already in a conference... Retry... */ 03198 if (!retrydahdi) { 03199 ast_debug(1, "DAHDI channel is in a conference already, retrying with pseudo\n"); 03200 retrydahdi = 1; 03201 goto dahdiretry; 03202 } 03203 } 03204 memset(&dahdic, 0, sizeof(dahdic)); 03205 /* Add us to the conference */ 03206 dahdic.chan = 0; 03207 dahdic.confno = conf->dahdiconf; 03208 03209 if (!ast_test_flag64(confflags, CONFFLAG_QUIET) && (ast_test_flag64(confflags, CONFFLAG_INTROUSER) || 03210 ast_test_flag64(confflags, CONFFLAG_INTROUSERNOREVIEW)) && conf->users > 1) { 03211 struct announce_listitem *item; 03212 if (!(item = ao2_alloc(sizeof(*item), NULL))) 03213 goto outrun; 03214 ast_copy_string(item->namerecloc, user->namerecloc, sizeof(item->namerecloc)); 03215 ast_copy_string(item->language, chan->language, sizeof(item->language)); 03216 item->confchan = conf->chan; 03217 item->confusers = conf->users; 03218 item->announcetype = CONF_HASJOIN; 03219 ast_mutex_lock(&conf->announcelistlock); 03220 ao2_ref(item, +1); /* add one more so we can determine when announce_thread is done playing it */ 03221 AST_LIST_INSERT_TAIL(&conf->announcelist, item, entry); 03222 ast_cond_signal(&conf->announcelist_addition); 03223 ast_mutex_unlock(&conf->announcelistlock); 03224 03225 while (!ast_check_hangup(conf->chan) && ao2_ref(item, 0) == 2 && !ast_safe_sleep(chan, 1000)) { 03226 ; 03227 } 03228 ao2_ref(item, -1); 03229 } 03230 03231 if (ast_test_flag64(confflags, CONFFLAG_WAITMARKED) && !conf->markedusers) 03232 dahdic.confmode = DAHDI_CONF_CONF; 03233 else if (ast_test_flag64(confflags, CONFFLAG_MONITOR)) 03234 dahdic.confmode = DAHDI_CONF_CONFMON | DAHDI_CONF_LISTENER; 03235 else if (ast_test_flag64(confflags, CONFFLAG_TALKER)) 03236 dahdic.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER; 03237 else 03238 dahdic.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER; 03239 03240 if (ioctl(fd, DAHDI_SETCONF, &dahdic)) { 03241 ast_log(LOG_WARNING, "Error setting conference\n"); 03242 close(fd); 03243 goto outrun; 03244 } 03245 ast_debug(1, "Placed channel %s in DAHDI conf %d\n", chan->name, conf->dahdiconf); 03246 03247 if (!sent_event) { 03248 ast_manager_event(chan, EVENT_FLAG_CALL, "MeetmeJoin", 03249 "Channel: %s\r\n" 03250 "Uniqueid: %s\r\n" 03251 "Meetme: %s\r\n" 03252 "Usernum: %d\r\n" 03253 "CallerIDnum: %s\r\n" 03254 "CallerIDname: %s\r\n" 03255 "ConnectedLineNum: %s\r\n" 03256 "ConnectedLineName: %s\r\n", 03257 chan->name, chan->uniqueid, conf->confno, 03258 user->user_no, 03259 S_COR(user->chan->caller.id.number.valid, user->chan->caller.id.number.str, "<unknown>"), 03260 S_COR(user->chan->caller.id.name.valid, user->chan->caller.id.name.str, "<unknown>"), 03261 S_COR(user->chan->connected.id.number.valid, user->chan->connected.id.number.str, "<unknown>"), 03262 S_COR(user->chan->connected.id.name.valid, user->chan->connected.id.name.str, "<unknown>") 03263 ); 03264 sent_event = 1; 03265 } 03266 03267 if (!firstpass && !ast_test_flag64(confflags, CONFFLAG_MONITOR) && 03268 !ast_test_flag64(confflags, CONFFLAG_ADMIN)) { 03269 firstpass = 1; 03270 if (!ast_test_flag64(confflags, CONFFLAG_QUIET)) 03271 if (!ast_test_flag64(confflags, CONFFLAG_WAITMARKED) || (ast_test_flag64(confflags, CONFFLAG_MARKEDUSER) && 03272 (conf->markedusers >= 1))) { 03273 conf_play(chan, conf, ENTER); 03274 } 03275 } 03276 03277 conf_flush(fd, chan); 03278 03279 if (dsp) 03280 ast_dsp_free(dsp); 03281 03282 if (!(dsp = ast_dsp_new())) { 03283 ast_log(LOG_WARNING, "Unable to allocate DSP!\n"); 03284 res = -1; 03285 } 03286 03287 if (ast_test_flag64(confflags, CONFFLAG_AGI)) { 03288 /* Get name of AGI file to run from $(MEETME_AGI_BACKGROUND) 03289 or use default filename of conf-background.agi */ 03290 03291 ast_channel_lock(chan); 03292 if ((tmpvar = pbx_builtin_getvar_helper(chan, "MEETME_AGI_BACKGROUND"))) { 03293 agifile = ast_strdupa(tmpvar); 03294 } else { 03295 agifile = ast_strdupa(agifiledefault); 03296 } 03297 ast_channel_unlock(chan); 03298 03299 if (user->dahdichannel) { 03300 /* Set CONFMUTE mode on DAHDI channel to mute DTMF tones */ 03301 x = 1; 03302 ast_channel_setoption(chan, AST_OPTION_TONE_VERIFY, &x, sizeof(char), 0); 03303 } 03304 /* Find a pointer to the agi app and execute the script */ 03305 agi_app = pbx_findapp("agi"); 03306 if (agi_app) { 03307 ret = pbx_exec(chan, agi_app, agifile); 03308 } else { 03309 ast_log(LOG_WARNING, "Could not find application (agi)\n"); 03310 ret = -2; 03311 } 03312 if (user->dahdichannel) { 03313 /* Remove CONFMUTE mode on DAHDI channel */ 03314 x = 0; 03315 ast_channel_setoption(chan, AST_OPTION_TONE_VERIFY, &x, sizeof(char), 0); 03316 } 03317 } else { 03318 int lastusers = conf->users; 03319 if (user->dahdichannel && ast_test_flag64(confflags, CONFFLAG_STARMENU)) { 03320 /* Set CONFMUTE mode on DAHDI channel to mute DTMF tones when the menu is enabled */ 03321 x = 1; 03322 ast_channel_setoption(chan, AST_OPTION_TONE_VERIFY, &x, sizeof(char), 0); 03323 } 03324 03325 for (;;) { 03326 int menu_was_active = 0; 03327 03328 outfd = -1; 03329 ms = -1; 03330 now = ast_tvnow(); 03331 03332 if (rt_schedule && conf->endtime) { 03333 char currenttime[32]; 03334 long localendtime = 0; 03335 int extended = 0; 03336 struct ast_tm tm; 03337 struct ast_variable *var, *origvar; 03338 struct timeval tmp; 03339 03340 if (now.tv_sec % 60 == 0) { 03341 if (!checked) { 03342 ast_localtime(&now, &tm, NULL); 03343 ast_strftime(currenttime, sizeof(currenttime), DATE_FORMAT, &tm); 03344 var = origvar = ast_load_realtime("meetme", "confno", 03345 conf->confno, "starttime <=", currenttime, 03346 "endtime >=", currenttime, NULL); 03347 03348 for ( ; var; var = var->next) { 03349 if (!strcasecmp(var->name, "endtime")) { 03350 struct ast_tm endtime_tm; 03351 ast_strptime(var->value, "%Y-%m-%d %H:%M:%S", &endtime_tm); 03352 tmp = ast_mktime(&endtime_tm, NULL); 03353 localendtime = tmp.tv_sec; 03354 } 03355 } 03356 ast_variables_destroy(origvar); 03357 03358 /* A conference can be extended from the 03359 Admin/User menu or by an external source */ 03360 if (localendtime > conf->endtime){ 03361 conf->endtime = localendtime; 03362 extended = 1; 03363 } 03364 03365 if (conf->endtime && (now.tv_sec >= conf->endtime)) { 03366 ast_verbose("Quitting time...\n"); 03367 goto outrun; 03368 } 03369 03370 if (!announcement_played && conf->endalert) { 03371 if (now.tv_sec + conf->endalert >= conf->endtime) { 03372 if (!ast_streamfile(chan, "conf-will-end-in", chan->language)) 03373 ast_waitstream(chan, ""); 03374 ast_say_digits(chan, (conf->endtime - now.tv_sec) / 60, "", chan->language); 03375 if (!ast_streamfile(chan, "minutes", chan->language)) 03376 ast_waitstream(chan, ""); 03377 if (musiconhold) { 03378 conf_start_moh(chan, optargs[OPT_ARG_MOH_CLASS]); 03379 } 03380 announcement_played = 1; 03381 } 03382 } 03383 03384 if (extended) { 03385 announcement_played = 0; 03386 } 03387 03388 checked = 1; 03389 } 03390 } else { 03391 checked = 0; 03392 } 03393 } 03394 03395 if (user->kicktime && (user->kicktime <= now.tv_sec)) { 03396 if (ast_test_flag64(confflags, CONFFLAG_KICK_CONTINUE)) { 03397 ret = 0; 03398 } else { 03399 ret = -1; 03400 } 03401 break; 03402 } 03403 03404 to = -1; 03405 if (user->timelimit) { 03406 int minutes = 0, seconds = 0, remain = 0; 03407 03408 to = ast_tvdiff_ms(nexteventts, now); 03409 if (to < 0) { 03410 to = 0; 03411 } 03412 time_left_ms = user->timelimit - ast_tvdiff_ms(now, user->start_time); 03413 if (time_left_ms < to) { 03414 to = time_left_ms; 03415 } 03416 03417 if (time_left_ms <= 0) { 03418 if (user->end_sound) { 03419 res = ast_streamfile(chan, user->end_sound, chan->language); 03420 res = ast_waitstream(chan, ""); 03421 } 03422 if (ast_test_flag64(confflags, CONFFLAG_KICK_CONTINUE)) { 03423 ret = 0; 03424 } else { 03425 ret = -1; 03426 } 03427 break; 03428 } 03429 03430 if (!to) { 03431 if (time_left_ms >= 5000) { 03432 03433 remain = (time_left_ms + 500) / 1000; 03434 if (remain / 60 >= 1) { 03435 minutes = remain / 60; 03436 seconds = remain % 60; 03437 } else { 03438 seconds = remain; 03439 } 03440 03441 /* force the time left to round up if appropriate */ 03442 if (user->warning_sound && user->play_warning) { 03443 if (!strcmp(user->warning_sound, "timeleft")) { 03444 03445 res = ast_streamfile(chan, "vm-youhave", chan->language); 03446 res = ast_waitstream(chan, ""); 03447 if (minutes) { 03448 res = ast_say_number(chan, minutes, AST_DIGIT_ANY, chan->language, (char *) NULL); 03449 res = ast_streamfile(chan, "queue-minutes", chan->language); 03450 res = ast_waitstream(chan, ""); 03451 } 03452 if (seconds) { 03453 res = ast_say_number(chan, seconds, AST_DIGIT_ANY, chan->language, (char *) NULL); 03454 res = ast_streamfile(chan, "queue-seconds", chan->language); 03455 res = ast_waitstream(chan, ""); 03456 } 03457 } else { 03458 res = ast_streamfile(chan, user->warning_sound, chan->language); 03459 res = ast_waitstream(chan, ""); 03460 } 03461 if (musiconhold) { 03462 conf_start_moh(chan, optargs[OPT_ARG_MOH_CLASS]); 03463 } 03464 } 03465 } 03466 if (user->warning_freq) { 03467 nexteventts = ast_tvadd(nexteventts, ast_samp2tv(user->warning_freq, 1000)); 03468 } else { 03469 nexteventts = ast_tvadd(user->start_time, ast_samp2tv(user->timelimit, 1000)); 03470 } 03471 } 03472 } 03473 03474 now = ast_tvnow(); 03475 if (timeout && now.tv_sec >= timeout) { 03476 if (ast_test_flag64(confflags, CONFFLAG_KICK_CONTINUE)) { 03477 ret = 0; 03478 } else { 03479 ret = -1; 03480 } 03481 break; 03482 } 03483 03484 /* if we have just exited from the menu, and the user had a channel-driver 03485 volume adjustment, restore it 03486 */ 03487 if (!menu_mode && menu_was_active && user->listen.desired && !user->listen.actual) { 03488 set_talk_volume(user, user->listen.desired); 03489 } 03490 03491 menu_was_active = menu_mode; 03492 03493 currentmarked = conf->markedusers; 03494 if (!ast_test_flag64(confflags, CONFFLAG_QUIET) && 03495 ast_test_flag64(confflags, CONFFLAG_MARKEDUSER) && 03496 ast_test_flag64(confflags, CONFFLAG_WAITMARKED) && 03497 lastmarked == 0) { 03498 if (currentmarked == 1 && conf->users > 1) { 03499 ast_say_number(chan, conf->users - 1, AST_DIGIT_ANY, chan->language, (char *) NULL); 03500 if (conf->users - 1 == 1) { 03501 if (!ast_streamfile(chan, "conf-userwilljoin", chan->language)) { 03502 ast_waitstream(chan, ""); 03503 } 03504 } else { 03505 if (!ast_streamfile(chan, "conf-userswilljoin", chan->language)) { 03506 ast_waitstream(chan, ""); 03507 } 03508 } 03509 } 03510 if (conf->users == 1 && !ast_test_flag64(confflags, CONFFLAG_MARKEDUSER)) { 03511 if (!ast_streamfile(chan, "conf-onlyperson", chan->language)) { 03512 ast_waitstream(chan, ""); 03513 } 03514 } 03515 } 03516 03517 /* Update the struct with the actual confflags */ 03518 user->userflags = *confflags; 03519 03520 if (ast_test_flag64(confflags, CONFFLAG_WAITMARKED)) { 03521 if (currentmarked == 0) { 03522 if (lastmarked != 0) { 03523 if (!ast_test_flag64(confflags, CONFFLAG_QUIET)) { 03524 if (!ast_streamfile(chan, "conf-leaderhasleft", chan->language)) { 03525 ast_waitstream(chan, ""); 03526 } 03527 } 03528 if (ast_test_flag64(confflags, CONFFLAG_MARKEDEXIT)) { 03529 if (ast_test_flag64(confflags, CONFFLAG_KICK_CONTINUE)) { 03530 ret = 0; 03531 } 03532 break; 03533 } else { 03534 dahdic.confmode = DAHDI_CONF_CONF; 03535 if (ioctl(fd, DAHDI_SETCONF, &dahdic)) { 03536 ast_log(LOG_WARNING, "Error setting conference\n"); 03537 close(fd); 03538 goto outrun; 03539 } 03540 } 03541 } 03542 if (!musiconhold && (ast_test_flag64(confflags, CONFFLAG_MOH))) { 03543 conf_start_moh(chan, optargs[OPT_ARG_MOH_CLASS]); 03544 musiconhold = 1; 03545 } 03546 } else if (currentmarked >= 1 && lastmarked == 0) { 03547 /* Marked user entered, so cancel timeout */ 03548 timeout = 0; 03549 if (ast_test_flag64(confflags, CONFFLAG_MONITOR)) { 03550 dahdic.confmode = DAHDI_CONF_CONFMON | DAHDI_CONF_LISTENER; 03551 } else if (ast_test_flag64(confflags, CONFFLAG_TALKER)) { 03552 dahdic.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER; 03553 } else { 03554 dahdic.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER; 03555 } 03556 if (ioctl(fd, DAHDI_SETCONF, &dahdic)) { 03557 ast_log(LOG_WARNING, "Error setting conference\n"); 03558 close(fd); 03559 goto outrun; 03560 } 03561 if (musiconhold && (ast_test_flag64(confflags, CONFFLAG_MOH))) { 03562 ast_moh_stop(chan); 03563 musiconhold = 0; 03564 } 03565 if (!ast_test_flag64(confflags, CONFFLAG_QUIET) && 03566 !ast_test_flag64(confflags, CONFFLAG_MARKEDUSER)) { 03567 if (!ast_streamfile(chan, "conf-placeintoconf", chan->language)) { 03568 ast_waitstream(chan, ""); 03569 } 03570 conf_play(chan, conf, ENTER); 03571 } 03572 } 03573 } 03574 03575 /* trying to add moh for single person conf */ 03576 if (ast_test_flag64(confflags, CONFFLAG_MOH) && !ast_test_flag64(confflags, CONFFLAG_WAITMARKED)) { 03577 if (conf->users == 1) { 03578 if (!musiconhold) { 03579 conf_start_moh(chan, optargs[OPT_ARG_MOH_CLASS]); 03580 musiconhold = 1; 03581 } 03582 } else { 03583 if (musiconhold) { 03584 ast_moh_stop(chan); 03585 musiconhold = 0; 03586 } 03587 } 03588 } 03589 03590 /* Leave if the last marked user left */ 03591 if (currentmarked == 0 && lastmarked != 0 && ast_test_flag64(confflags, CONFFLAG_MARKEDEXIT)) { 03592 if (ast_test_flag64(confflags, CONFFLAG_KICK_CONTINUE)) { 03593 ret = 0; 03594 } else { 03595 ret = -1; 03596 } 03597 break; 03598 } 03599 03600 /* Throw a TestEvent if a user exit did not cause this user to leave the conference */ 03601 if (conf->users != lastusers) { 03602 if (conf->users < lastusers) { 03603 ast_test_suite_event_notify("NOEXIT", "Message: CONFFLAG_MARKEDEXIT\r\nLastUsers: %d\r\nUsers: %d", lastusers, conf->users); 03604 } 03605 lastusers = conf->users; 03606 } 03607 03608 /* Check if my modes have changed */ 03609 03610 /* If I should be muted but am still talker, mute me */ 03611 if ((user->adminflags & (ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED)) && (dahdic.confmode & DAHDI_CONF_TALKER)) { 03612 dahdic.confmode ^= DAHDI_CONF_TALKER; 03613 if (ioctl(fd, DAHDI_SETCONF, &dahdic)) { 03614 ast_log(LOG_WARNING, "Error setting conference - Un/Mute \n"); 03615 ret = -1; 03616 break; 03617 } 03618 03619 /* Indicate user is not talking anymore - change him to unmonitored state */ 03620 if (ast_test_flag64(confflags, (CONFFLAG_MONITORTALKER | CONFFLAG_OPTIMIZETALKER))) { 03621 set_user_talking(chan, conf, user, -1, ast_test_flag64(confflags, CONFFLAG_MONITORTALKER)); 03622 } 03623 03624 ast_manager_event(chan, EVENT_FLAG_CALL, "MeetmeMute", 03625 "Channel: %s\r\n" 03626 "Uniqueid: %s\r\n" 03627 "Meetme: %s\r\n" 03628 "Usernum: %d\r\n" 03629 "Status: on\r\n", 03630 chan->name, chan->uniqueid, conf->confno, user->user_no); 03631 } 03632 03633 /* If I should be un-muted but am not talker, un-mute me */ 03634 if (!(user->adminflags & (ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED)) && !ast_test_flag64(confflags, CONFFLAG_MONITOR) && !(dahdic.confmode & DAHDI_CONF_TALKER)) { 03635 dahdic.confmode |= DAHDI_CONF_TALKER; 03636 if (ioctl(fd, DAHDI_SETCONF, &dahdic)) { 03637 ast_log(LOG_WARNING, "Error setting conference - Un/Mute \n"); 03638 ret = -1; 03639 break; 03640 } 03641 03642 ast_manager_event(chan, EVENT_FLAG_CALL, "MeetmeMute", 03643 "Channel: %s\r\n" 03644 "Uniqueid: %s\r\n" 03645 "Meetme: %s\r\n" 03646 "Usernum: %d\r\n" 03647 "Status: off\r\n", 03648 chan->name, chan->uniqueid, conf->confno, user->user_no); 03649 } 03650 03651 if ((user->adminflags & (ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED)) && 03652 (user->adminflags & ADMINFLAG_T_REQUEST) && !(talkreq_manager)) { 03653 talkreq_manager = 1; 03654 03655 ast_manager_event(chan, EVENT_FLAG_CALL, "MeetmeTalkRequest", 03656 "Channel: %s\r\n" 03657 "Uniqueid: %s\r\n" 03658 "Meetme: %s\r\n" 03659 "Usernum: %d\r\n" 03660 "Status: on\r\n", 03661 chan->name, chan->uniqueid, conf->confno, user->user_no); 03662 } 03663 03664 03665 if (!(user->adminflags & (ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED)) && 03666 !(user->adminflags & ADMINFLAG_T_REQUEST) && (talkreq_manager)) { 03667 talkreq_manager = 0; 03668 ast_manager_event(chan, EVENT_FLAG_CALL, "MeetmeTalkRequest", 03669 "Channel: %s\r\n" 03670 "Uniqueid: %s\r\n" 03671 "Meetme: %s\r\n" 03672 "Usernum: %d\r\n" 03673 "Status: off\r\n", 03674 chan->name, chan->uniqueid, conf->confno, user->user_no); 03675 } 03676 03677 /* If I have been kicked, exit the conference */ 03678 if (user->adminflags & ADMINFLAG_KICKME) { 03679 /* You have been kicked. */ 03680 if (!ast_test_flag64(confflags, CONFFLAG_QUIET) && 03681 !ast_streamfile(chan, "conf-kicked", chan->language)) { 03682 ast_waitstream(chan, ""); 03683 } 03684 ret = 0; 03685 break; 03686 } 03687 03688 /* Perform a hangup check here since ast_waitfor_nandfds will not always be able to get a channel after a hangup has occurred */ 03689 if (ast_check_hangup(chan)) { 03690 break; 03691 } 03692 03693 c = ast_waitfor_nandfds(&chan, 1, &fd, nfds, NULL, &outfd, &ms); 03694 03695 if (c) { 03696 char dtmfstr[2] = ""; 03697 03698 if (c->fds[0] != origfd || (user->dahdichannel && (c->audiohooks || c->monitor))) { 03699 if (using_pseudo) { 03700 /* Kill old pseudo */ 03701 close(fd); 03702 using_pseudo = 0; 03703 } 03704 ast_debug(1, "Ooh, something swapped out under us, starting over\n"); 03705 retrydahdi = (strcasecmp(c->tech->type, "DAHDI") || (c->audiohooks || c->monitor) ? 1 : 0); 03706 user->dahdichannel = !retrydahdi; 03707 goto dahdiretry; 03708 } 03709 if (ast_test_flag64(confflags, CONFFLAG_MONITOR) || (user->adminflags & (ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED))) { 03710 f = ast_read_noaudio(c); 03711 } else { 03712 f = ast_read(c); 03713 } 03714 if (!f) { 03715 break; 03716 } 03717 if (f->frametype == AST_FRAME_DTMF) { 03718 dtmfstr[0] = f->subclass.integer; 03719 dtmfstr[1] = '\0'; 03720 } 03721 03722 if ((f->frametype == AST_FRAME_VOICE) && (f->subclass.codec == AST_FORMAT_SLINEAR)) { 03723 if (user->talk.actual) { 03724 ast_frame_adjust_volume(f, user->talk.actual); 03725 } 03726 03727 if (ast_test_flag64(confflags, (CONFFLAG_OPTIMIZETALKER | CONFFLAG_MONITORTALKER))) { 03728 if (user->talking == -1) { 03729 user->talking = 0; 03730 } 03731 03732 res = ast_dsp_silence(dsp, f, &totalsilence); 03733 if (!user->talking && totalsilence < MEETME_DELAYDETECTTALK) { 03734 set_user_talking(chan, conf, user, 1, ast_test_flag64(confflags, CONFFLAG_MONITORTALKER)); 03735 } 03736 03737 if (user->talking && totalsilence > MEETME_DELAYDETECTENDTALK) { 03738 set_user_talking(chan, conf, user, 0, ast_test_flag64(confflags, CONFFLAG_MONITORTALKER)); 03739 } 03740 } 03741 if (using_pseudo) { 03742 /* Absolutely do _not_ use careful_write here... 03743 it is important that we read data from the channel 03744 as fast as it arrives, and feed it into the conference. 03745 The buffering in the pseudo channel will take care of any 03746 timing differences, unless they are so drastic as to lose 03747 audio frames (in which case carefully writing would only 03748 have delayed the audio even further). 03749 */ 03750 /* As it turns out, we do want to use careful write. We just 03751 don't want to block, but we do want to at least *try* 03752 to write out all the samples. 03753 */ 03754 if (user->talking || !ast_test_flag64(confflags, CONFFLAG_OPTIMIZETALKER)) { 03755 careful_write(fd, f->data.ptr, f->datalen, 0); 03756 } 03757 } 03758 } else if (((f->frametype == AST_FRAME_DTMF) && (f->subclass.integer == '*') && ast_test_flag64(confflags, CONFFLAG_STARMENU)) || ((f->frametype == AST_FRAME_DTMF) && menu_mode)) { 03759 if (ast_test_flag64(confflags, CONFFLAG_PASS_DTMF)) { 03760 conf_queue_dtmf(conf, user, f); 03761 } 03762 /* Take out of conference */ 03763 if (ioctl(fd, DAHDI_SETCONF, &dahdic_empty)) { 03764 ast_log(LOG_WARNING, "Error setting conference\n"); 03765 close(fd); 03766 ast_frfree(f); 03767 goto outrun; 03768 } 03769 03770 /* if we are entering the menu, and the user has a channel-driver 03771 volume adjustment, clear it 03772 */ 03773 if (!menu_mode && user->talk.desired && !user->talk.actual) { 03774 set_talk_volume(user, 0); 03775 } 03776 03777 if (musiconhold) { 03778 ast_moh_stop(chan); 03779 } else if (!menu_mode) { 03780 char *menu_to_play; 03781 if (ast_test_flag64(confflags, CONFFLAG_ADMIN)) { 03782 menu_mode = MENU_ADMIN; 03783 menu_to_play = "conf-adminmenu-18"; 03784 } else { 03785 menu_mode = MENU_NORMAL; 03786 menu_to_play = "conf-usermenu-162"; 03787 } 03788 03789 if (!ast_streamfile(chan, menu_to_play, chan->language)) { 03790 dtmf = ast_waitstream(chan, AST_DIGIT_ANY); 03791 ast_stopstream(chan); 03792 } else { 03793 dtmf = 0; 03794 } 03795 } else { 03796 dtmf = f->subclass.integer; 03797 } 03798 03799 if (dtmf > 0) { 03800 meetme_menu(&menu_mode, &dtmf, conf, confflags, 03801 chan, user, recordingtmp, sizeof(recordingtmp)); 03802 } 03803 03804 if (musiconhold && !menu_mode) { 03805 conf_start_moh(chan, optargs[OPT_ARG_MOH_CLASS]); 03806 } 03807 03808 /* Put back into conference */ 03809 if (ioctl(fd, DAHDI_SETCONF, &dahdic)) { 03810 ast_log(LOG_WARNING, "Error setting conference\n"); 03811 close(fd); 03812 ast_frfree(f); 03813 goto outrun; 03814 } 03815 03816 conf_flush(fd, chan); 03817 /* 03818 * Since options using DTMF could absorb DTMF meant for the 03819 * conference menu, we have to check them after the menu. 03820 */ 03821 } else if ((f->frametype == AST_FRAME_DTMF) && ast_test_flag64(confflags, CONFFLAG_EXIT_CONTEXT) && ast_exists_extension(chan, exitcontext, dtmfstr, 1, "")) { 03822 if (ast_test_flag64(confflags, CONFFLAG_PASS_DTMF)) { 03823 conf_queue_dtmf(conf, user, f); 03824 } 03825 03826 if (!ast_goto_if_exists(chan, exitcontext, dtmfstr, 1)) { 03827 ast_debug(1, "Got DTMF %c, goto context %s\n", dtmfstr[0], exitcontext); 03828 ret = 0; 03829 ast_frfree(f); 03830 break; 03831 } else { 03832 ast_debug(2, "Exit by single digit did not work in meetme. Extension %s does not exist in context %s\n", dtmfstr, exitcontext); 03833 } 03834 } else if ((f->frametype == AST_FRAME_DTMF) && ast_test_flag64(confflags, CONFFLAG_KEYEXIT) && 03835 (strchr(exitkeys, f->subclass.integer))) { 03836 pbx_builtin_setvar_helper(chan, "MEETME_EXIT_KEY", dtmfstr); 03837 03838 if (ast_test_flag64(confflags, CONFFLAG_PASS_DTMF)) { 03839 conf_queue_dtmf(conf, user, f); 03840 } 03841 ret = 0; 03842 ast_frfree(f); 03843 break; 03844 } else if ((f->frametype == AST_FRAME_DTMF_BEGIN || f->frametype == AST_FRAME_DTMF_END) 03845 && ast_test_flag64(confflags, CONFFLAG_PASS_DTMF)) { 03846 conf_queue_dtmf(conf, user, f); 03847 } else if (ast_test_flag64(confflags, CONFFLAG_SLA_STATION) && f->frametype == AST_FRAME_CONTROL) { 03848 switch (f->subclass.integer) { 03849 case AST_CONTROL_HOLD: 03850 sla_queue_event_conf(SLA_EVENT_HOLD, chan, conf); 03851 break; 03852 default: 03853 break; 03854 } 03855 } else if (f->frametype == AST_FRAME_NULL) { 03856 /* Ignore NULL frames. It is perfectly normal to get these if the person is muted. */ 03857 } else if (f->frametype == AST_FRAME_CONTROL) { 03858 switch (f->subclass.integer) { 03859 case AST_CONTROL_BUSY: 03860 case AST_CONTROL_CONGESTION: 03861 ast_frfree(f); 03862 goto outrun; 03863 break; 03864 default: 03865 ast_debug(1, 03866 "Got ignored control frame on channel %s, f->frametype=%u,f->subclass=%d\n", 03867 chan->name, f->frametype, f->subclass.integer); 03868 } 03869 } else { 03870 ast_debug(1, 03871 "Got unrecognized frame on channel %s, f->frametype=%u,f->subclass=%d\n", 03872 chan->name, f->frametype, f->subclass.integer); 03873 } 03874 ast_frfree(f); 03875 } else if (outfd > -1) { 03876 res = read(outfd, buf, CONF_SIZE); 03877 if (res > 0) { 03878 memset(&fr, 0, sizeof(fr)); 03879 fr.frametype = AST_FRAME_VOICE; 03880 fr.subclass.codec = AST_FORMAT_SLINEAR; 03881 fr.datalen = res; 03882 fr.samples = res / 2; 03883 fr.data.ptr = buf; 03884 fr.offset = AST_FRIENDLY_OFFSET; 03885 if (!user->listen.actual && 03886 (ast_test_flag64(confflags, CONFFLAG_MONITOR) || 03887 (user->adminflags & (ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED)) || 03888 (!user->talking && ast_test_flag64(confflags, CONFFLAG_OPTIMIZETALKER)) 03889 )) { 03890 int idx; 03891 for (idx = 0; idx < AST_FRAME_BITS; idx++) { 03892 if (chan->rawwriteformat & (1 << idx)) { 03893 break; 03894 } 03895 } 03896 if (idx >= AST_FRAME_BITS) { 03897 goto bailoutandtrynormal; 03898 } 03899 ast_mutex_lock(&conf->listenlock); 03900 if (!conf->transframe[idx]) { 03901 if (conf->origframe) { 03902 if (musiconhold 03903 && !ast_test_flag64(confflags, CONFFLAG_WAITMARKED) 03904 && !ast_dsp_silence(dsp, conf->origframe, &confsilence) 03905 && confsilence < MEETME_DELAYDETECTTALK) { 03906 ast_moh_stop(chan); 03907 mohtempstopped = 1; 03908 } 03909 if (!conf->transpath[idx]) { 03910 conf->transpath[idx] = ast_translator_build_path((1 << idx), AST_FORMAT_SLINEAR); 03911 } 03912 if (conf->transpath[idx]) { 03913 conf->transframe[idx] = ast_translate(conf->transpath[idx], conf->origframe, 0); 03914 if (!conf->transframe[idx]) { 03915 conf->transframe[idx] = &ast_null_frame; 03916 } 03917 } 03918 } 03919 } 03920 if (conf->transframe[idx]) { 03921 if ((conf->transframe[idx]->frametype != AST_FRAME_NULL) && 03922 can_write(chan, confflags)) { 03923 struct ast_frame *cur; 03924 /* the translator may have returned a list of frames, so 03925 write each one onto the channel 03926 */ 03927 for (cur = conf->transframe[idx]; cur; cur = AST_LIST_NEXT(cur, frame_list)) { 03928 if (ast_write(chan, cur)) { 03929 ast_log(LOG_WARNING, "Unable to write frame to channel %s\n", chan->name); 03930 break; 03931 } 03932 } 03933 if (musiconhold && mohtempstopped && confsilence > MEETME_DELAYDETECTENDTALK) { 03934 mohtempstopped = 0; 03935 conf_start_moh(chan, optargs[OPT_ARG_MOH_CLASS]); 03936 } 03937 } 03938 } else { 03939 ast_mutex_unlock(&conf->listenlock); 03940 goto bailoutandtrynormal; 03941 } 03942 ast_mutex_unlock(&conf->listenlock); 03943 } else { 03944 bailoutandtrynormal: 03945 if (musiconhold 03946 && !ast_test_flag64(confflags, CONFFLAG_WAITMARKED) 03947 && !ast_dsp_silence(dsp, &fr, &confsilence) 03948 && confsilence < MEETME_DELAYDETECTTALK) { 03949 ast_moh_stop(chan); 03950 mohtempstopped = 1; 03951 } 03952 if (user->listen.actual) { 03953 ast_frame_adjust_volume(&fr, user->listen.actual); 03954 } 03955 if (can_write(chan, confflags) && ast_write(chan, &fr) < 0) { 03956 ast_log(LOG_WARNING, "Unable to write frame to channel %s\n", chan->name); 03957 } 03958 if (musiconhold && mohtempstopped && confsilence > MEETME_DELAYDETECTENDTALK) { 03959 mohtempstopped = 0; 03960 conf_start_moh(chan, optargs[OPT_ARG_MOH_CLASS]); 03961 } 03962 } 03963 } else { 03964 ast_log(LOG_WARNING, "Failed to read frame: %s\n", strerror(errno)); 03965 } 03966 } 03967 lastmarked = currentmarked; 03968 } 03969 } 03970 03971 if (musiconhold) { 03972 ast_moh_stop(chan); 03973 } 03974 03975 if (using_pseudo) { 03976 close(fd); 03977 } else { 03978 /* Take out of conference */ 03979 dahdic.chan = 0; 03980 dahdic.confno = 0; 03981 dahdic.confmode = 0; 03982 if (ioctl(fd, DAHDI_SETCONF, &dahdic)) { 03983 ast_log(LOG_WARNING, "Error setting conference\n"); 03984 } 03985 } 03986 03987 reset_volumes(user); 03988 03989 if (!ast_test_flag64(confflags, CONFFLAG_QUIET) && !ast_test_flag64(confflags, CONFFLAG_MONITOR) && 03990 !ast_test_flag64(confflags, CONFFLAG_ADMIN)) { 03991 conf_play(chan, conf, LEAVE); 03992 } 03993 03994 if (!ast_test_flag64(confflags, CONFFLAG_QUIET) && (ast_test_flag64(confflags, CONFFLAG_INTROUSER) || ast_test_flag64(confflags, CONFFLAG_INTROUSERNOREVIEW)) && conf->users > 1) { 03995 struct announce_listitem *item; 03996 if (!(item = ao2_alloc(sizeof(*item), NULL))) 03997 goto outrun; 03998 ast_copy_string(item->namerecloc, user->namerecloc, sizeof(item->namerecloc)); 03999 ast_copy_string(item->language, chan->language, sizeof(item->language)); 04000 item->confchan = conf->chan; 04001 item->confusers = conf->users; 04002 item->announcetype = CONF_HASLEFT; 04003 ast_mutex_lock(&conf->announcelistlock); 04004 AST_LIST_INSERT_TAIL(&conf->announcelist, item, entry); 04005 ast_cond_signal(&conf->announcelist_addition); 04006 ast_mutex_unlock(&conf->announcelistlock); 04007 } else if (!ast_test_flag64(confflags, CONFFLAG_QUIET) && (ast_test_flag64(confflags, CONFFLAG_INTROUSER) || 04008 ast_test_flag64(confflags, CONFFLAG_INTROUSERNOREVIEW)) && conf->users == 1) { 04009 /* Last person is leaving, so no reason to try and announce, but should delete the name recording */ 04010 ast_filedelete(user->namerecloc, NULL); 04011 } 04012 04013 outrun: 04014 AST_LIST_LOCK(&confs); 04015 04016 if (dsp) { 04017 ast_dsp_free(dsp); 04018 } 04019 04020 if (user->user_no) { 04021 /* Only cleanup users who really joined! */ 04022 now = ast_tvnow(); 04023 04024 if (sent_event) { 04025 ast_manager_event(chan, EVENT_FLAG_CALL, "MeetmeLeave", 04026 "Channel: %s\r\n" 04027 "Uniqueid: %s\r\n" 04028 "Meetme: %s\r\n" 04029 "Usernum: %d\r\n" 04030 "CallerIDNum: %s\r\n" 04031 "CallerIDName: %s\r\n" 04032 "ConnectedLineNum: %s\r\n" 04033 "ConnectedLineName: %s\r\n" 04034 "Duration: %ld\r\n", 04035 chan->name, chan->uniqueid, conf->confno, 04036 user->user_no, 04037 S_COR(user->chan->caller.id.number.valid, user->chan->caller.id.number.str, "<unknown>"), 04038 S_COR(user->chan->caller.id.name.valid, user->chan->caller.id.name.str, "<unknown>"), 04039 S_COR(user->chan->connected.id.number.valid, user->chan->connected.id.number.str, "<unknown>"), 04040 S_COR(user->chan->connected.id.name.valid, user->chan->connected.id.name.str, "<unknown>"), 04041 (long)(now.tv_sec - user->jointime)); 04042 } 04043 04044 if (setusercount) { 04045 conf->users--; 04046 if (rt_log_members) { 04047 /* Update table */ 04048 snprintf(members, sizeof(members), "%d", conf->users); 04049 ast_realtime_require_field("meetme", 04050 "confno", strlen(conf->confno) > 7 ? RQ_UINTEGER4 : strlen(conf->confno) > 4 ? RQ_UINTEGER3 : RQ_UINTEGER2, strlen(conf->confno), 04051 "members", RQ_UINTEGER1, strlen(members), 04052 NULL); 04053 ast_update_realtime("meetme", "confno", conf->confno, "members", members, NULL); 04054 } 04055 if (ast_test_flag64(confflags, CONFFLAG_MARKEDUSER)) { 04056 conf->markedusers--; 04057 } 04058 } 04059 /* Remove ourselves from the container */ 04060 ao2_unlink(conf->usercontainer, user); 04061 04062 /* Change any states */ 04063 if (!conf->users) { 04064 ast_devstate_changed(AST_DEVICE_NOT_INUSE, (conf->isdynamic ? AST_DEVSTATE_NOT_CACHABLE : AST_DEVSTATE_CACHABLE), "meetme:%s", conf->confno); 04065 } 04066 04067 /* Return the number of seconds the user was in the conf */ 04068 snprintf(meetmesecs, sizeof(meetmesecs), "%d", (int) (time(NULL) - user->jointime)); 04069 pbx_builtin_setvar_helper(chan, "MEETMESECS", meetmesecs); 04070 04071 /* Return the RealTime bookid for CDR linking */ 04072 if (rt_schedule) { 04073 pbx_builtin_setvar_helper(chan, "MEETMEBOOKID", conf->bookid); 04074 } 04075 } 04076 ao2_ref(user, -1); 04077 AST_LIST_UNLOCK(&confs); 04078 04079 return ret; 04080 }
static void conf_start_moh | ( | struct ast_channel * | chan, | |
const char * | musicclass | |||
) | [static] |
Definition at line 2178 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().
02179 { 02180 char *original_moh; 02181 02182 ast_channel_lock(chan); 02183 original_moh = ast_strdupa(chan->musicclass); 02184 ast_string_field_set(chan, musicclass, musicclass); 02185 ast_channel_unlock(chan); 02186 02187 ast_moh_start(chan, original_moh, NULL); 02188 02189 ast_channel_lock(chan); 02190 ast_string_field_set(chan, musicclass, original_moh); 02191 ast_channel_unlock(chan); 02192 }
static int count_exec | ( | struct ast_channel * | chan, | |
const char * | data | |||
) | [static] |
The MeetmeCount application.
Definition at line 4374 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().
04375 { 04376 int res = 0; 04377 struct ast_conference *conf; 04378 int count; 04379 char *localdata; 04380 char val[80] = "0"; 04381 AST_DECLARE_APP_ARGS(args, 04382 AST_APP_ARG(confno); 04383 AST_APP_ARG(varname); 04384 ); 04385 04386 if (ast_strlen_zero(data)) { 04387 ast_log(LOG_WARNING, "MeetMeCount requires an argument (conference number)\n"); 04388 return -1; 04389 } 04390 04391 localdata = ast_strdupa(data); 04392 04393 AST_STANDARD_APP_ARGS(args, localdata); 04394 04395 conf = find_conf(chan, args.confno, 0, 0, NULL, 0, 1, NULL); 04396 04397 if (conf) { 04398 count = conf->users; 04399 dispose_conf(conf); 04400 conf = NULL; 04401 } else 04402 count = 0; 04403 04404 if (!ast_strlen_zero(args.varname)) { 04405 /* have var so load it and exit */ 04406 snprintf(val, sizeof(val), "%d", count); 04407 pbx_builtin_setvar_helper(chan, args.varname, val); 04408 } else { 04409 if (chan->_state != AST_STATE_UP) { 04410 ast_answer(chan); 04411 } 04412 res = ast_say_number(chan, count, "", chan->language, (char *) NULL); /* Needs gender */ 04413 } 04414 04415 return res; 04416 }
static struct sla_trunk_ref* create_trunk_ref | ( | struct sla_trunk * | trunk | ) | [static, read] |
Definition at line 6691 of file app_meetme.c.
References ao2_alloc, ao2_ref, and sla_trunk_ref_destructor().
Referenced by sla_add_trunk_to_station().
06692 { 06693 struct sla_trunk_ref *trunk_ref; 06694 06695 if (!(trunk_ref = ao2_alloc(sizeof(*trunk_ref), sla_trunk_ref_destructor))) { 06696 return NULL; 06697 } 06698 06699 ao2_ref(trunk, 1); 06700 trunk_ref->trunk = trunk; 06701 06702 return trunk_ref; 06703 }
static void* dial_trunk | ( | void * | data | ) | [static] |
Definition at line 6375 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, RAII_VAR, sla, sla_change_trunk_state(), SLA_TRUNK_STATE_IDLE, dial_trunk_args::station, and dial_trunk_args::trunk_ref.
Referenced by sla_station_exec().
06376 { 06377 struct dial_trunk_args *args = data; 06378 struct ast_dial *dial; 06379 char *tech, *tech_data; 06380 enum ast_dial_result dial_res; 06381 char conf_name[MAX_CONFNUM]; 06382 struct ast_conference *conf; 06383 struct ast_flags64 conf_flags = { 0 }; 06384 RAII_VAR(struct sla_trunk_ref *, trunk_ref, args->trunk_ref, unref_obj); 06385 RAII_VAR(struct sla_station *, station, args->station, unref_obj); 06386 int caller_is_saved; 06387 struct ast_party_caller caller; 06388 int last_state = 0; 06389 int current_state = 0; 06390 06391 if (!(dial = ast_dial_create())) { 06392 ast_mutex_lock(args->cond_lock); 06393 ast_cond_signal(args->cond); 06394 ast_mutex_unlock(args->cond_lock); 06395 return NULL; 06396 } 06397 06398 tech_data = ast_strdupa(trunk_ref->trunk->device); 06399 tech = strsep(&tech_data, "/"); 06400 if (ast_dial_append(dial, tech, tech_data) == -1) { 06401 ast_mutex_lock(args->cond_lock); 06402 ast_cond_signal(args->cond); 06403 ast_mutex_unlock(args->cond_lock); 06404 ast_dial_destroy(dial); 06405 return NULL; 06406 } 06407 06408 /* Do we need to save of the caller ID data? */ 06409 caller_is_saved = 0; 06410 if (!sla.attempt_callerid) { 06411 caller_is_saved = 1; 06412 caller = trunk_ref->chan->caller; 06413 ast_party_caller_init(&trunk_ref->chan->caller); 06414 } 06415 06416 dial_res = ast_dial_run(dial, trunk_ref->chan, 1); 06417 06418 /* Restore saved caller ID */ 06419 if (caller_is_saved) { 06420 ast_party_caller_free(&trunk_ref->chan->caller); 06421 trunk_ref->chan->caller = caller; 06422 } 06423 06424 if (dial_res != AST_DIAL_RESULT_TRYING) { 06425 ast_mutex_lock(args->cond_lock); 06426 ast_cond_signal(args->cond); 06427 ast_mutex_unlock(args->cond_lock); 06428 ast_dial_destroy(dial); 06429 return NULL; 06430 } 06431 06432 for (;;) { 06433 unsigned int done = 0; 06434 switch ((dial_res = ast_dial_state(dial))) { 06435 case AST_DIAL_RESULT_ANSWERED: 06436 trunk_ref->trunk->chan = ast_dial_answered(dial); 06437 case AST_DIAL_RESULT_HANGUP: 06438 case AST_DIAL_RESULT_INVALID: 06439 case AST_DIAL_RESULT_FAILED: 06440 case AST_DIAL_RESULT_TIMEOUT: 06441 case AST_DIAL_RESULT_UNANSWERED: 06442 done = 1; 06443 break; 06444 case AST_DIAL_RESULT_TRYING: 06445 current_state = AST_CONTROL_PROGRESS; 06446 break; 06447 case AST_DIAL_RESULT_RINGING: 06448 case AST_DIAL_RESULT_PROGRESS: 06449 case AST_DIAL_RESULT_PROCEEDING: 06450 current_state = AST_CONTROL_RINGING; 06451 break; 06452 } 06453 if (done) 06454 break; 06455 06456 /* check that SLA station that originated trunk call is still alive */ 06457 if (station && ast_device_state(station->device) == AST_DEVICE_NOT_INUSE) { 06458 ast_debug(3, "Originating station device %s no longer active\n", station->device); 06459 trunk_ref->trunk->chan = NULL; 06460 break; 06461 } 06462 06463 /* If trunk line state changed, send indication back to originating SLA Station channel */ 06464 if (current_state != last_state) { 06465 ast_debug(3, "Indicating State Change %d to channel %s\n", current_state, trunk_ref->chan->name); 06466 ast_indicate(trunk_ref->chan, current_state); 06467 last_state = current_state; 06468 } 06469 06470 /* avoid tight loop... sleep for 1/10th second */ 06471 ast_safe_sleep(trunk_ref->chan, 100); 06472 } 06473 06474 if (!trunk_ref->trunk->chan) { 06475 ast_mutex_lock(args->cond_lock); 06476 ast_cond_signal(args->cond); 06477 ast_mutex_unlock(args->cond_lock); 06478 ast_dial_join(dial); 06479 ast_dial_destroy(dial); 06480 return NULL; 06481 } 06482 06483 snprintf(conf_name, sizeof(conf_name), "SLA_%s", trunk_ref->trunk->name); 06484 ast_set_flag64(&conf_flags, 06485 CONFFLAG_QUIET | CONFFLAG_MARKEDEXIT | CONFFLAG_MARKEDUSER | 06486 CONFFLAG_PASS_DTMF | CONFFLAG_SLA_TRUNK); 06487 conf = build_conf(conf_name, "", "", 1, 1, 1, trunk_ref->trunk->chan, NULL); 06488 06489 ast_mutex_lock(args->cond_lock); 06490 ast_cond_signal(args->cond); 06491 ast_mutex_unlock(args->cond_lock); 06492 06493 if (conf) { 06494 conf_run(trunk_ref->trunk->chan, conf, &conf_flags, NULL); 06495 dispose_conf(conf); 06496 conf = NULL; 06497 } 06498 06499 /* If the trunk is going away, it is definitely now IDLE. */ 06500 sla_change_trunk_state(trunk_ref->trunk, SLA_TRUNK_STATE_IDLE, ALL_TRUNK_REFS, NULL); 06501 06502 trunk_ref->trunk->chan = NULL; 06503 trunk_ref->trunk->on_hold = 0; 06504 06505 ast_dial_join(dial); 06506 ast_dial_destroy(dial); 06507 06508 return NULL; 06509 }
static int dispose_conf | ( | struct ast_conference * | conf | ) | [static] |
Decrement reference counts, as incremented by find_conf().
Definition at line 2097 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().
02098 { 02099 int res = 0; 02100 int confno_int = 0; 02101 02102 AST_LIST_LOCK(&confs); 02103 if (ast_atomic_dec_and_test(&conf->refcount)) { 02104 /* Take the conference room number out of an inuse state */ 02105 if ((sscanf(conf->confno, "%4d", &confno_int) == 1) && (confno_int >= 0 && confno_int < 1024)) { 02106 conf_map[confno_int] = 0; 02107 } 02108 conf_free(conf); 02109 res = 1; 02110 } 02111 AST_LIST_UNLOCK(&confs); 02112 02113 return res; 02114 }
static void filename_parse | ( | char * | filename, | |
char * | buffer | |||
) | [static] |
Definition at line 5186 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().
05187 { 05188 char *slash; 05189 if (ast_strlen_zero(filename)) { 05190 ast_log(LOG_WARNING, "No file name was provided for a file save option.\n"); 05191 } else if (filename[0] != '/') { 05192 snprintf(buffer, PATH_MAX, "%s/meetme/%s", ast_config_AST_SPOOL_DIR, filename); 05193 } else { 05194 ast_copy_string(buffer, filename, PATH_MAX); 05195 } 05196 05197 slash = buffer; 05198 if ((slash = strrchr(slash, '/'))) { 05199 *slash = '\0'; 05200 ast_mkdir(buffer, 0777); 05201 *slash = '/'; 05202 } 05203 }
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 4270 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().
04272 { 04273 struct ast_config *cfg; 04274 struct ast_variable *var; 04275 struct ast_flags config_flags = { 0 }; 04276 struct ast_conference *cnf; 04277 04278 AST_DECLARE_APP_ARGS(args, 04279 AST_APP_ARG(confno); 04280 AST_APP_ARG(pin); 04281 AST_APP_ARG(pinadmin); 04282 ); 04283 04284 /* Check first in the conference list */ 04285 ast_debug(1, "The requested confno is '%s'?\n", confno); 04286 AST_LIST_LOCK(&confs); 04287 AST_LIST_TRAVERSE(&confs, cnf, list) { 04288 ast_debug(3, "Does conf %s match %s?\n", confno, cnf->confno); 04289 if (!strcmp(confno, cnf->confno)) 04290 break; 04291 } 04292 if (cnf) { 04293 cnf->refcount += refcount; 04294 } 04295 AST_LIST_UNLOCK(&confs); 04296 04297 if (!cnf) { 04298 if (dynamic) { 04299 /* No need to parse meetme.conf */ 04300 ast_debug(1, "Building dynamic conference '%s'\n", confno); 04301 if (dynamic_pin) { 04302 if (dynamic_pin[0] == 'q') { 04303 /* Query the user to enter a PIN */ 04304 if (ast_app_getdata(chan, "conf-getpin", dynamic_pin, pin_buf_len - 1, 0) < 0) 04305 return NULL; 04306 } 04307 cnf = build_conf(confno, dynamic_pin, "", make, dynamic, refcount, chan, NULL); 04308 } else { 04309 cnf = build_conf(confno, "", "", make, dynamic, refcount, chan, NULL); 04310 } 04311 } else { 04312 /* Check the config */ 04313 cfg = ast_config_load(CONFIG_FILE_NAME, config_flags); 04314 if (!cfg) { 04315 ast_log(LOG_WARNING, "No %s file :(\n", CONFIG_FILE_NAME); 04316 return NULL; 04317 } else if (cfg == CONFIG_STATUS_FILEINVALID) { 04318 ast_log(LOG_ERROR, "Config file " CONFIG_FILE_NAME " is in an invalid format. Aborting.\n"); 04319 return NULL; 04320 } 04321 04322 for (var = ast_variable_browse(cfg, "rooms"); var; var = var->next) { 04323 char parse[MAX_SETTINGS]; 04324 04325 if (strcasecmp(var->name, "conf")) 04326 continue; 04327 04328 ast_copy_string(parse, var->value, sizeof(parse)); 04329 04330 AST_STANDARD_APP_ARGS(args, parse); 04331 ast_debug(3, "Will conf %s match %s?\n", confno, args.confno); 04332 if (!strcasecmp(args.confno, confno)) { 04333 /* Bingo it's a valid conference */ 04334 cnf = build_conf(args.confno, 04335 S_OR(args.pin, ""), 04336 S_OR(args.pinadmin, ""), 04337 make, dynamic, refcount, chan, NULL); 04338 break; 04339 } 04340 } 04341 if (!var) { 04342 ast_debug(1, "%s isn't a valid conference\n", confno); 04343 } 04344 ast_config_destroy(cfg); 04345 } 04346 } else if (dynamic_pin) { 04347 /* Correct for the user selecting 'D' instead of 'd' to have 04348 someone join into a conference that has already been created 04349 with a pin. */ 04350 if (dynamic_pin[0] == 'q') { 04351 dynamic_pin[0] = '\0'; 04352 } 04353 } 04354 04355 if (cnf) { 04356 if (confflags && !cnf->chan && 04357 !ast_test_flag64(confflags, CONFFLAG_QUIET) && 04358 ast_test_flag64(confflags, CONFFLAG_INTROUSER | CONFFLAG_INTROUSERNOREVIEW)) { 04359 ast_log(LOG_WARNING, "No DAHDI channel available for conference, user introduction disabled (is chan_dahdi loaded?)\n"); 04360 ast_clear_flag64(confflags, CONFFLAG_INTROUSER | CONFFLAG_INTROUSERNOREVIEW); 04361 } 04362 04363 if (confflags && !cnf->chan && 04364 ast_test_flag64(confflags, CONFFLAG_RECORDCONF)) { 04365 ast_log(LOG_WARNING, "No DAHDI channel available for conference, conference recording disabled (is chan_dahdi loaded?)\n"); 04366 ast_clear_flag64(confflags, CONFFLAG_RECORDCONF); 04367 } 04368 } 04369 04370 return cnf; 04371 }
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 4082 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().
04084 { 04085 struct ast_variable *var, *origvar; 04086 struct ast_conference *cnf; 04087 04088 *too_early = 0; 04089 04090 /* Check first in the conference list */ 04091 AST_LIST_LOCK(&confs); 04092 AST_LIST_TRAVERSE(&confs, cnf, list) { 04093 if (!strcmp(confno, cnf->confno)) { 04094 break; 04095 } 04096 } 04097 if (cnf) { 04098 cnf->refcount += refcount; 04099 } 04100 AST_LIST_UNLOCK(&confs); 04101 04102 if (!cnf) { 04103 char *pin = NULL, *pinadmin = NULL; /* For temp use */ 04104 int maxusers = 0; 04105 struct timeval now; 04106 char recordingfilename[256] = ""; 04107 char recordingformat[11] = ""; 04108 char currenttime[32] = ""; 04109 char eatime[32] = ""; 04110 char bookid[51] = ""; 04111 char recordingtmp[AST_MAX_EXTENSION] = ""; 04112 char useropts[OPTIONS_LEN + 1] = ""; /* Used for RealTime conferences */ 04113 char adminopts[OPTIONS_LEN + 1] = ""; 04114 struct ast_tm tm, etm; 04115 struct timeval endtime = { .tv_sec = 0 }; 04116 const char *var2; 04117 04118 if (rt_schedule) { 04119 now = ast_tvnow(); 04120 04121 ast_localtime(&now, &tm, NULL); 04122 ast_strftime(currenttime, sizeof(currenttime), DATE_FORMAT, &tm); 04123 04124 ast_debug(1, "Looking for conference %s that starts after %s\n", confno, currenttime); 04125 04126 var = ast_load_realtime("meetme", "confno", 04127 confno, "starttime <= ", currenttime, "endtime >= ", 04128 currenttime, NULL); 04129 04130 if (!var && fuzzystart) { 04131 now = ast_tvnow(); 04132 now.tv_sec += fuzzystart; 04133 04134 ast_localtime(&now, &tm, NULL); 04135 ast_strftime(currenttime, sizeof(currenttime), DATE_FORMAT, &tm); 04136 var = ast_load_realtime("meetme", "confno", 04137 confno, "starttime <= ", currenttime, "endtime >= ", 04138 currenttime, NULL); 04139 } 04140 04141 if (!var && earlyalert) { 04142 now = ast_tvnow(); 04143 now.tv_sec += earlyalert; 04144 ast_localtime(&now, &etm, NULL); 04145 ast_strftime(eatime, sizeof(eatime), DATE_FORMAT, &etm); 04146 var = ast_load_realtime("meetme", "confno", 04147 confno, "starttime <= ", eatime, "endtime >= ", 04148 currenttime, NULL); 04149 if (var) { 04150 *too_early = 1; 04151 } 04152 } 04153 04154 } else { 04155 var = ast_load_realtime("meetme", "confno", confno, NULL); 04156 } 04157 04158 if (!var) { 04159 return NULL; 04160 } 04161 04162 if (rt_schedule && *too_early) { 04163 /* Announce that the caller is early and exit */ 04164 if (!ast_streamfile(chan, "conf-has-not-started", chan->language)) { 04165 ast_waitstream(chan, ""); 04166 } 04167 ast_variables_destroy(var); 04168 return NULL; 04169 } 04170 04171 for (origvar = var; var; var = var->next) { 04172 if (!strcasecmp(var->name, "pin")) { 04173 pin = ast_strdupa(var->value); 04174 } else if (!strcasecmp(var->name, "adminpin")) { 04175 pinadmin = ast_strdupa(var->value); 04176 } else if (!strcasecmp(var->name, "bookId")) { 04177 ast_copy_string(bookid, var->value, sizeof(bookid)); 04178 } else if (!strcasecmp(var->name, "opts")) { 04179 ast_copy_string(useropts, var->value, sizeof(char[OPTIONS_LEN + 1])); 04180 } else if (!strcasecmp(var->name, "maxusers")) { 04181 maxusers = atoi(var->value); 04182 } else if (!strcasecmp(var->name, "adminopts")) { 04183 ast_copy_string(adminopts, var->value, sizeof(char[OPTIONS_LEN + 1])); 04184 } else if (!strcasecmp(var->name, "recordingfilename")) { 04185 ast_copy_string(recordingfilename, var->value, sizeof(recordingfilename)); 04186 } else if (!strcasecmp(var->name, "recordingformat")) { 04187 ast_copy_string(recordingformat, var->value, sizeof(recordingformat)); 04188 } else if (!strcasecmp(var->name, "endtime")) { 04189 struct ast_tm endtime_tm; 04190 ast_strptime(var->value, "%Y-%m-%d %H:%M:%S", &endtime_tm); 04191 endtime = ast_mktime(&endtime_tm, NULL); 04192 } 04193 } 04194 04195 ast_variables_destroy(origvar); 04196 04197 cnf = build_conf(confno, pin ? pin : "", pinadmin ? pinadmin : "", make, dynamic, refcount, chan, NULL); 04198 04199 if (cnf) { 04200 struct ast_flags64 tmp_flags; 04201 04202 cnf->maxusers = maxusers; 04203 cnf->endalert = endalert; 04204 cnf->endtime = endtime.tv_sec; 04205 cnf->useropts = ast_strdup(useropts); 04206 cnf->adminopts = ast_strdup(adminopts); 04207 cnf->bookid = ast_strdup(bookid); 04208 if (!ast_strlen_zero(recordingfilename)) { 04209 cnf->recordingfilename = ast_strdup(recordingfilename); 04210 } 04211 if (!ast_strlen_zero(recordingformat)) { 04212 cnf->recordingformat = ast_strdup(recordingformat); 04213 } 04214 04215 /* Parse the other options into confflags -- need to do this in two 04216 * steps, because the parse_options routine zeroes the buffer. */ 04217 ast_app_parse_options64(meetme_opts, &tmp_flags, optargs, useropts); 04218 ast_copy_flags64(confflags, &tmp_flags, tmp_flags.flags); 04219 04220 if (strchr(cnf->useropts, 'r')) { 04221 if (ast_strlen_zero(recordingfilename)) { /* If the recordingfilename in the database is empty, use the channel definition or use the default. */ 04222 ast_channel_lock(chan); 04223 if ((var2 = pbx_builtin_getvar_helper(chan, "MEETME_RECORDINGFILE"))) { 04224 ast_free(cnf->recordingfilename); 04225 cnf->recordingfilename = ast_strdup(var2); 04226 } 04227 ast_channel_unlock(chan); 04228 if (ast_strlen_zero(cnf->recordingfilename)) { 04229 snprintf(recordingtmp, sizeof(recordingtmp), "meetme-conf-rec-%s-%s", cnf->confno, chan->uniqueid); 04230 ast_free(cnf->recordingfilename); 04231 cnf->recordingfilename = ast_strdup(recordingtmp); 04232 } 04233 } 04234 if (ast_strlen_zero(cnf->recordingformat)) {/* If the recording format is empty, use the wav as default */ 04235 ast_channel_lock(chan); 04236 if ((var2 = pbx_builtin_getvar_helper(chan, "MEETME_RECORDINGFORMAT"))) { 04237 ast_free(cnf->recordingformat); 04238 cnf->recordingformat = ast_strdup(var2); 04239 } 04240 ast_channel_unlock(chan); 04241 if (ast_strlen_zero(cnf->recordingformat)) { 04242 ast_free(cnf->recordingformat); 04243 cnf->recordingformat = ast_strdup("wav"); 04244 } 04245 } 04246 ast_verb(4, "Starting recording of MeetMe Conference %s into file %s.%s.\n", cnf->confno, cnf->recordingfilename, cnf->recordingformat); 04247 } 04248 } 04249 } 04250 04251 if (cnf) { 04252 if (confflags->flags && !cnf->chan && 04253 !ast_test_flag64(confflags, CONFFLAG_QUIET) && 04254 ast_test_flag64(confflags, CONFFLAG_INTROUSER | CONFFLAG_INTROUSERNOREVIEW)) { 04255 ast_log(LOG_WARNING, "No DAHDI channel available for conference, user introduction disabled (is chan_dahdi loaded?)\n"); 04256 ast_clear_flag64(confflags, CONFFLAG_INTROUSER | CONFFLAG_INTROUSERNOREVIEW); 04257 } 04258 04259 if (confflags && !cnf->chan && 04260 ast_test_flag64(confflags, CONFFLAG_RECORDCONF)) { 04261 ast_log(LOG_WARNING, "No DAHDI channel available for conference, conference recording disabled (is chan_dahdi loaded?)\n"); 04262 ast_clear_flag64(confflags, CONFFLAG_RECORDCONF); 04263 } 04264 } 04265 04266 return cnf; 04267 }
static struct ast_conf_user* find_user | ( | struct ast_conference * | conf, | |
const char * | callerident | |||
) | [static, read] |
Definition at line 4744 of file app_meetme.c.
References ao2_find, and ast_conference::usercontainer.
Referenced by admin_exec().
04745 { 04746 struct ast_conf_user *user = NULL; 04747 int cid; 04748 04749 if (conf && callerident && sscanf(callerident, "%30d", &cid) == 1) { 04750 user = ao2_find(conf->usercontainer, &cid, 0); 04751 /* reference decremented later in admin_exec */ 04752 return user; 04753 } 04754 return NULL; 04755 }
static const char* get_announce_filename | ( | enum announcetypes | type | ) | [static] |
Definition at line 2194 of file app_meetme.c.
References CONF_HASJOIN, and CONF_HASLEFT.
Referenced by announce_thread().
02195 { 02196 switch (type) { 02197 case CONF_HASLEFT: 02198 return "conf-hasleft"; 02199 break; 02200 case CONF_HASJOIN: 02201 return "conf-hasjoin"; 02202 break; 02203 default: 02204 return ""; 02205 } 02206 }
static const char* istalking | ( | int | x | ) | [static] |
Definition at line 1006 of file app_meetme.c.
Referenced by meetme_show_cmd().
static int load_config | ( | int | reload | ) | [static] |
Definition at line 7535 of file app_meetme.c.
References load_config_meetme(), and sla_load_config().
Referenced by load_module(), and reload().
07536 { 07537 load_config_meetme(); 07538 return sla_load_config(reload); 07539 }
static void load_config_meetme | ( | void | ) | [static] |
Definition at line 5296 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().
05297 { 05298 struct ast_config *cfg; 05299 struct ast_flags config_flags = { 0 }; 05300 const char *val; 05301 05302 if (!(cfg = ast_config_load(CONFIG_FILE_NAME, config_flags))) { 05303 return; 05304 } else if (cfg == CONFIG_STATUS_FILEINVALID) { 05305 ast_log(LOG_ERROR, "Config file " CONFIG_FILE_NAME " is in an invalid format. Aborting.\n"); 05306 return; 05307 } 05308 05309 audio_buffers = DEFAULT_AUDIO_BUFFERS; 05310 05311 /* Scheduling support is off by default */ 05312 rt_schedule = 0; 05313 fuzzystart = 0; 05314 earlyalert = 0; 05315 endalert = 0; 05316 extendby = 0; 05317 05318 /* Logging of participants defaults to ON for compatibility reasons */ 05319 rt_log_members = 1; 05320 05321 if ((val = ast_variable_retrieve(cfg, "general", "audiobuffers"))) { 05322 if ((sscanf(val, "%30d", &audio_buffers) != 1)) { 05323 ast_log(LOG_WARNING, "audiobuffers setting must be a number, not '%s'\n", val); 05324 audio_buffers = DEFAULT_AUDIO_BUFFERS; 05325 } else if ((audio_buffers < DAHDI_DEFAULT_NUM_BUFS) || (audio_buffers > DAHDI_MAX_NUM_BUFS)) { 05326 ast_log(LOG_WARNING, "audiobuffers setting must be between %d and %d\n", 05327 DAHDI_DEFAULT_NUM_BUFS, DAHDI_MAX_NUM_BUFS); 05328 audio_buffers = DEFAULT_AUDIO_BUFFERS; 05329 } 05330 if (audio_buffers != DEFAULT_AUDIO_BUFFERS) 05331 ast_log(LOG_NOTICE, "Audio buffers per channel set to %d\n", audio_buffers); 05332 } 05333 05334 if ((val = ast_variable_retrieve(cfg, "general", "schedule"))) 05335 rt_schedule = ast_true(val); 05336 if ((val = ast_variable_retrieve(cfg, "general", "logmembercount"))) 05337 rt_log_members = ast_true(val); 05338 if ((val = ast_variable_retrieve(cfg, "general", "fuzzystart"))) { 05339 if ((sscanf(val, "%30d", &fuzzystart) != 1)) { 05340 ast_log(LOG_WARNING, "fuzzystart must be a number, not '%s'\n", val); 05341 fuzzystart = 0; 05342 } 05343 } 05344 if ((val = ast_variable_retrieve(cfg, "general", "earlyalert"))) { 05345 if ((sscanf(val, "%30d", &earlyalert) != 1)) { 05346 ast_log(LOG_WARNING, "earlyalert must be a number, not '%s'\n", val); 05347 earlyalert = 0; 05348 } 05349 } 05350 if ((val = ast_variable_retrieve(cfg, "general", "endalert"))) { 05351 if ((sscanf(val, "%30d", &endalert) != 1)) { 05352 ast_log(LOG_WARNING, "endalert must be a number, not '%s'\n", val); 05353 endalert = 0; 05354 } 05355 } 05356 if ((val = ast_variable_retrieve(cfg, "general", "extendby"))) { 05357 if ((sscanf(val, "%30d", &extendby) != 1)) { 05358 ast_log(LOG_WARNING, "extendby must be a number, not '%s'\n", val); 05359 extendby = 0; 05360 } 05361 } 05362 05363 ast_config_destroy(cfg); 05364 }
static int load_module | ( | void | ) | [static] |
Definition at line 7750 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().
07751 { 07752 int res = 0; 07753 07754 res |= load_config(0); 07755 07756 ast_cli_register_multiple(cli_meetme, ARRAY_LEN(cli_meetme)); 07757 res |= ast_manager_register_xml("MeetmeMute", EVENT_FLAG_CALL, action_meetmemute); 07758 res |= ast_manager_register_xml("MeetmeUnmute", EVENT_FLAG_CALL, action_meetmeunmute); 07759 res |= ast_manager_register_xml("MeetmeList", EVENT_FLAG_REPORTING, action_meetmelist); 07760 res |= ast_register_application_xml(app4, channel_admin_exec); 07761 res |= ast_register_application_xml(app3, admin_exec); 07762 res |= ast_register_application_xml(app2, count_exec); 07763 res |= ast_register_application_xml(app, conf_exec); 07764 res |= ast_register_application_xml(slastation_app, sla_station_exec); 07765 res |= ast_register_application_xml(slatrunk_app, sla_trunk_exec); 07766 07767 #ifdef TEST_FRAMEWORK 07768 AST_TEST_REGISTER(test_meetme_data_provider); 07769 #endif 07770 ast_data_register_multiple(meetme_data_providers, ARRAY_LEN(meetme_data_providers)); 07771 07772 res |= ast_devstate_prov_add("Meetme", meetmestate); 07773 res |= ast_devstate_prov_add("SLA", sla_state); 07774 07775 res |= ast_custom_function_register(&meetme_info_acf); 07776 ast_realtime_require_field("meetme", "confno", RQ_UINTEGER2, 3, "members", RQ_UINTEGER1, 3, NULL); 07777 07778 return res; 07779 }
static char* meetme_cmd_helper | ( | struct ast_cli_args * | a | ) | [static] |
Definition at line 1594 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().
01595 { 01596 /* Process the command */ 01597 struct ast_str *cmdline; 01598 01599 /* Max confno length */ 01600 if (!(cmdline = ast_str_create(MAX_CONFNUM))) { 01601 return CLI_FAILURE; 01602 } 01603 01604 ast_str_set(&cmdline, 0, "%s", a->argv[2]); /* Argv 2: conference number */ 01605 if (strcasestr(a->argv[1], "lock")) { 01606 if (strcasecmp(a->argv[1], "lock") == 0) { 01607 /* Lock */ 01608 ast_str_append(&cmdline, 0, ",L"); 01609 } else { 01610 /* Unlock */ 01611 ast_str_append(&cmdline, 0, ",l"); 01612 } 01613 } else if (strcasestr(a->argv[1], "mute")) { 01614 if (strcasecmp(a->argv[1], "mute") == 0) { 01615 /* Mute */ 01616 if (strcasecmp(a->argv[3], "all") == 0) { 01617 ast_str_append(&cmdline, 0, ",N"); 01618 } else { 01619 ast_str_append(&cmdline, 0, ",M,%s", a->argv[3]); 01620 } 01621 } else { 01622 /* Unmute */ 01623 if (strcasecmp(a->argv[3], "all") == 0) { 01624 ast_str_append(&cmdline, 0, ",n"); 01625 } else { 01626 ast_str_append(&cmdline, 0, ",m,%s", a->argv[3]); 01627 } 01628 } 01629 } else if (strcasecmp(a->argv[1], "kick") == 0) { 01630 if (strcasecmp(a->argv[3], "all") == 0) { 01631 /* Kick all */ 01632 ast_str_append(&cmdline, 0, ",K"); 01633 } else { 01634 /* Kick a single user */ 01635 ast_str_append(&cmdline, 0, ",k,%s", a->argv[3]); 01636 } 01637 } else { 01638 /* 01639 * Should never get here because it is already filtered by the 01640 * callers. 01641 */ 01642 ast_free(cmdline); 01643 return CLI_SHOWUSAGE; 01644 } 01645 01646 ast_debug(1, "Cmdline: %s\n", ast_str_buffer(cmdline)); 01647 01648 admin_exec(NULL, ast_str_buffer(cmdline)); 01649 ast_free(cmdline); 01650 01651 return CLI_SUCCESS; 01652 }
static int meetme_data_provider_get | ( | const struct ast_data_search * | search, | |
struct ast_data * | data_root | |||
) | [static] |
Definition at line 7616 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.
07618 { 07619 struct ast_conference *cnf; 07620 struct ast_data *data_meetme, *data_meetme_users; 07621 07622 AST_LIST_LOCK(&confs); 07623 AST_LIST_TRAVERSE(&confs, cnf, list) { 07624 data_meetme = ast_data_add_node(data_root, "meetme"); 07625 if (!data_meetme) { 07626 continue; 07627 } 07628 07629 ast_data_add_structure(ast_conference, data_meetme, cnf); 07630 07631 if (ao2_container_count(cnf->usercontainer)) { 07632 data_meetme_users = ast_data_add_node(data_meetme, "users"); 07633 if (!data_meetme_users) { 07634 ast_data_remove_node(data_root, data_meetme); 07635 continue; 07636 } 07637 07638 ao2_callback(cnf->usercontainer, OBJ_NODATA, user_add_provider_cb, data_meetme_users); 07639 } 07640 07641 if (!ast_data_search_match(search, data_meetme)) { 07642 ast_data_remove_node(data_root, data_meetme); 07643 } 07644 } 07645 AST_LIST_UNLOCK(&confs); 07646 07647 return 0; 07648 }
static char* meetme_kick_cmd | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 1674 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.
01675 { 01676 switch (cmd) { 01677 case CLI_INIT: 01678 e->command = "meetme kick"; 01679 e->usage = 01680 "Usage: meetme kick <confno> all|<userno>\n" 01681 " Kick a conference or a user in a conference.\n"; 01682 return NULL; 01683 case CLI_GENERATE: 01684 return complete_meetmecmd_mute_kick(a->line, a->word, a->pos, a->n); 01685 } 01686 01687 if (a->argc != 4) { 01688 return CLI_SHOWUSAGE; 01689 } 01690 01691 return meetme_cmd_helper(a); 01692 }
static char* meetme_lock_cmd | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 1654 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.
01655 { 01656 switch (cmd) { 01657 case CLI_INIT: 01658 e->command = "meetme {lock|unlock}"; 01659 e->usage = 01660 "Usage: meetme lock|unlock <confno>\n" 01661 " Lock or unlock a conference to new users.\n"; 01662 return NULL; 01663 case CLI_GENERATE: 01664 return complete_meetmecmd_lock(a->word, a->pos, a->n); 01665 } 01666 01667 if (a->argc != 3) { 01668 return CLI_SHOWUSAGE; 01669 } 01670 01671 return meetme_cmd_helper(a); 01672 }
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, | |||
int | recordingtmp_size | |||
) | [static] |
Definition at line 2736 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().
02739 { 02740 switch (*menu_mode) { 02741 case MENU_DISABLED: 02742 break; 02743 case MENU_NORMAL: 02744 meetme_menu_normal(menu_mode, dtmf, conf, confflags, chan, user); 02745 break; 02746 case MENU_ADMIN: 02747 meetme_menu_admin(menu_mode, dtmf, conf, confflags, chan, user); 02748 /* Admin Menu is capable of branching into another menu, in which case it will reset dtmf and change the menu mode. */ 02749 if (*menu_mode != MENU_ADMIN_EXTENDED || (*dtmf <= 0)) { 02750 break; 02751 } 02752 case MENU_ADMIN_EXTENDED: 02753 meetme_menu_admin_extended(menu_mode, dtmf, conf, confflags, chan, user, 02754 recordingtmp, recordingtmp_size); 02755 break; 02756 } 02757 }
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 2429 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().
02430 { 02431 switch(*dtmf) { 02432 case '1': /* Un/Mute */ 02433 *menu_mode = MENU_DISABLED; 02434 /* for admin, change both admin and use flags */ 02435 if (user->adminflags & (ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED)) { 02436 user->adminflags &= ~(ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED); 02437 } else { 02438 user->adminflags |= (ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED); 02439 } 02440 02441 if (ast_test_flag64(confflags, CONFFLAG_MONITOR) || (user->adminflags & (ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED))) { 02442 if (!ast_streamfile(chan, "conf-muted", chan->language)) { 02443 ast_waitstream(chan, ""); 02444 } 02445 } else { 02446 if (!ast_streamfile(chan, "conf-unmuted", chan->language)) { 02447 ast_waitstream(chan, ""); 02448 } 02449 } 02450 break; 02451 02452 case '2': /* Un/Lock the Conference */ 02453 *menu_mode = MENU_DISABLED; 02454 if (conf->locked) { 02455 conf->locked = 0; 02456 if (!ast_streamfile(chan, "conf-unlockednow", chan->language)) { 02457 ast_waitstream(chan, ""); 02458 } 02459 } else { 02460 conf->locked = 1; 02461 if (!ast_streamfile(chan, "conf-lockednow", chan->language)) { 02462 ast_waitstream(chan, ""); 02463 } 02464 } 02465 break; 02466 02467 case '3': /* Eject last user */ 02468 { 02469 struct ast_conf_user *usr = NULL; 02470 int max_no = 0; 02471 ao2_callback(conf->usercontainer, OBJ_NODATA, user_max_cmp, &max_no); 02472 *menu_mode = MENU_DISABLED; 02473 usr = ao2_find(conf->usercontainer, &max_no, 0); 02474 if ((usr->chan->name == chan->name) || ast_test_flag64(&usr->userflags, CONFFLAG_ADMIN)) { 02475 if (!ast_streamfile(chan, "conf-errormenu", chan->language)) { 02476 ast_waitstream(chan, ""); 02477 } 02478 } else { 02479 usr->adminflags |= ADMINFLAG_KICKME; 02480 } 02481 ao2_ref(usr, -1); 02482 ast_stopstream(chan); 02483 break; 02484 } 02485 02486 case '4': 02487 tweak_listen_volume(user, VOL_DOWN); 02488 break; 02489 02490 case '5': 02491 /* Extend RT conference */ 02492 if (rt_schedule) { 02493 if (!rt_extend_conf(conf->confno)) { 02494 if (!ast_streamfile(chan, "conf-extended", chan->language)) { 02495 ast_waitstream(chan, ""); 02496 } 02497 } else { 02498 if (!ast_streamfile(chan, "conf-nonextended", chan->language)) { 02499 ast_waitstream(chan, ""); 02500 } 02501 } 02502 ast_stopstream(chan); 02503 } 02504 *menu_mode = MENU_DISABLED; 02505 break; 02506 02507 case '6': 02508 tweak_listen_volume(user, VOL_UP); 02509 break; 02510 02511 case '7': 02512 tweak_talk_volume(user, VOL_DOWN); 02513 break; 02514 02515 case '8': 02516 if (!ast_streamfile(chan, "conf-adminmenu-menu8", chan->language)) { 02517 /* 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. */ 02518 *dtmf = ast_waitstream(chan, AST_DIGIT_ANY); 02519 ast_stopstream(chan); 02520 } 02521 *menu_mode = MENU_ADMIN_EXTENDED; 02522 break; 02523 02524 case '9': 02525 tweak_talk_volume(user, VOL_UP); 02526 break; 02527 default: 02528 menu_mode = MENU_DISABLED; 02529 /* Play an error message! */ 02530 if (!ast_streamfile(chan, "conf-errormenu", chan->language)) { 02531 ast_waitstream(chan, ""); 02532 } 02533 break; 02534 } 02535 02536 }
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, | |||
int | recordingtmp_size | |||
) | [static] |
Definition at line 2549 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().
02552 { 02553 int keepplaying; 02554 int playednamerec; 02555 int res; 02556 struct ao2_iterator user_iter; 02557 struct ast_conf_user *usr = NULL; 02558 02559 switch(*dtmf) { 02560 case '1': /* *81 Roll call */ 02561 keepplaying = 1; 02562 playednamerec = 0; 02563 if (conf->users == 1) { 02564 if (keepplaying && !ast_streamfile(chan, "conf-onlyperson", chan->language)) { 02565 res = ast_waitstream(chan, AST_DIGIT_ANY); 02566 ast_stopstream(chan); 02567 if (res > 0) { 02568 keepplaying = 0; 02569 } 02570 } 02571 } else if (conf->users == 2) { 02572 if (keepplaying && !ast_streamfile(chan, "conf-onlyone", chan->language)) { 02573 res = ast_waitstream(chan, AST_DIGIT_ANY); 02574 ast_stopstream(chan); 02575 if (res > 0) { 02576 keepplaying = 0; 02577 } 02578 } 02579 } else { 02580 if (keepplaying && !ast_streamfile(chan, "conf-thereare", chan->language)) { 02581 res = ast_waitstream(chan, AST_DIGIT_ANY); 02582 ast_stopstream(chan); 02583 if (res > 0) { 02584 keepplaying = 0; 02585 } 02586 } 02587 if (keepplaying) { 02588 res = ast_say_number(chan, conf->users - 1, AST_DIGIT_ANY, chan->language, (char *) NULL); 02589 ast_stopstream(chan); 02590 if (res > 0) { 02591 keepplaying = 0; 02592 } 02593 } 02594 if (keepplaying && !ast_streamfile(chan, "conf-otherinparty", chan->language)) { 02595 res = ast_waitstream(chan, AST_DIGIT_ANY); 02596 ast_stopstream(chan); 02597 if (res > 0) { 02598 keepplaying = 0; 02599 } 02600 } 02601 } 02602 user_iter = ao2_iterator_init(conf->usercontainer, 0); 02603 while((usr = ao2_iterator_next(&user_iter))) { 02604 if (ast_fileexists(usr->namerecloc, NULL, NULL)) { 02605 if (keepplaying && !ast_streamfile(chan, usr->namerecloc, chan->language)) { 02606 res = ast_waitstream(chan, AST_DIGIT_ANY); 02607 ast_stopstream(chan); 02608 if (res > 0) { 02609 keepplaying = 0; 02610 } 02611 } 02612 playednamerec = 1; 02613 } 02614 ao2_ref(usr, -1); 02615 } 02616 ao2_iterator_destroy(&user_iter); 02617 if (keepplaying && playednamerec && !ast_streamfile(chan, "conf-roll-callcomplete", chan->language)) { 02618 res = ast_waitstream(chan, AST_DIGIT_ANY); 02619 ast_stopstream(chan); 02620 if (res > 0) { 02621 keepplaying = 0; 02622 } 02623 } 02624 02625 *menu_mode = MENU_DISABLED; 02626 break; 02627 02628 case '2': /* *82 Eject all non-admins */ 02629 if (conf->users == 1) { 02630 if(!ast_streamfile(chan, "conf-errormenu", chan->language)) { 02631 ast_waitstream(chan, ""); 02632 } 02633 } else { 02634 ao2_callback(conf->usercontainer, OBJ_NODATA, user_set_kickme_cb, &conf); 02635 } 02636 ast_stopstream(chan); 02637 *menu_mode = MENU_DISABLED; 02638 break; 02639 02640 case '3': /* *83 (Admin) mute/unmute all non-admins */ 02641 if(conf->gmuted) { 02642 conf->gmuted = 0; 02643 ao2_callback(conf->usercontainer, OBJ_NODATA, user_set_unmuted_cb, &conf); 02644 if (!ast_streamfile(chan, "conf-now-unmuted", chan->language)) { 02645 ast_waitstream(chan, ""); 02646 } 02647 } else { 02648 conf->gmuted = 1; 02649 ao2_callback(conf->usercontainer, OBJ_NODATA, user_set_muted_cb, &conf); 02650 if (!ast_streamfile(chan, "conf-now-muted", chan->language)) { 02651 ast_waitstream(chan, ""); 02652 } 02653 } 02654 ast_stopstream(chan); 02655 *menu_mode = MENU_DISABLED; 02656 break; 02657 02658 case '4': /* *84 Record conference */ 02659 if (conf->recording != MEETME_RECORD_ACTIVE) { 02660 ast_set_flag64(confflags, CONFFLAG_RECORDCONF); 02661 if (!conf->recordingfilename) { 02662 const char *var; 02663 ast_channel_lock(chan); 02664 if ((var = pbx_builtin_getvar_helper(chan, "MEETME_RECORDINGFILE"))) { 02665 conf->recordingfilename = ast_strdup(var); 02666 } 02667 if ((var = pbx_builtin_getvar_helper(chan, "MEETME_RECORDINGFORMAT"))) { 02668 conf->recordingformat = ast_strdup(var); 02669 } 02670 ast_channel_unlock(chan); 02671 if (!conf->recordingfilename) { 02672 snprintf(recordingtmp, recordingtmp_size, "meetme-conf-rec-%s-%s", conf->confno, chan->uniqueid); 02673 conf->recordingfilename = ast_strdup(recordingtmp); 02674 } 02675 if (!conf->recordingformat) { 02676 conf->recordingformat = ast_strdup("wav"); 02677 } 02678 ast_verb(4, "Starting recording of MeetMe Conference %s into file %s.%s.\n", 02679 conf->confno, conf->recordingfilename, conf->recordingformat); 02680 } 02681 02682 ast_mutex_lock(&conf->recordthreadlock); 02683 if ((conf->recordthread == AST_PTHREADT_NULL) && ast_test_flag64(confflags, CONFFLAG_RECORDCONF) && ((conf->lchan = ast_request("DAHDI", AST_FORMAT_SLINEAR, chan, "pseudo", NULL)))) { 02684 struct dahdi_confinfo dahdic; 02685 02686 ast_set_read_format(conf->lchan, AST_FORMAT_SLINEAR); 02687 ast_set_write_format(conf->lchan, AST_FORMAT_SLINEAR); 02688 dahdic.chan = 0; 02689 dahdic.confno = conf->dahdiconf; 02690 dahdic.confmode = DAHDI_CONF_CONFANN | DAHDI_CONF_CONFANNMON; 02691 if (ioctl(conf->lchan->fds[0], DAHDI_SETCONF, &dahdic)) { 02692 ast_log(LOG_WARNING, "Error starting listen channel\n"); 02693 ast_hangup(conf->lchan); 02694 conf->lchan = NULL; 02695 } else { 02696 ast_pthread_create_detached_background(&conf->recordthread, NULL, recordthread, conf); 02697 } 02698 } 02699 ast_mutex_unlock(&conf->recordthreadlock); 02700 if (!ast_streamfile(chan, "conf-now-recording", chan->language)) { 02701 ast_waitstream(chan, ""); 02702 } 02703 } 02704 02705 ast_stopstream(chan); 02706 *menu_mode = MENU_DISABLED; 02707 break; 02708 02709 case '8': /* *88 Exit the menu and return to the conference... without an error message */ 02710 ast_stopstream(chan); 02711 *menu_mode = MENU_DISABLED; 02712 break; 02713 02714 default: 02715 if (!ast_streamfile(chan, "conf-errormenu", chan->language)) { 02716 ast_waitstream(chan, ""); 02717 } 02718 ast_stopstream(chan); 02719 *menu_mode = MENU_DISABLED; 02720 break; 02721 } 02722 }
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 2349 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().
02350 { 02351 switch (*dtmf) { 02352 case '1': /* Un/Mute */ 02353 *menu_mode = MENU_DISABLED; 02354 02355 /* user can only toggle the self-muted state */ 02356 user->adminflags ^= ADMINFLAG_SELFMUTED; 02357 02358 /* they can't override the admin mute state */ 02359 if (ast_test_flag64(confflags, CONFFLAG_MONITOR) || (user->adminflags & (ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED))) { 02360 if (!ast_streamfile(chan, "conf-muted", chan->language)) { 02361 ast_waitstream(chan, ""); 02362 } 02363 } else { 02364 if (!ast_streamfile(chan, "conf-unmuted", chan->language)) { 02365 ast_waitstream(chan, ""); 02366 } 02367 } 02368 break; 02369 02370 case '2': 02371 *menu_mode = MENU_DISABLED; 02372 if (user->adminflags & (ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED)) { 02373 user->adminflags |= ADMINFLAG_T_REQUEST; 02374 } 02375 02376 if (user->adminflags & ADMINFLAG_T_REQUEST) { 02377 if (!ast_streamfile(chan, "beep", chan->language)) { 02378 ast_waitstream(chan, ""); 02379 } 02380 } 02381 break; 02382 02383 case '4': 02384 tweak_listen_volume(user, VOL_DOWN); 02385 break; 02386 case '5': 02387 /* Extend RT conference */ 02388 if (rt_schedule) { 02389 rt_extend_conf(conf->confno); 02390 } 02391 *menu_mode = MENU_DISABLED; 02392 break; 02393 02394 case '6': 02395 tweak_listen_volume(user, VOL_UP); 02396 break; 02397 02398 case '7': 02399 tweak_talk_volume(user, VOL_DOWN); 02400 break; 02401 02402 case '8': 02403 *menu_mode = MENU_DISABLED; 02404 break; 02405 02406 case '9': 02407 tweak_talk_volume(user, VOL_UP); 02408 break; 02409 02410 default: 02411 *menu_mode = MENU_DISABLED; 02412 if (!ast_streamfile(chan, "conf-errormenu", chan->language)) { 02413 ast_waitstream(chan, ""); 02414 } 02415 break; 02416 } 02417 }
static char* meetme_mute_cmd | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 1694 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.
01695 { 01696 switch (cmd) { 01697 case CLI_INIT: 01698 e->command = "meetme {mute|unmute}"; 01699 e->usage = 01700 "Usage: meetme mute|unmute <confno> all|<userno>\n" 01701 " Mute or unmute a conference or a user in a conference.\n"; 01702 return NULL; 01703 case CLI_GENERATE: 01704 return complete_meetmecmd_mute_kick(a->line, a->word, a->pos, a->n); 01705 } 01706 01707 if (a->argc != 4) { 01708 return CLI_SHOWUSAGE; 01709 } 01710 01711 return meetme_cmd_helper(a); 01712 }
static char* meetme_show_cmd | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 1451 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.
01452 { 01453 /* Process the command */ 01454 struct ast_conf_user *user; 01455 struct ast_conference *cnf; 01456 int hr, min, sec; 01457 int total = 0; 01458 time_t now; 01459 #define MC_HEADER_FORMAT "%-14s %-14s %-10s %-8s %-8s %-6s\n" 01460 #define MC_DATA_FORMAT "%-12.12s %4.4d %4.4s %02d:%02d:%02d %-8s %-6s\n" 01461 01462 switch (cmd) { 01463 case CLI_INIT: 01464 e->command = "meetme list"; 01465 e->usage = 01466 "Usage: meetme list [<confno>] [" STR_CONCISE "]\n" 01467 " List all conferences or a specific conference.\n"; 01468 return NULL; 01469 case CLI_GENERATE: 01470 return complete_meetmecmd_list(a->line, a->word, a->pos, a->n); 01471 } 01472 01473 if (a->argc == 2 || (a->argc == 3 && !strcasecmp(a->argv[2], STR_CONCISE))) { 01474 /* List all the conferences */ 01475 int concise = (a->argc == 3); 01476 struct ast_str *marked_users; 01477 01478 if (!(marked_users = ast_str_create(30))) { 01479 return CLI_FAILURE; 01480 } 01481 01482 now = time(NULL); 01483 AST_LIST_LOCK(&confs); 01484 if (AST_LIST_EMPTY(&confs)) { 01485 if (!concise) { 01486 ast_cli(a->fd, "No active MeetMe conferences.\n"); 01487 } 01488 AST_LIST_UNLOCK(&confs); 01489 ast_free(marked_users); 01490 return CLI_SUCCESS; 01491 } 01492 if (!concise) { 01493 ast_cli(a->fd, MC_HEADER_FORMAT, "Conf Num", "Parties", "Marked", "Activity", "Creation", "Locked"); 01494 } 01495 AST_LIST_TRAVERSE(&confs, cnf, list) { 01496 hr = (now - cnf->start) / 3600; 01497 min = ((now - cnf->start) % 3600) / 60; 01498 sec = (now - cnf->start) % 60; 01499 if (!concise) { 01500 if (cnf->markedusers == 0) { 01501 ast_str_set(&marked_users, 0, "N/A "); 01502 } else { 01503 ast_str_set(&marked_users, 0, "%4.4d", cnf->markedusers); 01504 } 01505 ast_cli(a->fd, MC_DATA_FORMAT, cnf->confno, cnf->users, 01506 ast_str_buffer(marked_users), hr, min, sec, 01507 cnf->isdynamic ? "Dynamic" : "Static", cnf->locked ? "Yes" : "No"); 01508 } else { 01509 ast_cli(a->fd, "%s!%d!%d!%02d:%02d:%02d!%d!%d\n", 01510 cnf->confno, 01511 cnf->users, 01512 cnf->markedusers, 01513 hr, min, sec, 01514 cnf->isdynamic, 01515 cnf->locked); 01516 } 01517 01518 total += cnf->users; 01519 } 01520 AST_LIST_UNLOCK(&confs); 01521 if (!concise) { 01522 ast_cli(a->fd, "* Total number of MeetMe users: %d\n", total); 01523 } 01524 ast_free(marked_users); 01525 return CLI_SUCCESS; 01526 } 01527 if (a->argc == 3 || (a->argc == 4 && !strcasecmp(a->argv[3], STR_CONCISE))) { 01528 struct ao2_iterator user_iter; 01529 int concise = (a->argc == 4); 01530 01531 /* List all the users in a conference */ 01532 if (AST_LIST_EMPTY(&confs)) { 01533 if (!concise) { 01534 ast_cli(a->fd, "No active MeetMe conferences.\n"); 01535 } 01536 return CLI_SUCCESS; 01537 } 01538 /* Find the right conference */ 01539 AST_LIST_LOCK(&confs); 01540 AST_LIST_TRAVERSE(&confs, cnf, list) { 01541 if (strcmp(cnf->confno, a->argv[2]) == 0) { 01542 break; 01543 } 01544 } 01545 if (!cnf) { 01546 if (!concise) 01547 ast_cli(a->fd, "No such conference: %s.\n", a->argv[2]); 01548 AST_LIST_UNLOCK(&confs); 01549 return CLI_SUCCESS; 01550 } 01551 /* Show all the users */ 01552 time(&now); 01553 user_iter = ao2_iterator_init(cnf->usercontainer, 0); 01554 while((user = ao2_iterator_next(&user_iter))) { 01555 hr = (now - user->jointime) / 3600; 01556 min = ((now - user->jointime) % 3600) / 60; 01557 sec = (now - user->jointime) % 60; 01558 if (!concise) { 01559 ast_cli(a->fd, "User #: %-2.2d %12.12s %-20.20s Channel: %s %s %s %s %s %s %02d:%02d:%02d\n", 01560 user->user_no, 01561 S_COR(user->chan->caller.id.number.valid, user->chan->caller.id.number.str, "<unknown>"), 01562 S_COR(user->chan->caller.id.name.valid, user->chan->caller.id.name.str, "<no name>"), 01563 user->chan->name, 01564 ast_test_flag64(&user->userflags, CONFFLAG_ADMIN) ? "(Admin)" : "", 01565 ast_test_flag64(&user->userflags, CONFFLAG_MONITOR) ? "(Listen only)" : "", 01566 user->adminflags & ADMINFLAG_MUTED ? "(Admin Muted)" : user->adminflags & ADMINFLAG_SELFMUTED ? "(Muted)" : "", 01567 user->adminflags & ADMINFLAG_T_REQUEST ? "(Request to Talk)" : "", 01568 istalking(user->talking), hr, min, sec); 01569 } else { 01570 ast_cli(a->fd, "%d!%s!%s!%s!%s!%s!%s!%s!%d!%02d:%02d:%02d\n", 01571 user->user_no, 01572 S_COR(user->chan->caller.id.number.valid, user->chan->caller.id.number.str, ""), 01573 S_COR(user->chan->caller.id.name.valid, user->chan->caller.id.name.str, ""), 01574 user->chan->name, 01575 ast_test_flag64(&user->userflags, CONFFLAG_ADMIN) ? "1" : "", 01576 ast_test_flag64(&user->userflags, CONFFLAG_MONITOR) ? "1" : "", 01577 user->adminflags & (ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED) ? "1" : "", 01578 user->adminflags & ADMINFLAG_T_REQUEST ? "1" : "", 01579 user->talking, hr, min, sec); 01580 } 01581 ao2_ref(user, -1); 01582 } 01583 ao2_iterator_destroy(&user_iter); 01584 if (!concise) { 01585 ast_cli(a->fd, "%d users in that conference.\n", cnf->users); 01586 } 01587 AST_LIST_UNLOCK(&confs); 01588 return CLI_SUCCESS; 01589 } 01590 return CLI_SHOWUSAGE; 01591 }
static int meetmemute | ( | struct mansession * | s, | |
const struct message * | m, | |||
int | mute | |||
) | [static] |
Definition at line 5035 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().
05036 { 05037 struct ast_conference *conf; 05038 struct ast_conf_user *user; 05039 const char *confid = astman_get_header(m, "Meetme"); 05040 char *userid = ast_strdupa(astman_get_header(m, "Usernum")); 05041 int userno; 05042 05043 if (ast_strlen_zero(confid)) { 05044 astman_send_error(s, m, "Meetme conference not specified"); 05045 return 0; 05046 } 05047 05048 if (ast_strlen_zero(userid)) { 05049 astman_send_error(s, m, "Meetme user number not specified"); 05050 return 0; 05051 } 05052 05053 userno = strtoul(userid, &userid, 10); 05054 05055 if (*userid) { 05056 astman_send_error(s, m, "Invalid user number"); 05057 return 0; 05058 } 05059 05060 /* Look in the conference list */ 05061 AST_LIST_LOCK(&confs); 05062 AST_LIST_TRAVERSE(&confs, conf, list) { 05063 if (!strcmp(confid, conf->confno)) 05064 break; 05065 } 05066 05067 if (!conf) { 05068 AST_LIST_UNLOCK(&confs); 05069 astman_send_error(s, m, "Meetme conference does not exist"); 05070 return 0; 05071 } 05072 05073 user = ao2_find(conf->usercontainer, &userno, 0); 05074 05075 if (!user) { 05076 AST_LIST_UNLOCK(&confs); 05077 astman_send_error(s, m, "User number not found"); 05078 return 0; 05079 } 05080 05081 if (mute) 05082 user->adminflags |= ADMINFLAG_MUTED; /* request user muting */ 05083 else 05084 user->adminflags &= ~(ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED | ADMINFLAG_T_REQUEST); /* request user unmuting */ 05085 05086 AST_LIST_UNLOCK(&confs); 05087 05088 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); 05089 05090 ao2_ref(user, -1); 05091 astman_send_ack(s, m, mute ? "User muted" : "User unmuted"); 05092 return 0; 05093 }
static enum ast_device_state meetmestate | ( | const char * | data | ) | [static] |
Callback for devicestate providers.
Definition at line 5274 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().
05275 { 05276 struct ast_conference *conf; 05277 05278 /* Find conference */ 05279 AST_LIST_LOCK(&confs); 05280 AST_LIST_TRAVERSE(&confs, conf, list) { 05281 if (!strcmp(data, conf->confno)) 05282 break; 05283 } 05284 AST_LIST_UNLOCK(&confs); 05285 if (!conf) 05286 return AST_DEVICE_INVALID; 05287 05288 05289 /* SKREP to fill */ 05290 if (!conf->users) 05291 return AST_DEVICE_NOT_INUSE; 05292 05293 return AST_DEVICE_INUSE; 05294 }
static struct sla_ringing_trunk* queue_ringing_trunk | ( | struct sla_trunk * | trunk | ) | [static, read] |
Definition at line 6705 of file app_meetme.c.
References ALL_TRUNK_REFS, ao2_ref, 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().
06706 { 06707 struct sla_ringing_trunk *ringing_trunk; 06708 06709 if (!(ringing_trunk = ast_calloc(1, sizeof(*ringing_trunk)))) { 06710 return NULL; 06711 } 06712 06713 ao2_ref(trunk, 1); 06714 ringing_trunk->trunk = trunk; 06715 ringing_trunk->ring_begin = ast_tvnow(); 06716 06717 sla_change_trunk_state(trunk, SLA_TRUNK_STATE_RINGING, ALL_TRUNK_REFS, NULL); 06718 06719 ast_mutex_lock(&sla.lock); 06720 AST_LIST_INSERT_HEAD(&sla.ringing_trunks, ringing_trunk, entry); 06721 ast_mutex_unlock(&sla.lock); 06722 06723 sla_queue_event(SLA_EVENT_RINGING_TRUNK); 06724 06725 return ringing_trunk; 06726 }
static void * recordthread | ( | void * | args | ) | [static] |
Definition at line 5205 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.
05206 { 05207 struct ast_conference *cnf = args; 05208 struct ast_frame *f = NULL; 05209 int flags; 05210 struct ast_filestream *s = NULL; 05211 int res = 0; 05212 int x; 05213 const char *oldrecordingfilename = NULL; 05214 char filename_buffer[PATH_MAX]; 05215 05216 if (!cnf || !cnf->lchan) { 05217 pthread_exit(0); 05218 } 05219 05220 filename_buffer[0] = '\0'; 05221 filename_parse(cnf->recordingfilename, filename_buffer); 05222 05223 ast_stopstream(cnf->lchan); 05224 flags = O_CREAT | O_TRUNC | O_WRONLY; 05225 05226 05227 cnf->recording = MEETME_RECORD_ACTIVE; 05228 while (ast_waitfor(cnf->lchan, -1) > -1) { 05229 if (cnf->recording == MEETME_RECORD_TERMINATE) { 05230 AST_LIST_LOCK(&confs); 05231 AST_LIST_UNLOCK(&confs); 05232 break; 05233 } 05234 if (!s && !(ast_strlen_zero(filename_buffer)) && (filename_buffer != oldrecordingfilename)) { 05235 s = ast_writefile(filename_buffer, cnf->recordingformat, NULL, flags, 0, AST_FILE_MODE); 05236 oldrecordingfilename = filename_buffer; 05237 } 05238 05239 f = ast_read(cnf->lchan); 05240 if (!f) { 05241 res = -1; 05242 break; 05243 } 05244 if (f->frametype == AST_FRAME_VOICE) { 05245 ast_mutex_lock(&cnf->listenlock); 05246 for (x = 0; x < AST_FRAME_BITS; x++) { 05247 /* Free any translations that have occured */ 05248 if (cnf->transframe[x]) { 05249 ast_frfree(cnf->transframe[x]); 05250 cnf->transframe[x] = NULL; 05251 } 05252 } 05253 if (cnf->origframe) 05254 ast_frfree(cnf->origframe); 05255 cnf->origframe = ast_frdup(f); 05256 ast_mutex_unlock(&cnf->listenlock); 05257 if (s) 05258 res = ast_writestream(s, f); 05259 if (res) { 05260 ast_frfree(f); 05261 break; 05262 } 05263 } 05264 ast_frfree(f); 05265 } 05266 cnf->recording = MEETME_RECORD_OFF; 05267 if (s) 05268 ast_closestream(s); 05269 05270 pthread_exit(0); 05271 }
static int reload | ( | void | ) | [static] |
Definition at line 7781 of file app_meetme.c.
References ast_unload_realtime(), and load_config().
07782 { 07783 ast_unload_realtime("meetme"); 07784 return load_config(1); 07785 }
static void reset_volumes | ( | struct ast_conf_user * | user | ) | [static] |
Definition at line 1126 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().
01127 { 01128 signed char zero_volume = 0; 01129 01130 ast_channel_setoption(user->chan, AST_OPTION_TXGAIN, &zero_volume, sizeof(zero_volume), 0); 01131 ast_channel_setoption(user->chan, AST_OPTION_RXGAIN, &zero_volume, sizeof(zero_volume), 0); 01132 }
static int rt_extend_conf | ( | const char * | confno | ) | [static] |
Definition at line 2116 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().
02117 { 02118 char currenttime[32]; 02119 char endtime[32]; 02120 struct timeval now; 02121 struct ast_tm tm; 02122 struct ast_variable *var, *orig_var; 02123 char bookid[51]; 02124 02125 if (!extendby) { 02126 return 0; 02127 } 02128 02129 now = ast_tvnow(); 02130 02131 ast_localtime(&now, &tm, NULL); 02132 ast_strftime(currenttime, sizeof(currenttime), DATE_FORMAT, &tm); 02133 02134 var = ast_load_realtime("meetme", "confno", 02135 confno, "startTime<= ", currenttime, 02136 "endtime>= ", currenttime, NULL); 02137 02138 orig_var = var; 02139 02140 /* Identify the specific RealTime conference */ 02141 while (var) { 02142 if (!strcasecmp(var->name, "bookid")) { 02143 ast_copy_string(bookid, var->value, sizeof(bookid)); 02144 } 02145 if (!strcasecmp(var->name, "endtime")) { 02146 ast_copy_string(endtime, var->value, sizeof(endtime)); 02147 } 02148 02149 var = var->next; 02150 } 02151 ast_variables_destroy(orig_var); 02152 02153 ast_strptime(endtime, DATE_FORMAT, &tm); 02154 now = ast_mktime(&tm, NULL); 02155 02156 now.tv_sec += extendby; 02157 02158 ast_localtime(&now, &tm, NULL); 02159 ast_strftime(currenttime, sizeof(currenttime), DATE_FORMAT, &tm); 02160 strcat(currenttime, "0"); /* Seconds needs to be 00 */ 02161 02162 var = ast_load_realtime("meetme", "confno", 02163 confno, "startTime<= ", currenttime, 02164 "endtime>= ", currenttime, NULL); 02165 02166 /* If there is no conflict with extending the conference, update the DB */ 02167 if (!var) { 02168 ast_debug(3, "Trying to update the endtime of Conference %s to %s\n", confno, currenttime); 02169 ast_update_realtime("meetme", "bookid", bookid, "endtime", currenttime, NULL); 02170 return 0; 02171 02172 } 02173 02174 ast_variables_destroy(var); 02175 return -1; 02176 }
static void* run_station | ( | void * | data | ) | [static] |
Definition at line 5591 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(), RAII_VAR, 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().
05592 { 05593 RAII_VAR(struct sla_station *, station, NULL, unref_obj); 05594 RAII_VAR(struct sla_trunk_ref *, trunk_ref, NULL, unref_obj); 05595 struct ast_str *conf_name = ast_str_create(16); 05596 struct ast_flags64 conf_flags = { 0 }; 05597 struct ast_conference *conf; 05598 05599 { 05600 struct run_station_args *args = data; 05601 station = args->station; 05602 trunk_ref = args->trunk_ref; 05603 ast_mutex_lock(args->cond_lock); 05604 ast_cond_signal(args->cond); 05605 ast_mutex_unlock(args->cond_lock); 05606 /* args is no longer valid here. */ 05607 } 05608 05609 ast_atomic_fetchadd_int((int *) &trunk_ref->trunk->active_stations, 1); 05610 ast_str_set(&conf_name, 0, "SLA_%s", trunk_ref->trunk->name); 05611 ast_set_flag64(&conf_flags, 05612 CONFFLAG_QUIET | CONFFLAG_MARKEDEXIT | CONFFLAG_PASS_DTMF | CONFFLAG_SLA_STATION); 05613 answer_trunk_chan(trunk_ref->chan); 05614 conf = build_conf(ast_str_buffer(conf_name), "", "", 0, 0, 1, trunk_ref->chan, NULL); 05615 if (conf) { 05616 conf_run(trunk_ref->chan, conf, &conf_flags, NULL); 05617 dispose_conf(conf); 05618 conf = NULL; 05619 } 05620 trunk_ref->chan = NULL; 05621 if (ast_atomic_dec_and_test((int *) &trunk_ref->trunk->active_stations) && 05622 trunk_ref->state != SLA_TRUNK_STATE_ONHOLD_BYME) { 05623 ast_str_append(&conf_name, 0, ",K"); 05624 admin_exec(NULL, ast_str_buffer(conf_name)); 05625 trunk_ref->trunk->hold_stations = 0; 05626 sla_change_trunk_state(trunk_ref->trunk, SLA_TRUNK_STATE_IDLE, ALL_TRUNK_REFS, NULL); 05627 } 05628 05629 ast_dial_join(station->dial); 05630 ast_dial_destroy(station->dial); 05631 station->dial = NULL; 05632 ast_free(conf_name); 05633 05634 return NULL; 05635 }
static void send_talking_event | ( | struct ast_channel * | chan, | |
struct ast_conference * | conf, | |||
struct ast_conf_user * | user, | |||
int | talking | |||
) | [static] |
Definition at line 2270 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().
02271 { 02272 ast_manager_event(chan, EVENT_FLAG_CALL, "MeetmeTalking", 02273 "Channel: %s\r\n" 02274 "Uniqueid: %s\r\n" 02275 "Meetme: %s\r\n" 02276 "Usernum: %d\r\n" 02277 "Status: %s\r\n", 02278 chan->name, chan->uniqueid, conf->confno, user->user_no, talking ? "on" : "off"); 02279 }
static int set_listen_volume | ( | struct ast_conf_user * | user, | |
int | volume | |||
) | [static] |
Definition at line 1055 of file app_meetme.c.
References ast_channel_setoption(), AST_OPTION_TXGAIN, and ast_conf_user::chan.
Referenced by tweak_listen_volume().
01056 { 01057 char gain_adjust; 01058 01059 /* attempt to make the adjustment in the channel driver; 01060 if successful, don't adjust in the frame reading routine 01061 */ 01062 gain_adjust = gain_map[volume + 5]; 01063 01064 return ast_channel_setoption(user->chan, AST_OPTION_TXGAIN, &gain_adjust, sizeof(gain_adjust), 0); 01065 }
static int set_talk_volume | ( | struct ast_conf_user * | user, | |
int | volume | |||
) | [static] |
Definition at line 1043 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().
01044 { 01045 char gain_adjust; 01046 01047 /* attempt to make the adjustment in the channel driver; 01048 if successful, don't adjust in the frame reading routine 01049 */ 01050 gain_adjust = gain_map[volume + 5]; 01051 01052 return ast_channel_setoption(user->chan, AST_OPTION_RXGAIN, &gain_adjust, sizeof(gain_adjust), 0); 01053 }
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 2281 of file app_meetme.c.
References send_talking_event(), and ast_conf_user::talking.
Referenced by conf_run().
02282 { 02283 int last_talking = user->talking; 02284 if (last_talking == talking) 02285 return; 02286 02287 user->talking = talking; 02288 02289 if (monitor) { 02290 /* Check if talking state changed. Take care of -1 which means unmonitored */ 02291 int was_talking = (last_talking > 0); 02292 int now_talking = (talking > 0); 02293 if (was_talking != now_talking) { 02294 send_talking_event(chan, conf, user, now_talking); 02295 } 02296 } 02297 }
static void sla_add_trunk_to_station | ( | struct sla_station * | station, | |
struct ast_variable * | var | |||
) | [static] |
Definition at line 7100 of file app_meetme.c.
References ao2_lock, ao2_ref, ao2_unlock, ast_atomic_fetchadd_int(), AST_LIST_INSERT_TAIL, AST_LIST_TRAVERSE, ast_log(), ast_strdupa, create_trunk_ref(), LOG_ERROR, LOG_WARNING, name, RAII_VAR, sla_create_station_ref(), sla_find_trunk(), SLA_TRUNK_STATE_IDLE, value, and ast_variable::value.
Referenced by sla_build_station().
07101 { 07102 RAII_VAR(struct sla_trunk *, trunk, NULL, unref_obj); 07103 struct sla_trunk_ref *trunk_ref = NULL; 07104 struct sla_station_ref *station_ref; 07105 char *trunk_name, *options, *cur; 07106 int existing_trunk_ref = 0; 07107 int existing_station_ref = 0; 07108 07109 options = ast_strdupa(var->value); 07110 trunk_name = strsep(&options, ","); 07111 07112 trunk = sla_find_trunk(trunk_name); 07113 if (!trunk) { 07114 ast_log(LOG_ERROR, "Trunk '%s' not found!\n", var->value); 07115 return; 07116 } 07117 07118 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) { 07119 if (trunk_ref->trunk == trunk) { 07120 trunk_ref->mark = 0; 07121 existing_trunk_ref = 1; 07122 break; 07123 } 07124 } 07125 07126 if (!trunk_ref && !(trunk_ref = create_trunk_ref(trunk))) { 07127 return; 07128 } 07129 07130 trunk_ref->state = SLA_TRUNK_STATE_IDLE; 07131 07132 while ((cur = strsep(&options, ","))) { 07133 char *name, *value = cur; 07134 name = strsep(&value, "="); 07135 if (!strcasecmp(name, "ringtimeout")) { 07136 if (sscanf(value, "%30u", &trunk_ref->ring_timeout) != 1) { 07137 ast_log(LOG_WARNING, "Invalid ringtimeout value '%s' for " 07138 "trunk '%s' on station '%s'\n", value, trunk->name, station->name); 07139 trunk_ref->ring_timeout = 0; 07140 } 07141 } else if (!strcasecmp(name, "ringdelay")) { 07142 if (sscanf(value, "%30u", &trunk_ref->ring_delay) != 1) { 07143 ast_log(LOG_WARNING, "Invalid ringdelay value '%s' for " 07144 "trunk '%s' on station '%s'\n", value, trunk->name, station->name); 07145 trunk_ref->ring_delay = 0; 07146 } 07147 } else { 07148 ast_log(LOG_WARNING, "Invalid option '%s' for " 07149 "trunk '%s' on station '%s'\n", name, trunk->name, station->name); 07150 } 07151 } 07152 07153 AST_LIST_TRAVERSE(&trunk->stations, station_ref, entry) { 07154 if (station_ref->station == station) { 07155 station_ref->mark = 0; 07156 existing_station_ref = 1; 07157 break; 07158 } 07159 } 07160 07161 if (!station_ref && !(station_ref = sla_create_station_ref(station))) { 07162 if (!existing_trunk_ref) { 07163 ao2_ref(trunk_ref, -1); 07164 } else { 07165 trunk_ref->mark = 1; 07166 } 07167 return; 07168 } 07169 07170 if (!existing_station_ref) { 07171 ao2_lock(trunk); 07172 AST_LIST_INSERT_TAIL(&trunk->stations, station_ref, entry); 07173 ast_atomic_fetchadd_int((int *) &trunk->num_stations, 1); 07174 ao2_unlock(trunk); 07175 } 07176 07177 if (!existing_trunk_ref) { 07178 ao2_lock(station); 07179 AST_LIST_INSERT_TAIL(&station->trunks, trunk_ref, entry); 07180 ao2_unlock(station); 07181 } 07182 }
static int sla_build_station | ( | struct ast_config * | cfg, | |
const char * | cat | |||
) | [static] |
Definition at line 7184 of file app_meetme.c.
References ao2_alloc, ao2_link, ao2_lock, ao2_unlock, ast_add_extension2(), ast_context_find_or_create(), ast_free_ptr(), AST_LIST_TRAVERSE, ast_log(), AST_MAX_APP, AST_MAX_EXTENSION, ast_strdup, ast_string_field_init, ast_string_field_set, ast_strlen_zero(), ast_variable_browse(), ast_variable_retrieve(), context, exten, ast_variable::lineno, LOG_ERROR, LOG_WARNING, ast_variable::name, name, ast_variable::next, PRIORITY_HINT, RAII_VAR, sla_add_trunk_to_station(), SLA_CONFIG_FILE, sla_find_station(), SLA_HOLD_OPEN, SLA_HOLD_PRIVATE, sla_registrar, sla_station_destructor(), sla_stations, ast_variable::value, and var.
Referenced by sla_load_config().
07185 { 07186 RAII_VAR(struct sla_station *, station, NULL, unref_obj); 07187 struct ast_variable *var; 07188 const char *dev; 07189 int existing_station = 0; 07190 07191 if (!(dev = ast_variable_retrieve(cfg, cat, "device"))) { 07192 ast_log(LOG_ERROR, "SLA Station '%s' defined with no device!\n", cat); 07193 return -1; 07194 } 07195 07196 if ((station = sla_find_station(cat))) { 07197 station->mark = 0; 07198 existing_station = 1; 07199 } else if ((station = ao2_alloc(sizeof(*station), sla_station_destructor))) { 07200 if (ast_string_field_init(station, 32)) { 07201 return -1; 07202 } 07203 ast_string_field_set(station, name, cat); 07204 } else { 07205 return -1; 07206 } 07207 07208 ao2_lock(station); 07209 07210 ast_string_field_set(station, device, dev); 07211 07212 for (var = ast_variable_browse(cfg, cat); var; var = var->next) { 07213 if (!strcasecmp(var->name, "trunk")) { 07214 ao2_unlock(station); 07215 sla_add_trunk_to_station(station, var); 07216 ao2_lock(station); 07217 } else if (!strcasecmp(var->name, "autocontext")) { 07218 ast_string_field_set(station, autocontext, var->value); 07219 } else if (!strcasecmp(var->name, "ringtimeout")) { 07220 if (sscanf(var->value, "%30u", &station->ring_timeout) != 1) { 07221 ast_log(LOG_WARNING, "Invalid ringtimeout '%s' specified for station '%s'\n", 07222 var->value, station->name); 07223 station->ring_timeout = 0; 07224 } 07225 } else if (!strcasecmp(var->name, "ringdelay")) { 07226 if (sscanf(var->value, "%30u", &station->ring_delay) != 1) { 07227 ast_log(LOG_WARNING, "Invalid ringdelay '%s' specified for station '%s'\n", 07228 var->value, station->name); 07229 station->ring_delay = 0; 07230 } 07231 } else if (!strcasecmp(var->name, "hold")) { 07232 if (!strcasecmp(var->value, "private")) 07233 station->hold_access = SLA_HOLD_PRIVATE; 07234 else if (!strcasecmp(var->value, "open")) 07235 station->hold_access = SLA_HOLD_OPEN; 07236 else { 07237 ast_log(LOG_WARNING, "Invalid value '%s' for hold on station %s\n", 07238 var->value, station->name); 07239 } 07240 07241 } else if (strcasecmp(var->name, "type") && strcasecmp(var->name, "device")) { 07242 ast_log(LOG_ERROR, "Invalid option '%s' specified at line %d of %s!\n", 07243 var->name, var->lineno, SLA_CONFIG_FILE); 07244 } 07245 } 07246 07247 ao2_unlock(station); 07248 07249 if (!ast_strlen_zero(station->autocontext)) { 07250 struct ast_context *context; 07251 struct sla_trunk_ref *trunk_ref; 07252 context = ast_context_find_or_create(NULL, NULL, station->autocontext, sla_registrar); 07253 if (!context) { 07254 ast_log(LOG_ERROR, "Failed to automatically find or create " 07255 "context '%s' for SLA!\n", station->autocontext); 07256 return -1; 07257 } 07258 /* The extension for when the handset goes off-hook. 07259 * exten => station1,1,SLAStation(station1) */ 07260 if (ast_add_extension2(context, 0 /* don't replace */, station->name, 1, 07261 NULL, NULL, slastation_app, ast_strdup(station->name), ast_free_ptr, sla_registrar)) { 07262 ast_log(LOG_ERROR, "Failed to automatically create extension " 07263 "for trunk '%s'!\n", station->name); 07264 return -1; 07265 } 07266 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) { 07267 char exten[AST_MAX_EXTENSION]; 07268 char hint[AST_MAX_APP]; 07269 snprintf(exten, sizeof(exten), "%s_%s", station->name, trunk_ref->trunk->name); 07270 snprintf(hint, sizeof(hint), "SLA:%s", exten); 07271 /* Extension for this line button 07272 * exten => station1_line1,1,SLAStation(station1_line1) */ 07273 if (ast_add_extension2(context, 0 /* don't replace */, exten, 1, 07274 NULL, NULL, slastation_app, ast_strdup(exten), ast_free_ptr, sla_registrar)) { 07275 ast_log(LOG_ERROR, "Failed to automatically create extension " 07276 "for trunk '%s'!\n", station->name); 07277 return -1; 07278 } 07279 /* Hint for this line button 07280 * exten => station1_line1,hint,SLA:station1_line1 */ 07281 if (ast_add_extension2(context, 0 /* don't replace */, exten, PRIORITY_HINT, 07282 NULL, NULL, hint, NULL, NULL, sla_registrar)) { 07283 ast_log(LOG_ERROR, "Failed to automatically create hint " 07284 "for trunk '%s'!\n", station->name); 07285 return -1; 07286 } 07287 } 07288 } 07289 07290 if (!existing_station) { 07291 ao2_link(sla_stations, station); 07292 } 07293 07294 return 0; 07295 }
static int sla_build_trunk | ( | struct ast_config * | cfg, | |
const char * | cat | |||
) | [static] |
Definition at line 7011 of file app_meetme.c.
References ao2_alloc, ao2_link, ao2_lock, ao2_unlock, ast_add_extension2(), ast_context_find_or_create(), ast_false(), ast_free_ptr(), ast_log(), ast_strdup, ast_string_field_init, ast_string_field_set, ast_strlen_zero(), ast_variable_browse(), ast_variable_retrieve(), context, ast_variable::lineno, LOG_ERROR, LOG_WARNING, ast_variable::name, name, ast_variable::next, RAII_VAR, sla_check_device(), SLA_CONFIG_FILE, sla_find_trunk(), SLA_HOLD_OPEN, SLA_HOLD_PRIVATE, sla_registrar, sla_trunk_destructor(), sla_trunks, ast_variable::value, and var.
Referenced by sla_load_config().
07012 { 07013 RAII_VAR(struct sla_trunk *, trunk, NULL, unref_obj); 07014 struct ast_variable *var; 07015 const char *dev; 07016 int existing_trunk = 0; 07017 07018 if (!(dev = ast_variable_retrieve(cfg, cat, "device"))) { 07019 ast_log(LOG_ERROR, "SLA Trunk '%s' defined with no device!\n", cat); 07020 return -1; 07021 } 07022 07023 if (sla_check_device(dev)) { 07024 ast_log(LOG_ERROR, "SLA Trunk '%s' defined with invalid device '%s'!\n", 07025 cat, dev); 07026 return -1; 07027 } 07028 07029 if ((trunk = sla_find_trunk(cat))) { 07030 trunk->mark = 0; 07031 existing_trunk = 1; 07032 } else if ((trunk = ao2_alloc(sizeof(*trunk), sla_trunk_destructor))) { 07033 if (ast_string_field_init(trunk, 32)) { 07034 return -1; 07035 } 07036 ast_string_field_set(trunk, name, cat); 07037 } else { 07038 return -1; 07039 } 07040 07041 ao2_lock(trunk); 07042 07043 ast_string_field_set(trunk, device, dev); 07044 07045 for (var = ast_variable_browse(cfg, cat); var; var = var->next) { 07046 if (!strcasecmp(var->name, "autocontext")) 07047 ast_string_field_set(trunk, autocontext, var->value); 07048 else if (!strcasecmp(var->name, "ringtimeout")) { 07049 if (sscanf(var->value, "%30u", &trunk->ring_timeout) != 1) { 07050 ast_log(LOG_WARNING, "Invalid ringtimeout '%s' specified for trunk '%s'\n", 07051 var->value, trunk->name); 07052 trunk->ring_timeout = 0; 07053 } 07054 } else if (!strcasecmp(var->name, "barge")) 07055 trunk->barge_disabled = ast_false(var->value); 07056 else if (!strcasecmp(var->name, "hold")) { 07057 if (!strcasecmp(var->value, "private")) 07058 trunk->hold_access = SLA_HOLD_PRIVATE; 07059 else if (!strcasecmp(var->value, "open")) 07060 trunk->hold_access = SLA_HOLD_OPEN; 07061 else { 07062 ast_log(LOG_WARNING, "Invalid value '%s' for hold on trunk %s\n", 07063 var->value, trunk->name); 07064 } 07065 } else if (strcasecmp(var->name, "type") && strcasecmp(var->name, "device")) { 07066 ast_log(LOG_ERROR, "Invalid option '%s' specified at line %d of %s!\n", 07067 var->name, var->lineno, SLA_CONFIG_FILE); 07068 } 07069 } 07070 07071 ao2_unlock(trunk); 07072 07073 if (!ast_strlen_zero(trunk->autocontext)) { 07074 struct ast_context *context; 07075 context = ast_context_find_or_create(NULL, NULL, trunk->autocontext, sla_registrar); 07076 if (!context) { 07077 ast_log(LOG_ERROR, "Failed to automatically find or create " 07078 "context '%s' for SLA!\n", trunk->autocontext); 07079 return -1; 07080 } 07081 if (ast_add_extension2(context, 0 /* don't replace */, "s", 1, 07082 NULL, NULL, slatrunk_app, ast_strdup(trunk->name), ast_free_ptr, sla_registrar)) { 07083 ast_log(LOG_ERROR, "Failed to automatically create extension " 07084 "for trunk '%s'!\n", trunk->name); 07085 return -1; 07086 } 07087 } 07088 07089 if (!existing_trunk) { 07090 ao2_link(sla_trunks, trunk); 07091 } 07092 07093 return 0; 07094 }
static int sla_calc_station_delays | ( | unsigned int * | timeout | ) | [static] |
Calculate the ring delay for a station.
Definition at line 6219 of file app_meetme.c.
References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_ref, sla_check_inuse_station(), sla_check_ringing_station(), sla_check_station_delay(), sla_choose_ringing_trunk(), and sla_stations.
Referenced by sla_process_timers().
06220 { 06221 struct sla_station *station; 06222 int res = 0; 06223 struct ao2_iterator i; 06224 06225 i = ao2_iterator_init(sla_stations, 0); 06226 for (; (station = ao2_iterator_next(&i)); ao2_ref(station, -1)) { 06227 struct sla_ringing_trunk *ringing_trunk; 06228 int time_left; 06229 06230 /* Ignore stations already ringing */ 06231 if (sla_check_ringing_station(station)) 06232 continue; 06233 06234 /* Ignore stations already on a call */ 06235 if (sla_check_inuse_station(station)) 06236 continue; 06237 06238 /* Ignore stations that don't have one of their trunks ringing */ 06239 if (!(ringing_trunk = sla_choose_ringing_trunk(station, NULL, 0))) 06240 continue; 06241 06242 if ((time_left = sla_check_station_delay(station, ringing_trunk)) == INT_MAX) 06243 continue; 06244 06245 /* If there is no time left, then the station needs to start ringing. 06246 * Return non-zero so that an event will be queued up an event to 06247 * make that happen. */ 06248 if (time_left <= 0) { 06249 res = 1; 06250 continue; 06251 } 06252 06253 if (time_left < *timeout) 06254 *timeout = time_left; 06255 } 06256 ao2_iterator_destroy(&i); 06257 06258 return res; 06259 }
static int sla_calc_station_timeouts | ( | unsigned int * | timeout | ) | [static] |
Process station ring timeouts.
Definition at line 6136 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().
06137 { 06138 struct sla_ringing_trunk *ringing_trunk; 06139 struct sla_ringing_station *ringing_station; 06140 int res = 0; 06141 06142 AST_LIST_TRAVERSE_SAFE_BEGIN(&sla.ringing_stations, ringing_station, entry) { 06143 unsigned int ring_timeout = 0; 06144 int time_elapsed, time_left = INT_MAX, final_trunk_time_left = INT_MIN; 06145 struct sla_trunk_ref *trunk_ref; 06146 06147 /* If there are any ring timeouts specified for a specific trunk 06148 * on the station, then use the highest per-trunk ring timeout. 06149 * Otherwise, use the ring timeout set for the entire station. */ 06150 AST_LIST_TRAVERSE(&ringing_station->station->trunks, trunk_ref, entry) { 06151 struct sla_station_ref *station_ref; 06152 int trunk_time_elapsed, trunk_time_left; 06153 06154 AST_LIST_TRAVERSE(&sla.ringing_trunks, ringing_trunk, entry) { 06155 if (ringing_trunk->trunk == trunk_ref->trunk) 06156 break; 06157 } 06158 if (!ringing_trunk) 06159 continue; 06160 06161 /* If there is a trunk that is ringing without a timeout, then the 06162 * only timeout that could matter is a global station ring timeout. */ 06163 if (!trunk_ref->ring_timeout) 06164 break; 06165 06166 /* This trunk on this station is ringing and has a timeout. 06167 * However, make sure this trunk isn't still ringing from a 06168 * previous timeout. If so, don't consider it. */ 06169 AST_LIST_TRAVERSE(&ringing_trunk->timed_out_stations, station_ref, entry) { 06170 if (station_ref->station == ringing_station->station) 06171 break; 06172 } 06173 if (station_ref) 06174 continue; 06175 06176 trunk_time_elapsed = ast_tvdiff_ms(ast_tvnow(), ringing_trunk->ring_begin); 06177 trunk_time_left = (trunk_ref->ring_timeout * 1000) - trunk_time_elapsed; 06178 if (trunk_time_left > final_trunk_time_left) 06179 final_trunk_time_left = trunk_time_left; 06180 } 06181 06182 /* No timeout was found for ringing trunks, and no timeout for the entire station */ 06183 if (final_trunk_time_left == INT_MIN && !ringing_station->station->ring_timeout) 06184 continue; 06185 06186 /* Compute how much time is left for a global station timeout */ 06187 if (ringing_station->station->ring_timeout) { 06188 ring_timeout = ringing_station->station->ring_timeout; 06189 time_elapsed = ast_tvdiff_ms(ast_tvnow(), ringing_station->ring_begin); 06190 time_left = (ring_timeout * 1000) - time_elapsed; 06191 } 06192 06193 /* If the time left based on the per-trunk timeouts is smaller than the 06194 * global station ring timeout, use that. */ 06195 if (final_trunk_time_left > INT_MIN && final_trunk_time_left < time_left) 06196 time_left = final_trunk_time_left; 06197 06198 /* If there is no time left, the station needs to stop ringing */ 06199 if (time_left <= 0) { 06200 AST_LIST_REMOVE_CURRENT(entry); 06201 sla_stop_ringing_station(ringing_station, SLA_STATION_HANGUP_TIMEOUT); 06202 res = 1; 06203 continue; 06204 } 06205 06206 /* There is still some time left for this station to ring, so save that 06207 * timeout if it is the first event scheduled to occur */ 06208 if (time_left < *timeout) 06209 *timeout = time_left; 06210 } 06211 AST_LIST_TRAVERSE_SAFE_END; 06212 06213 return res; 06214 }
static int sla_calc_trunk_timeouts | ( | unsigned int * | timeout | ) | [static] |
Process trunk ring timeouts.
Definition at line 6106 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().
06107 { 06108 struct sla_ringing_trunk *ringing_trunk; 06109 int res = 0; 06110 06111 AST_LIST_TRAVERSE_SAFE_BEGIN(&sla.ringing_trunks, ringing_trunk, entry) { 06112 int time_left, time_elapsed; 06113 if (!ringing_trunk->trunk->ring_timeout) 06114 continue; 06115 time_elapsed = ast_tvdiff_ms(ast_tvnow(), ringing_trunk->ring_begin); 06116 time_left = (ringing_trunk->trunk->ring_timeout * 1000) - time_elapsed; 06117 if (time_left <= 0) { 06118 pbx_builtin_setvar_helper(ringing_trunk->trunk->chan, "SLATRUNK_STATUS", "RINGTIMEOUT"); 06119 AST_LIST_REMOVE_CURRENT(entry); 06120 sla_stop_ringing_trunk(ringing_trunk); 06121 res = 1; 06122 continue; 06123 } 06124 if (time_left < *timeout) 06125 *timeout = time_left; 06126 } 06127 AST_LIST_TRAVERSE_SAFE_END; 06128 06129 return res; 06130 }
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 5552 of file app_meetme.c.
References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_lock, ao2_ref, ao2_unlock, AST_DEVSTATE_CACHABLE, ast_devstate_changed(), AST_LIST_TRAVERSE, sla_state_to_devstate(), and sla_stations.
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().
05554 { 05555 struct sla_station *station; 05556 struct sla_trunk_ref *trunk_ref; 05557 struct ao2_iterator i; 05558 05559 i = ao2_iterator_init(sla_stations, 0); 05560 while ((station = ao2_iterator_next(&i))) { 05561 ao2_lock(station); 05562 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) { 05563 if (trunk_ref->trunk != trunk || (inactive_only ? trunk_ref->chan : 0) 05564 || trunk_ref == exclude) { 05565 continue; 05566 } 05567 trunk_ref->state = state; 05568 ast_devstate_changed(sla_state_to_devstate(state), AST_DEVSTATE_CACHABLE, 05569 "SLA:%s_%s", station->name, trunk->name); 05570 break; 05571 } 05572 ao2_unlock(station); 05573 ao2_ref(station, -1); 05574 } 05575 ao2_iterator_destroy(&i); 05576 }
static int sla_check_device | ( | const char * | device | ) | [static] |
Definition at line 6983 of file app_meetme.c.
References ast_strdupa, and ast_strlen_zero().
Referenced by sla_build_trunk().
06984 { 06985 char *tech, *tech_data; 06986 06987 tech_data = ast_strdupa(device); 06988 tech = strsep(&tech_data, "/"); 06989 06990 if (ast_strlen_zero(tech) || ast_strlen_zero(tech_data)) 06991 return -1; 06992 06993 return 0; 06994 }
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 5855 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(), sla_failed_station::last_try, sla, sla_failed_station_destroy(), and sla_failed_station::station.
Referenced by sla_ring_stations().
05856 { 05857 struct sla_failed_station *failed_station; 05858 int res = 0; 05859 05860 AST_LIST_TRAVERSE_SAFE_BEGIN(&sla.failed_stations, failed_station, entry) { 05861 if (station != failed_station->station) 05862 continue; 05863 if (ast_tvdiff_ms(ast_tvnow(), failed_station->last_try) > 1000) { 05864 AST_LIST_REMOVE_CURRENT(entry); 05865 sla_failed_station_destroy(failed_station); 05866 break; 05867 } 05868 res = 1; 05869 } 05870 AST_LIST_TRAVERSE_SAFE_END 05871 05872 return res; 05873 }
static int sla_check_inuse_station | ( | const struct sla_station * | station | ) | [static] |
Check to see if a station is in use.
Definition at line 5938 of file app_meetme.c.
References AST_LIST_TRAVERSE.
Referenced by sla_calc_station_delays(), and sla_ring_stations().
05939 { 05940 struct sla_trunk_ref *trunk_ref; 05941 05942 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) { 05943 if (trunk_ref->chan) 05944 return 1; 05945 } 05946 05947 return 0; 05948 }
static int sla_check_ringing_station | ( | const struct sla_station * | station | ) | [static] |
Check to see if this station is already ringing.
Definition at line 5840 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().
05841 { 05842 struct sla_ringing_station *ringing_station; 05843 05844 AST_LIST_TRAVERSE(&sla.ringing_stations, ringing_station, entry) { 05845 if (station == ringing_station->station) 05846 return 1; 05847 } 05848 05849 return 0; 05850 }
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 5970 of file app_meetme.c.
References ast_tvdiff_ms(), ast_tvnow(), RAII_VAR, 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().
05972 { 05973 RAII_VAR(struct sla_trunk_ref *, trunk_ref, NULL, unref_obj); 05974 unsigned int delay = UINT_MAX; 05975 int time_left, time_elapsed; 05976 05977 if (!ringing_trunk) 05978 ringing_trunk = sla_choose_ringing_trunk(station, &trunk_ref, 0); 05979 else 05980 trunk_ref = sla_find_trunk_ref(station, ringing_trunk->trunk); 05981 05982 if (!ringing_trunk || !trunk_ref) 05983 return delay; 05984 05985 /* If this station has a ring delay specific to the highest priority 05986 * ringing trunk, use that. Otherwise, use the ring delay specified 05987 * globally for the station. */ 05988 delay = trunk_ref->ring_delay; 05989 if (!delay) 05990 delay = station->ring_delay; 05991 if (!delay) 05992 return INT_MAX; 05993 05994 time_elapsed = ast_tvdiff_ms(ast_tvnow(), ringing_trunk->ring_begin); 05995 time_left = (delay * 1000) - time_elapsed; 05996 05997 return time_left; 05998 }
static int sla_check_station_hold_access | ( | const struct sla_trunk * | trunk, | |
const struct sla_station * | station | |||
) | [static] |
Definition at line 5403 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().
05405 { 05406 struct sla_station_ref *station_ref; 05407 struct sla_trunk_ref *trunk_ref; 05408 05409 /* For each station that has this call on hold, check for private hold. */ 05410 AST_LIST_TRAVERSE(&trunk->stations, station_ref, entry) { 05411 AST_LIST_TRAVERSE(&station_ref->station->trunks, trunk_ref, entry) { 05412 if (trunk_ref->trunk != trunk || station_ref->station == station) 05413 continue; 05414 if (trunk_ref->state == SLA_TRUNK_STATE_ONHOLD_BYME && 05415 station_ref->station->hold_access == SLA_HOLD_PRIVATE) 05416 return 1; 05417 return 0; 05418 } 05419 } 05420 05421 return 0; 05422 }
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 5698 of file app_meetme.c.
References AST_LIST_TRAVERSE.
Referenced by sla_choose_ringing_trunk(), and sla_ring_stations().
05700 { 05701 struct sla_station_ref *timed_out_station; 05702 05703 AST_LIST_TRAVERSE(&ringing_trunk->timed_out_stations, timed_out_station, entry) { 05704 if (station == timed_out_station->station) 05705 return 1; 05706 } 05707 05708 return 0; 05709 }
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 6515 of file app_meetme.c.
References ao2_ref, AST_LIST_TRAVERSE, and SLA_TRUNK_STATE_IDLE.
Referenced by sla_station_exec().
06516 { 06517 struct sla_trunk_ref *trunk_ref = NULL; 06518 06519 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) { 06520 if (trunk_ref->state == SLA_TRUNK_STATE_IDLE) { 06521 ao2_ref(trunk_ref, 1); 06522 break; 06523 } 06524 } 06525 06526 return trunk_ref; 06527 }
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 5719 of file app_meetme.c.
References ao2_ref, 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().
05721 { 05722 struct sla_trunk_ref *s_trunk_ref; 05723 struct sla_ringing_trunk *ringing_trunk = NULL; 05724 05725 AST_LIST_TRAVERSE(&station->trunks, s_trunk_ref, entry) { 05726 AST_LIST_TRAVERSE_SAFE_BEGIN(&sla.ringing_trunks, ringing_trunk, entry) { 05727 /* Make sure this is the trunk we're looking for */ 05728 if (s_trunk_ref->trunk != ringing_trunk->trunk) 05729 continue; 05730 05731 /* This trunk on the station is ringing. But, make sure this station 05732 * didn't already time out while this trunk was ringing. */ 05733 if (sla_check_timed_out_station(ringing_trunk, station)) 05734 continue; 05735 05736 if (rm) 05737 AST_LIST_REMOVE_CURRENT(entry); 05738 05739 if (trunk_ref) { 05740 ao2_ref(s_trunk_ref, 1); 05741 *trunk_ref = s_trunk_ref; 05742 } 05743 05744 break; 05745 } 05746 AST_LIST_TRAVERSE_SAFE_END; 05747 05748 if (ringing_trunk) 05749 break; 05750 } 05751 05752 return ringing_trunk; 05753 }
static struct sla_failed_station* sla_create_failed_station | ( | struct sla_station * | station | ) | [static, read] |
Definition at line 5510 of file app_meetme.c.
References ao2_ref, ast_calloc, ast_tvnow(), sla_failed_station::last_try, and sla_failed_station::station.
Referenced by sla_ring_station().
05511 { 05512 struct sla_failed_station *failed_station; 05513 05514 if (!(failed_station = ast_calloc(1, sizeof(*failed_station)))) { 05515 return NULL; 05516 } 05517 05518 ao2_ref(station, 1); 05519 failed_station->station = station; 05520 failed_station->last_try = ast_tvnow(); 05521 05522 return failed_station; 05523 }
static struct sla_ringing_station* sla_create_ringing_station | ( | struct sla_station * | station | ) | [static, read] |
Definition at line 5486 of file app_meetme.c.
References ao2_ref, ast_calloc, ast_tvnow(), sla_ringing_station::ring_begin, and sla_ringing_station::station.
Referenced by sla_ring_station().
05487 { 05488 struct sla_ringing_station *ringing_station; 05489 05490 if (!(ringing_station = ast_calloc(1, sizeof(*ringing_station)))) 05491 return NULL; 05492 05493 ao2_ref(station, 1); 05494 ringing_station->station = station; 05495 ringing_station->ring_begin = ast_tvnow(); 05496 05497 return ringing_station; 05498 }
static struct sla_station_ref* sla_create_station_ref | ( | struct sla_station * | station | ) | [static, read] |
Definition at line 5472 of file app_meetme.c.
References ao2_alloc, ao2_ref, and sla_station_ref_destructor().
Referenced by sla_add_trunk_to_station(), and sla_stop_ringing_station().
05473 { 05474 struct sla_station_ref *station_ref; 05475 05476 if (!(station_ref = ao2_alloc(sizeof(*station_ref), sla_station_ref_destructor))) { 05477 return NULL; 05478 } 05479 05480 ao2_ref(station, 1); 05481 station_ref->station = station; 05482 05483 return station_ref; 05484 }
static void sla_destroy | ( | void | ) | [static] |
Definition at line 6957 of file app_meetme.c.
References ao2_callback, ao2_ref, ast_cond_destroy, ast_cond_signal, ast_context_destroy(), ast_mutex_destroy, ast_mutex_lock, ast_mutex_unlock, AST_PTHREADT_NULL, sla, sla_registrar, sla_station_release_refs(), sla_stations, sla_trunk_release_refs(), and sla_trunks.
Referenced by unload_module().
06958 { 06959 if (sla.thread != AST_PTHREADT_NULL) { 06960 ast_mutex_lock(&sla.lock); 06961 sla.stop = 1; 06962 ast_cond_signal(&sla.cond); 06963 ast_mutex_unlock(&sla.lock); 06964 pthread_join(sla.thread, NULL); 06965 } 06966 06967 /* Drop any created contexts from the dialplan */ 06968 ast_context_destroy(NULL, sla_registrar); 06969 06970 ast_mutex_destroy(&sla.lock); 06971 ast_cond_destroy(&sla.cond); 06972 06973 ao2_callback(sla_trunks, 0, sla_trunk_release_refs, NULL); 06974 ao2_callback(sla_stations, 0, sla_station_release_refs, NULL); 06975 06976 ao2_ref(sla_trunks, -1); 06977 sla_trunks = NULL; 06978 06979 ao2_ref(sla_stations, -1); 06980 sla_stations = NULL; 06981 }
static void sla_dial_state_callback | ( | struct ast_dial * | dial | ) | [static] |
Definition at line 5690 of file app_meetme.c.
References SLA_EVENT_DIAL_STATE, and sla_queue_event().
Referenced by sla_ring_station().
05691 { 05692 sla_queue_event(SLA_EVENT_DIAL_STATE); 05693 }
static void sla_event_destroy | ( | struct sla_event * | event | ) | [static] |
Definition at line 6298 of file app_meetme.c.
References ao2_ref, ast_free, sla_event::station, and sla_event::trunk_ref.
Referenced by sla_thread().
static void sla_failed_station_destroy | ( | struct sla_failed_station * | failed_station | ) | [static] |
Definition at line 5525 of file app_meetme.c.
References ao2_ref, ast_free, and sla_failed_station::station.
Referenced by sla_check_failed_station(), and sla_thread().
static struct sla_station* sla_find_station | ( | const char * | name | ) | [static, read] |
Definition at line 5394 of file app_meetme.c.
References ao2_find, OBJ_POINTER, and sla_stations.
Referenced by sla_build_station(), sla_state(), and sla_station_exec().
05395 { 05396 struct sla_station tmp_station = { 05397 .name = name, 05398 }; 05399 05400 return ao2_find(sla_stations, &tmp_station, OBJ_POINTER); 05401 }
static struct sla_trunk* sla_find_trunk | ( | const char * | name | ) | [static, read] |
Definition at line 5381 of file app_meetme.c.
References ao2_find, OBJ_POINTER, and sla_trunks.
Referenced by sla_add_trunk_to_station(), sla_build_trunk(), and sla_trunk_exec().
05382 { 05383 struct sla_trunk tmp_trunk = { 05384 .name = name, 05385 }; 05386 05387 return ao2_find(sla_trunks, &tmp_trunk, OBJ_POINTER); 05388 }
static struct sla_trunk_ref* sla_find_trunk_ref | ( | const struct sla_station * | station, | |
const struct sla_trunk * | trunk | |||
) | [static, read] |
Definition at line 5950 of file app_meetme.c.
References ao2_ref, and AST_LIST_TRAVERSE.
Referenced by sla_check_station_delay().
05952 { 05953 struct sla_trunk_ref *trunk_ref = NULL; 05954 05955 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) { 05956 if (trunk_ref->trunk == trunk) 05957 break; 05958 } 05959 05960 ao2_ref(trunk_ref, 1); 05961 05962 return trunk_ref; 05963 }
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 5433 of file app_meetme.c.
References ao2_ref, 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().
05435 { 05436 struct sla_trunk_ref *trunk_ref = NULL; 05437 05438 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) { 05439 if (strcasecmp(trunk_ref->trunk->name, name)) 05440 continue; 05441 05442 if ( (trunk_ref->trunk->barge_disabled 05443 && trunk_ref->state == SLA_TRUNK_STATE_UP) || 05444 (trunk_ref->trunk->hold_stations 05445 && trunk_ref->trunk->hold_access == SLA_HOLD_PRIVATE 05446 && trunk_ref->state != SLA_TRUNK_STATE_ONHOLD_BYME) || 05447 sla_check_station_hold_access(trunk_ref->trunk, station) ) 05448 { 05449 trunk_ref = NULL; 05450 } 05451 05452 break; 05453 } 05454 05455 if (trunk_ref) { 05456 ao2_ref(trunk_ref, 1); 05457 } 05458 05459 return trunk_ref; 05460 }
static void sla_handle_dial_state_event | ( | void | ) | [static] |
Definition at line 5755 of file app_meetme.c.
References ALL_TRUNK_REFS, answer_trunk_chan(), ao2_ref, ast_cond_destroy, ast_cond_init, ast_cond_wait, ast_debug, ast_dial_answered(), ast_dial_destroy(), ast_dial_join(), AST_DIAL_RESULT_ANSWERED, AST_DIAL_RESULT_FAILED, AST_DIAL_RESULT_HANGUP, AST_DIAL_RESULT_INVALID, AST_DIAL_RESULT_PROCEEDING, AST_DIAL_RESULT_PROGRESS, AST_DIAL_RESULT_RINGING, AST_DIAL_RESULT_TIMEOUT, AST_DIAL_RESULT_TRYING, AST_DIAL_RESULT_UNANSWERED, ast_dial_state(), AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_mutex_destroy, ast_mutex_init, ast_mutex_lock, ast_mutex_unlock, ast_pthread_create_detached_background, run_station_args::cond, run_station_args::cond_lock, RAII_VAR, run_station(), sla, sla_change_trunk_state(), sla_choose_ringing_trunk(), SLA_EVENT_DIAL_STATE, SLA_EVENT_RINGING_TRUNK, sla_queue_event(), sla_ringing_station_destroy(), sla_ringing_trunk_destroy(), SLA_STATION_HANGUP_NORMAL, sla_stop_ringing_station(), SLA_TRUNK_STATE_UP, run_station_args::station, sla_ringing_station::station, sla_ringing_trunk::trunk, and run_station_args::trunk_ref.
Referenced by sla_thread().
05756 { 05757 struct sla_ringing_station *ringing_station; 05758 05759 AST_LIST_TRAVERSE_SAFE_BEGIN(&sla.ringing_stations, ringing_station, entry) { 05760 RAII_VAR(struct sla_trunk_ref *, s_trunk_ref, NULL, unref_obj); 05761 struct sla_ringing_trunk *ringing_trunk = NULL; 05762 struct run_station_args args; 05763 enum ast_dial_result dial_res; 05764 pthread_t dont_care; 05765 ast_mutex_t cond_lock; 05766 ast_cond_t cond; 05767 05768 switch ((dial_res = ast_dial_state(ringing_station->station->dial))) { 05769 case AST_DIAL_RESULT_HANGUP: 05770 case AST_DIAL_RESULT_INVALID: 05771 case AST_DIAL_RESULT_FAILED: 05772 case AST_DIAL_RESULT_TIMEOUT: 05773 case AST_DIAL_RESULT_UNANSWERED: 05774 AST_LIST_REMOVE_CURRENT(entry); 05775 sla_stop_ringing_station(ringing_station, SLA_STATION_HANGUP_NORMAL); 05776 break; 05777 case AST_DIAL_RESULT_ANSWERED: 05778 AST_LIST_REMOVE_CURRENT(entry); 05779 /* Find the appropriate trunk to answer. */ 05780 ast_mutex_lock(&sla.lock); 05781 ringing_trunk = sla_choose_ringing_trunk(ringing_station->station, &s_trunk_ref, 1); 05782 ast_mutex_unlock(&sla.lock); 05783 if (!ringing_trunk) { 05784 /* This case happens in a bit of a race condition. If two stations answer 05785 * the outbound call at the same time, the first one will get connected to 05786 * the trunk. When the second one gets here, it will not see any trunks 05787 * ringing so we have no idea what to conect it to. So, we just hang up 05788 * on it. */ 05789 ast_debug(1, "Found no ringing trunk for station '%s' to answer!\n", ringing_station->station->name); 05790 ast_dial_join(ringing_station->station->dial); 05791 ast_dial_destroy(ringing_station->station->dial); 05792 ringing_station->station->dial = NULL; 05793 sla_ringing_station_destroy(ringing_station); 05794 break; 05795 } 05796 /* Track the channel that answered this trunk */ 05797 s_trunk_ref->chan = ast_dial_answered(ringing_station->station->dial); 05798 /* Actually answer the trunk */ 05799 answer_trunk_chan(ringing_trunk->trunk->chan); 05800 sla_change_trunk_state(ringing_trunk->trunk, SLA_TRUNK_STATE_UP, ALL_TRUNK_REFS, NULL); 05801 /* Now, start a thread that will connect this station to the trunk. The rest of 05802 * the code here sets up the thread and ensures that it is able to save the arguments 05803 * before they are no longer valid since they are allocated on the stack. */ 05804 ao2_ref(s_trunk_ref, 1); 05805 args.trunk_ref = s_trunk_ref; 05806 ao2_ref(ringing_station->station, 1); 05807 args.station = ringing_station->station; 05808 args.cond = &cond; 05809 args.cond_lock = &cond_lock; 05810 sla_ringing_trunk_destroy(ringing_trunk); 05811 sla_ringing_station_destroy(ringing_station); 05812 ast_mutex_init(&cond_lock); 05813 ast_cond_init(&cond, NULL); 05814 ast_mutex_lock(&cond_lock); 05815 ast_pthread_create_detached_background(&dont_care, NULL, run_station, &args); 05816 ast_cond_wait(&cond, &cond_lock); 05817 ast_mutex_unlock(&cond_lock); 05818 ast_mutex_destroy(&cond_lock); 05819 ast_cond_destroy(&cond); 05820 break; 05821 case AST_DIAL_RESULT_TRYING: 05822 case AST_DIAL_RESULT_RINGING: 05823 case AST_DIAL_RESULT_PROGRESS: 05824 case AST_DIAL_RESULT_PROCEEDING: 05825 break; 05826 } 05827 if (dial_res == AST_DIAL_RESULT_ANSWERED) { 05828 /* Queue up reprocessing ringing trunks, and then ringing stations again */ 05829 sla_queue_event(SLA_EVENT_RINGING_TRUNK); 05830 sla_queue_event(SLA_EVENT_DIAL_STATE); 05831 break; 05832 } 05833 } 05834 AST_LIST_TRAVERSE_SAFE_END; 05835 }
static void sla_handle_hold_event | ( | struct sla_event * | event | ) | [static] |
Definition at line 6082 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().
06083 { 06084 ast_atomic_fetchadd_int((int *) &event->trunk_ref->trunk->hold_stations, 1); 06085 event->trunk_ref->state = SLA_TRUNK_STATE_ONHOLD_BYME; 06086 ast_devstate_changed(AST_DEVICE_ONHOLD, AST_DEVSTATE_CACHABLE, "SLA:%s_%s", 06087 event->station->name, event->trunk_ref->trunk->name); 06088 sla_change_trunk_state(event->trunk_ref->trunk, SLA_TRUNK_STATE_ONHOLD, 06089 INACTIVE_TRUNK_REFS, event->trunk_ref); 06090 06091 if (event->trunk_ref->trunk->active_stations == 1) { 06092 /* The station putting it on hold is the only one on the call, so start 06093 * Music on hold to the trunk. */ 06094 event->trunk_ref->trunk->on_hold = 1; 06095 ast_indicate(event->trunk_ref->trunk->chan, AST_CONTROL_HOLD); 06096 } 06097 06098 ast_softhangup(event->trunk_ref->chan, AST_SOFTHANGUP_DEV); 06099 event->trunk_ref->chan = NULL; 06100 }
static void sla_handle_ringing_trunk_event | ( | void | ) | [static] |
Definition at line 6072 of file app_meetme.c.
References ast_mutex_lock, ast_mutex_unlock, sla, sla_hangup_stations(), and sla_ring_stations().
Referenced by sla_thread().
06073 { 06074 ast_mutex_lock(&sla.lock); 06075 sla_ring_stations(); 06076 ast_mutex_unlock(&sla.lock); 06077 06078 /* Find stations that shouldn't be ringing anymore. */ 06079 sla_hangup_stations(); 06080 }
static void sla_hangup_stations | ( | void | ) | [static] |
Definition at line 6044 of file app_meetme.c.
References ast_dial_destroy(), ast_dial_join(), AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_mutex_lock, ast_mutex_unlock, sla, sla_ringing_station_destroy(), sla_ringing_station::station, and sla_ringing_trunk::trunk.
Referenced by sla_handle_ringing_trunk_event().
06045 { 06046 struct sla_trunk_ref *trunk_ref; 06047 struct sla_ringing_station *ringing_station; 06048 06049 AST_LIST_TRAVERSE_SAFE_BEGIN(&sla.ringing_stations, ringing_station, entry) { 06050 AST_LIST_TRAVERSE(&ringing_station->station->trunks, trunk_ref, entry) { 06051 struct sla_ringing_trunk *ringing_trunk; 06052 ast_mutex_lock(&sla.lock); 06053 AST_LIST_TRAVERSE(&sla.ringing_trunks, ringing_trunk, entry) { 06054 if (trunk_ref->trunk == ringing_trunk->trunk) 06055 break; 06056 } 06057 ast_mutex_unlock(&sla.lock); 06058 if (ringing_trunk) 06059 break; 06060 } 06061 if (!trunk_ref) { 06062 AST_LIST_REMOVE_CURRENT(entry); 06063 ast_dial_join(ringing_station->station->dial); 06064 ast_dial_destroy(ringing_station->station->dial); 06065 ringing_station->station->dial = NULL; 06066 sla_ringing_station_destroy(ringing_station); 06067 } 06068 } 06069 AST_LIST_TRAVERSE_SAFE_END 06070 }
static const char* sla_hold_str | ( | unsigned int | hold_access | ) | [static] |
Definition at line 1714 of file app_meetme.c.
References SLA_HOLD_OPEN, and SLA_HOLD_PRIVATE.
Referenced by sla_show_stations(), and sla_show_trunks().
01715 { 01716 const char *hold = "Unknown"; 01717 01718 switch (hold_access) { 01719 case SLA_HOLD_OPEN: 01720 hold = "Open"; 01721 break; 01722 case SLA_HOLD_PRIVATE: 01723 hold = "Private"; 01724 default: 01725 break; 01726 } 01727 01728 return hold; 01729 }
static int sla_in_use | ( | void | ) | [static] |
Definition at line 7389 of file app_meetme.c.
References ao2_container_count(), sla_stations, and sla_trunks.
Referenced by sla_load_config().
07390 { 07391 return ao2_container_count(sla_trunks) || ao2_container_count(sla_stations); 07392 }
static int sla_load_config | ( | int | reload | ) | [static] |
Definition at line 7394 of file app_meetme.c.
References ao2_callback, ao2_container_alloc, ast_category_browse(), ast_cond_init, ast_config_destroy(), ast_config_load, ast_log(), ast_mutex_init, ast_pthread_create, AST_PTHREADT_NULL, ast_true(), ast_variable_retrieve(), CONFIG_FLAG_FILEUNCHANGED, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEUNCHANGED, LOG_ERROR, LOG_WARNING, OBJ_MULTIPLE, OBJ_NODATA, OBJ_UNLINK, sla, sla_build_station(), sla_build_trunk(), SLA_CONFIG_FILE, sla_in_use(), sla_station_cmp(), sla_station_hash(), sla_station_is_marked(), sla_station_mark(), sla_stations, sla_thread(), sla_trunk_cmp(), sla_trunk_hash(), sla_trunk_is_marked(), sla_trunk_mark(), sla_trunks, and type.
Referenced by load_config().
07395 { 07396 struct ast_config *cfg; 07397 struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; 07398 const char *cat = NULL; 07399 int res = 0; 07400 const char *val; 07401 07402 if (!reload) { 07403 ast_mutex_init(&sla.lock); 07404 ast_cond_init(&sla.cond, NULL); 07405 sla_trunks = ao2_container_alloc(1, sla_trunk_hash, sla_trunk_cmp); 07406 sla_stations = ao2_container_alloc(1, sla_station_hash, sla_station_cmp); 07407 } 07408 07409 if (!(cfg = ast_config_load(SLA_CONFIG_FILE, config_flags))) { 07410 return 0; /* Treat no config as normal */ 07411 } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) { 07412 return 0; 07413 } else if (cfg == CONFIG_STATUS_FILEINVALID) { 07414 ast_log(LOG_ERROR, "Config file " SLA_CONFIG_FILE " is in an invalid format. Aborting.\n"); 07415 return 0; 07416 } 07417 07418 if (reload) { 07419 ao2_callback(sla_trunks, 0, sla_trunk_mark, NULL); 07420 ao2_callback(sla_stations, 0, sla_station_mark, NULL); 07421 } 07422 07423 if ((val = ast_variable_retrieve(cfg, "general", "attemptcallerid"))) 07424 sla.attempt_callerid = ast_true(val); 07425 07426 while ((cat = ast_category_browse(cfg, cat)) && !res) { 07427 const char *type; 07428 if (!strcasecmp(cat, "general")) 07429 continue; 07430 if (!(type = ast_variable_retrieve(cfg, cat, "type"))) { 07431 ast_log(LOG_WARNING, "Invalid entry in %s defined with no type!\n", 07432 SLA_CONFIG_FILE); 07433 continue; 07434 } 07435 if (!strcasecmp(type, "trunk")) 07436 res = sla_build_trunk(cfg, cat); 07437 else if (!strcasecmp(type, "station")) 07438 res = sla_build_station(cfg, cat); 07439 else { 07440 ast_log(LOG_WARNING, "Entry in %s defined with invalid type '%s'!\n", 07441 SLA_CONFIG_FILE, type); 07442 } 07443 } 07444 07445 ast_config_destroy(cfg); 07446 07447 if (reload) { 07448 ao2_callback(sla_trunks, OBJ_NODATA | OBJ_UNLINK | OBJ_MULTIPLE, sla_trunk_is_marked, NULL); 07449 ao2_callback(sla_stations, OBJ_NODATA | OBJ_UNLINK | OBJ_MULTIPLE, sla_station_is_marked, NULL); 07450 } 07451 07452 /* Start SLA event processing thread once SLA has been configured. */ 07453 if (sla.thread == AST_PTHREADT_NULL && sla_in_use()) { 07454 ast_pthread_create(&sla.thread, NULL, sla_thread, NULL); 07455 } 07456 07457 return res; 07458 }
static int sla_process_timers | ( | struct timespec * | ts | ) | [static] |
Calculate the time until the next known event.
Definition at line 6263 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().
06264 { 06265 unsigned int timeout = UINT_MAX; 06266 struct timeval wait; 06267 unsigned int change_made = 0; 06268 06269 /* Check for ring timeouts on ringing trunks */ 06270 if (sla_calc_trunk_timeouts(&timeout)) 06271 change_made = 1; 06272 06273 /* Check for ring timeouts on ringing stations */ 06274 if (sla_calc_station_timeouts(&timeout)) 06275 change_made = 1; 06276 06277 /* Check for station ring delays */ 06278 if (sla_calc_station_delays(&timeout)) 06279 change_made = 1; 06280 06281 /* queue reprocessing of ringing trunks */ 06282 if (change_made) 06283 sla_queue_event_nolock(SLA_EVENT_RINGING_TRUNK); 06284 06285 /* No timeout */ 06286 if (timeout == UINT_MAX) 06287 return 0; 06288 06289 if (ts) { 06290 wait = ast_tvadd(ast_tvnow(), ast_samp2tv(timeout, 1000)); 06291 ts->tv_sec = wait.tv_sec; 06292 ts->tv_nsec = wait.tv_usec * 1000; 06293 } 06294 06295 return 1; 06296 }
static void sla_queue_event | ( | enum sla_event_type | type | ) | [static] |
Definition at line 2049 of file app_meetme.c.
References sla_queue_event_full().
Referenced by queue_ringing_trunk(), sla_dial_state_callback(), sla_handle_dial_state_event(), sla_station_exec(), and sla_trunk_exec().
02050 { 02051 sla_queue_event_full(type, NULL, NULL, 1); 02052 }
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 2055 of file app_meetme.c.
References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_lock, ao2_ref, ao2_unlock, ast_debug, AST_LIST_TRAVERSE, ast_log(), ast_strdupa, ast_strlen_zero(), ast_conference::confno, LOG_ERROR, sla_queue_event_full(), and sla_stations.
Referenced by conf_run().
02057 { 02058 struct sla_station *station; 02059 struct sla_trunk_ref *trunk_ref = NULL; 02060 char *trunk_name; 02061 struct ao2_iterator i; 02062 02063 trunk_name = ast_strdupa(conf->confno); 02064 strsep(&trunk_name, "_"); 02065 if (ast_strlen_zero(trunk_name)) { 02066 ast_log(LOG_ERROR, "Invalid conference name for SLA - '%s'!\n", conf->confno); 02067 return; 02068 } 02069 02070 i = ao2_iterator_init(sla_stations, 0); 02071 while ((station = ao2_iterator_next(&i))) { 02072 ao2_lock(station); 02073 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) { 02074 if (trunk_ref->chan == chan && !strcmp(trunk_ref->trunk->name, trunk_name)) { 02075 ao2_ref(trunk_ref, 1); 02076 break; 02077 } 02078 } 02079 ao2_unlock(station); 02080 if (trunk_ref) { 02081 /* station reference given to sla_queue_event_full() */ 02082 break; 02083 } 02084 ao2_ref(station, -1); 02085 } 02086 ao2_iterator_destroy(&i); 02087 02088 if (!trunk_ref) { 02089 ast_debug(1, "Trunk not found for event!\n"); 02090 return; 02091 } 02092 02093 sla_queue_event_full(type, trunk_ref, station, 1); 02094 }
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 2012 of file app_meetme.c.
References ao2_ref, 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().
02014 { 02015 struct sla_event *event; 02016 02017 if (sla.thread == AST_PTHREADT_NULL) { 02018 ao2_ref(station, -1); 02019 ao2_ref(trunk_ref, -1); 02020 return; 02021 } 02022 02023 if (!(event = ast_calloc(1, sizeof(*event)))) { 02024 ao2_ref(station, -1); 02025 ao2_ref(trunk_ref, -1); 02026 return; 02027 } 02028 02029 event->type = type; 02030 event->trunk_ref = trunk_ref; 02031 event->station = station; 02032 02033 if (!lock) { 02034 AST_LIST_INSERT_TAIL(&sla.event_q, event, entry); 02035 return; 02036 } 02037 02038 ast_mutex_lock(&sla.lock); 02039 AST_LIST_INSERT_TAIL(&sla.event_q, event, entry); 02040 ast_cond_signal(&sla.cond); 02041 ast_mutex_unlock(&sla.lock); 02042 }
static void sla_queue_event_nolock | ( | enum sla_event_type | type | ) | [static] |
Definition at line 2044 of file app_meetme.c.
References sla_queue_event_full().
Referenced by sla_process_timers().
02045 { 02046 sla_queue_event_full(type, NULL, NULL, 0); 02047 }
static int sla_ring_station | ( | struct sla_ringing_trunk * | ringing_trunk, | |
struct sla_station * | station | |||
) | [static] |
Ring a station.
Definition at line 5878 of file app_meetme.c.
References ast_dial_append(), ast_dial_create(), ast_dial_destroy(), ast_dial_join(), AST_DIAL_RESULT_TRYING, ast_dial_run(), ast_dial_set_state_callback(), AST_LIST_INSERT_HEAD, ast_party_caller_free(), ast_party_caller_init(), ast_strdupa, sla, sla_create_failed_station(), sla_create_ringing_station(), sla_dial_state_callback(), and sla_ringing_trunk::trunk.
Referenced by sla_ring_stations().
05879 { 05880 char *tech, *tech_data; 05881 struct ast_dial *dial; 05882 struct sla_ringing_station *ringing_station; 05883 enum ast_dial_result res; 05884 int caller_is_saved; 05885 struct ast_party_caller caller; 05886 05887 if (!(dial = ast_dial_create())) 05888 return -1; 05889 05890 ast_dial_set_state_callback(dial, sla_dial_state_callback); 05891 tech_data = ast_strdupa(station->device); 05892 tech = strsep(&tech_data, "/"); 05893 05894 if (ast_dial_append(dial, tech, tech_data) == -1) { 05895 ast_dial_destroy(dial); 05896 return -1; 05897 } 05898 05899 /* Do we need to save off the caller ID data? */ 05900 caller_is_saved = 0; 05901 if (!sla.attempt_callerid) { 05902 caller_is_saved = 1; 05903 caller = ringing_trunk->trunk->chan->caller; 05904 ast_party_caller_init(&ringing_trunk->trunk->chan->caller); 05905 } 05906 05907 res = ast_dial_run(dial, ringing_trunk->trunk->chan, 1); 05908 05909 /* Restore saved caller ID */ 05910 if (caller_is_saved) { 05911 ast_party_caller_free(&ringing_trunk->trunk->chan->caller); 05912 ringing_trunk->trunk->chan->caller = caller; 05913 } 05914 05915 if (res != AST_DIAL_RESULT_TRYING) { 05916 struct sla_failed_station *failed_station; 05917 ast_dial_destroy(dial); 05918 if ((failed_station = sla_create_failed_station(station))) { 05919 AST_LIST_INSERT_HEAD(&sla.failed_stations, failed_station, entry); 05920 } 05921 return -1; 05922 } 05923 if (!(ringing_station = sla_create_ringing_station(station))) { 05924 ast_dial_join(dial); 05925 ast_dial_destroy(dial); 05926 return -1; 05927 } 05928 05929 station->dial = dial; 05930 05931 AST_LIST_INSERT_HEAD(&sla.ringing_stations, ringing_station, entry); 05932 05933 return 0; 05934 }
static void sla_ring_stations | ( | void | ) | [static] |
Ring stations based on current set of ringing trunks.
Definition at line 6003 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().
06004 { 06005 struct sla_station_ref *station_ref; 06006 struct sla_ringing_trunk *ringing_trunk; 06007 06008 /* Make sure that every station that uses at least one of the ringing 06009 * trunks, is ringing. */ 06010 AST_LIST_TRAVERSE(&sla.ringing_trunks, ringing_trunk, entry) { 06011 AST_LIST_TRAVERSE(&ringing_trunk->trunk->stations, station_ref, entry) { 06012 int time_left; 06013 06014 /* Is this station already ringing? */ 06015 if (sla_check_ringing_station(station_ref->station)) 06016 continue; 06017 06018 /* Is this station already in a call? */ 06019 if (sla_check_inuse_station(station_ref->station)) 06020 continue; 06021 06022 /* Did we fail to dial this station earlier? If so, has it been 06023 * a minute since we tried? */ 06024 if (sla_check_failed_station(station_ref->station)) 06025 continue; 06026 06027 /* If this station already timed out while this trunk was ringing, 06028 * do not dial it again for this ringing trunk. */ 06029 if (sla_check_timed_out_station(ringing_trunk, station_ref->station)) 06030 continue; 06031 06032 /* Check for a ring delay in progress */ 06033 time_left = sla_check_station_delay(station_ref->station, ringing_trunk); 06034 if (time_left != INT_MAX && time_left > 0) 06035 continue; 06036 06037 /* It is time to make this station begin to ring. Do it! */ 06038 sla_ring_station(ringing_trunk, station_ref->station); 06039 } 06040 } 06041 /* Now, all of the stations that should be ringing, are ringing. */ 06042 }
static void sla_ringing_station_destroy | ( | struct sla_ringing_station * | ringing_station | ) | [static] |
Definition at line 5500 of file app_meetme.c.
References ao2_ref, ast_free, and sla_ringing_station::station.
Referenced by sla_handle_dial_state_event(), sla_hangup_stations(), sla_stop_ringing_station(), and sla_thread().
static void sla_ringing_trunk_destroy | ( | struct sla_ringing_trunk * | ringing_trunk | ) | [static] |
Definition at line 6728 of file app_meetme.c.
References ao2_ref, ast_free, and sla_ringing_trunk::trunk.
Referenced by sla_handle_dial_state_event(), sla_station_exec(), sla_stop_ringing_trunk(), and sla_trunk_exec().
static char* sla_show_stations | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 1805 of file app_meetme.c.
References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_lock, ao2_ref, ao2_unlock, ast_cli(), AST_LIST_TRAVERSE, CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, S_OR, sla_hold_str(), sla_stations, trunkstate2str(), and ast_cli_entry::usage.
01806 { 01807 struct ao2_iterator i; 01808 struct sla_station *station; 01809 01810 switch (cmd) { 01811 case CLI_INIT: 01812 e->command = "sla show stations"; 01813 e->usage = 01814 "Usage: sla show stations\n" 01815 " This will list all stations defined in sla.conf\n"; 01816 return NULL; 01817 case CLI_GENERATE: 01818 return NULL; 01819 } 01820 01821 ast_cli(a->fd, "\n" 01822 "=============================================================\n" 01823 "=== Configured SLA Stations =================================\n" 01824 "=============================================================\n" 01825 "===\n"); 01826 i = ao2_iterator_init(sla_stations, 0); 01827 for (; (station = ao2_iterator_next(&i)); ao2_ref(station, -1)) { 01828 struct sla_trunk_ref *trunk_ref; 01829 char ring_timeout[16] = "(none)"; 01830 char ring_delay[16] = "(none)"; 01831 01832 ao2_lock(station); 01833 01834 if (station->ring_timeout) { 01835 snprintf(ring_timeout, sizeof(ring_timeout), 01836 "%u", station->ring_timeout); 01837 } 01838 if (station->ring_delay) { 01839 snprintf(ring_delay, sizeof(ring_delay), 01840 "%u", station->ring_delay); 01841 } 01842 ast_cli(a->fd, "=== ---------------------------------------------------------\n" 01843 "=== Station Name: %s\n" 01844 "=== ==> Device: %s\n" 01845 "=== ==> AutoContext: %s\n" 01846 "=== ==> RingTimeout: %s\n" 01847 "=== ==> RingDelay: %s\n" 01848 "=== ==> HoldAccess: %s\n" 01849 "=== ==> Trunks ...\n", 01850 station->name, station->device, 01851 S_OR(station->autocontext, "(none)"), 01852 ring_timeout, ring_delay, 01853 sla_hold_str(station->hold_access)); 01854 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) { 01855 if (trunk_ref->ring_timeout) { 01856 snprintf(ring_timeout, sizeof(ring_timeout), 01857 "%u", trunk_ref->ring_timeout); 01858 } else 01859 strcpy(ring_timeout, "(none)"); 01860 if (trunk_ref->ring_delay) { 01861 snprintf(ring_delay, sizeof(ring_delay), 01862 "%u", trunk_ref->ring_delay); 01863 } else 01864 strcpy(ring_delay, "(none)"); 01865 ast_cli(a->fd, "=== ==> Trunk Name: %s\n" 01866 "=== ==> State: %s\n" 01867 "=== ==> RingTimeout: %s\n" 01868 "=== ==> RingDelay: %s\n", 01869 trunk_ref->trunk->name, 01870 trunkstate2str(trunk_ref->state), 01871 ring_timeout, ring_delay); 01872 } 01873 ast_cli(a->fd, "=== ---------------------------------------------------------\n" 01874 "===\n"); 01875 01876 ao2_unlock(station); 01877 } 01878 ao2_iterator_destroy(&i); 01879 ast_cli(a->fd, "============================================================\n" 01880 "\n"); 01881 01882 return CLI_SUCCESS; 01883 }
static char* sla_show_trunks | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 1731 of file app_meetme.c.
References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_lock, ao2_ref, ao2_unlock, ast_cli(), AST_LIST_TRAVERSE, CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, S_OR, sla_hold_str(), sla_trunks, and ast_cli_entry::usage.
01732 { 01733 struct ao2_iterator i; 01734 struct sla_trunk *trunk; 01735 01736 switch (cmd) { 01737 case CLI_INIT: 01738 e->command = "sla show trunks"; 01739 e->usage = 01740 "Usage: sla show trunks\n" 01741 " This will list all trunks defined in sla.conf\n"; 01742 return NULL; 01743 case CLI_GENERATE: 01744 return NULL; 01745 } 01746 01747 ast_cli(a->fd, "\n" 01748 "=============================================================\n" 01749 "=== Configured SLA Trunks ===================================\n" 01750 "=============================================================\n" 01751 "===\n"); 01752 i = ao2_iterator_init(sla_trunks, 0); 01753 for (; (trunk = ao2_iterator_next(&i)); ao2_ref(trunk, -1)) { 01754 struct sla_station_ref *station_ref; 01755 char ring_timeout[16] = "(none)"; 01756 01757 ao2_lock(trunk); 01758 01759 if (trunk->ring_timeout) { 01760 snprintf(ring_timeout, sizeof(ring_timeout), "%u Seconds", trunk->ring_timeout); 01761 } 01762 01763 ast_cli(a->fd, "=== ---------------------------------------------------------\n" 01764 "=== Trunk Name: %s\n" 01765 "=== ==> Device: %s\n" 01766 "=== ==> AutoContext: %s\n" 01767 "=== ==> RingTimeout: %s\n" 01768 "=== ==> BargeAllowed: %s\n" 01769 "=== ==> HoldAccess: %s\n" 01770 "=== ==> Stations ...\n", 01771 trunk->name, trunk->device, 01772 S_OR(trunk->autocontext, "(none)"), 01773 ring_timeout, 01774 trunk->barge_disabled ? "No" : "Yes", 01775 sla_hold_str(trunk->hold_access)); 01776 01777 AST_LIST_TRAVERSE(&trunk->stations, station_ref, entry) { 01778 ast_cli(a->fd, "=== ==> Station name: %s\n", station_ref->station->name); 01779 } 01780 01781 ast_cli(a->fd, "=== ---------------------------------------------------------\n===\n"); 01782 01783 ao2_unlock(trunk); 01784 } 01785 ao2_iterator_destroy(&i); 01786 ast_cli(a->fd, "=============================================================\n\n"); 01787 01788 return CLI_SUCCESS; 01789 }
static enum ast_device_state sla_state | ( | const char * | data | ) | [static] |
Definition at line 6849 of file app_meetme.c.
References ao2_lock, ao2_unlock, AST_DEVICE_INVALID, AST_LIST_TRAVERSE, ast_log(), ast_strdupa, LOG_ERROR, RAII_VAR, sla_find_station(), and sla_state_to_devstate().
Referenced by load_module().
06850 { 06851 char *buf, *station_name, *trunk_name; 06852 RAII_VAR(struct sla_station *, station, NULL, unref_obj); 06853 struct sla_trunk_ref *trunk_ref; 06854 enum ast_device_state res = AST_DEVICE_INVALID; 06855 06856 trunk_name = buf = ast_strdupa(data); 06857 station_name = strsep(&trunk_name, "_"); 06858 06859 station = sla_find_station(station_name); 06860 if (station) { 06861 ao2_lock(station); 06862 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) { 06863 if (!strcasecmp(trunk_name, trunk_ref->trunk->name)) { 06864 res = sla_state_to_devstate(trunk_ref->state); 06865 break; 06866 } 06867 } 06868 ao2_unlock(station); 06869 } 06870 06871 if (res == AST_DEVICE_INVALID) { 06872 ast_log(LOG_ERROR, "Could not determine state for trunk %s on station %s!\n", 06873 trunk_name, station_name); 06874 } 06875 06876 return res; 06877 }
static enum ast_device_state sla_state_to_devstate | ( | enum sla_trunk_state | state | ) | [static] |
Definition at line 5535 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().
05536 { 05537 switch (state) { 05538 case SLA_TRUNK_STATE_IDLE: 05539 return AST_DEVICE_NOT_INUSE; 05540 case SLA_TRUNK_STATE_RINGING: 05541 return AST_DEVICE_RINGING; 05542 case SLA_TRUNK_STATE_UP: 05543 return AST_DEVICE_INUSE; 05544 case SLA_TRUNK_STATE_ONHOLD: 05545 case SLA_TRUNK_STATE_ONHOLD_BYME: 05546 return AST_DEVICE_ONHOLD; 05547 } 05548 05549 return AST_DEVICE_UNKNOWN; 05550 }
static int sla_station_cmp | ( | void * | obj, | |
void * | arg, | |||
int | flags | |||
) | [static] |
Definition at line 6950 of file app_meetme.c.
References CMP_MATCH, and CMP_STOP.
Referenced by sla_load_config().
06951 { 06952 struct sla_station *station = obj, *station2 = arg; 06953 06954 return !strcasecmp(station->name, station2->name) ? CMP_MATCH | CMP_STOP : 0; 06955 }
static void sla_station_destructor | ( | void * | obj | ) | [static] |
Definition at line 6903 of file app_meetme.c.
References ast_context_remove_extension(), ast_debug, AST_LIST_TRAVERSE, AST_MAX_APP, AST_MAX_EXTENSION, ast_string_field_free_memory, ast_strlen_zero(), exten, PRIORITY_HINT, sla_registrar, and sla_station_release_refs().
Referenced by sla_build_station().
06904 { 06905 struct sla_station *station = obj; 06906 06907 ast_debug(1, "sla_station destructor for '%s'\n", station->name); 06908 06909 if (!ast_strlen_zero(station->autocontext)) { 06910 struct sla_trunk_ref *trunk_ref; 06911 06912 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) { 06913 char exten[AST_MAX_EXTENSION]; 06914 char hint[AST_MAX_APP]; 06915 snprintf(exten, sizeof(exten), "%s_%s", station->name, trunk_ref->trunk->name); 06916 snprintf(hint, sizeof(hint), "SLA:%s", exten); 06917 ast_context_remove_extension(station->autocontext, exten, 06918 1, sla_registrar); 06919 ast_context_remove_extension(station->autocontext, hint, 06920 PRIORITY_HINT, sla_registrar); 06921 } 06922 } 06923 06924 sla_station_release_refs(station, NULL, 0); 06925 06926 ast_string_field_free_memory(station); 06927 }
static int sla_station_exec | ( | struct ast_channel * | chan, | |
const char * | data | |||
) | [static] |
Definition at line 6529 of file app_meetme.c.
References admin_exec(), ALL_TRUNK_REFS, answer_trunk_chan(), ao2_lock, ao2_ref, ao2_unlock, 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_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(), LOG_NOTICE, LOG_WARNING, MAX_CONFNUM, pbx_builtin_setvar_helper(), RAII_VAR, sla, sla_change_trunk_state(), sla_choose_idle_trunk(), SLA_EVENT_DIAL_STATE, SLA_EVENT_RINGING_TRUNK, sla_find_station(), sla_find_trunk_ref_byname(), sla_queue_event(), sla_ringing_trunk_destroy(), SLA_TRUNK_STATE_IDLE, SLA_TRUNK_STATE_ONHOLD_BYME, SLA_TRUNK_STATE_RINGING, SLA_TRUNK_STATE_UP, sla_ringing_trunk::trunk, and dial_trunk_args::trunk_ref.
Referenced by load_module().
06530 { 06531 char *station_name, *trunk_name; 06532 RAII_VAR(struct sla_station *, station, NULL, unref_obj); 06533 RAII_VAR(struct sla_trunk_ref *, trunk_ref, NULL, unref_obj); 06534 char conf_name[MAX_CONFNUM]; 06535 struct ast_flags64 conf_flags = { 0 }; 06536 struct ast_conference *conf; 06537 06538 if (ast_strlen_zero(data)) { 06539 ast_log(LOG_WARNING, "Invalid Arguments to SLAStation!\n"); 06540 pbx_builtin_setvar_helper(chan, "SLASTATION_STATUS", "FAILURE"); 06541 return 0; 06542 } 06543 06544 trunk_name = ast_strdupa(data); 06545 station_name = strsep(&trunk_name, "_"); 06546 06547 if (ast_strlen_zero(station_name)) { 06548 ast_log(LOG_WARNING, "Invalid Arguments to SLAStation!\n"); 06549 pbx_builtin_setvar_helper(chan, "SLASTATION_STATUS", "FAILURE"); 06550 return 0; 06551 } 06552 06553 station = sla_find_station(station_name); 06554 06555 if (!station) { 06556 ast_log(LOG_WARNING, "Station '%s' not found!\n", station_name); 06557 pbx_builtin_setvar_helper(chan, "SLASTATION_STATUS", "FAILURE"); 06558 return 0; 06559 } 06560 06561 ao2_lock(station); 06562 if (!ast_strlen_zero(trunk_name)) { 06563 trunk_ref = sla_find_trunk_ref_byname(station, trunk_name); 06564 } else { 06565 trunk_ref = sla_choose_idle_trunk(station); 06566 } 06567 ao2_unlock(station); 06568 06569 if (!trunk_ref) { 06570 if (ast_strlen_zero(trunk_name)) 06571 ast_log(LOG_NOTICE, "No trunks available for call.\n"); 06572 else { 06573 ast_log(LOG_NOTICE, "Can't join existing call on trunk " 06574 "'%s' due to access controls.\n", trunk_name); 06575 } 06576 pbx_builtin_setvar_helper(chan, "SLASTATION_STATUS", "CONGESTION"); 06577 return 0; 06578 } 06579 06580 if (trunk_ref->state == SLA_TRUNK_STATE_ONHOLD_BYME) { 06581 if (ast_atomic_dec_and_test((int *) &trunk_ref->trunk->hold_stations) == 1) 06582 sla_change_trunk_state(trunk_ref->trunk, SLA_TRUNK_STATE_UP, ALL_TRUNK_REFS, NULL); 06583 else { 06584 trunk_ref->state = SLA_TRUNK_STATE_UP; 06585 ast_devstate_changed(AST_DEVICE_INUSE, AST_DEVSTATE_CACHABLE, 06586 "SLA:%s_%s", station->name, trunk_ref->trunk->name); 06587 } 06588 } else if (trunk_ref->state == SLA_TRUNK_STATE_RINGING) { 06589 struct sla_ringing_trunk *ringing_trunk; 06590 06591 ast_mutex_lock(&sla.lock); 06592 AST_LIST_TRAVERSE_SAFE_BEGIN(&sla.ringing_trunks, ringing_trunk, entry) { 06593 if (ringing_trunk->trunk == trunk_ref->trunk) { 06594 AST_LIST_REMOVE_CURRENT(entry); 06595 break; 06596 } 06597 } 06598 AST_LIST_TRAVERSE_SAFE_END 06599 ast_mutex_unlock(&sla.lock); 06600 06601 if (ringing_trunk) { 06602 answer_trunk_chan(ringing_trunk->trunk->chan); 06603 sla_change_trunk_state(ringing_trunk->trunk, SLA_TRUNK_STATE_UP, ALL_TRUNK_REFS, NULL); 06604 06605 sla_ringing_trunk_destroy(ringing_trunk); 06606 06607 /* Queue up reprocessing ringing trunks, and then ringing stations again */ 06608 sla_queue_event(SLA_EVENT_RINGING_TRUNK); 06609 sla_queue_event(SLA_EVENT_DIAL_STATE); 06610 } 06611 } 06612 06613 trunk_ref->chan = chan; 06614 06615 if (!trunk_ref->trunk->chan) { 06616 ast_mutex_t cond_lock; 06617 ast_cond_t cond; 06618 pthread_t dont_care; 06619 struct dial_trunk_args args = { 06620 .trunk_ref = trunk_ref, 06621 .station = station, 06622 .cond_lock = &cond_lock, 06623 .cond = &cond, 06624 }; 06625 ao2_ref(trunk_ref, 1); 06626 ao2_ref(station, 1); 06627 sla_change_trunk_state(trunk_ref->trunk, SLA_TRUNK_STATE_UP, ALL_TRUNK_REFS, NULL); 06628 /* Create a thread to dial the trunk and dump it into the conference. 06629 * However, we want to wait until the trunk has been dialed and the 06630 * conference is created before continuing on here. */ 06631 ast_autoservice_start(chan); 06632 ast_mutex_init(&cond_lock); 06633 ast_cond_init(&cond, NULL); 06634 ast_mutex_lock(&cond_lock); 06635 ast_pthread_create_detached_background(&dont_care, NULL, dial_trunk, &args); 06636 ast_cond_wait(&cond, &cond_lock); 06637 ast_mutex_unlock(&cond_lock); 06638 ast_mutex_destroy(&cond_lock); 06639 ast_cond_destroy(&cond); 06640 ast_autoservice_stop(chan); 06641 if (!trunk_ref->trunk->chan) { 06642 ast_debug(1, "Trunk didn't get created. chan: %lx\n", (unsigned long) trunk_ref->trunk->chan); 06643 pbx_builtin_setvar_helper(chan, "SLASTATION_STATUS", "CONGESTION"); 06644 sla_change_trunk_state(trunk_ref->trunk, SLA_TRUNK_STATE_IDLE, ALL_TRUNK_REFS, NULL); 06645 trunk_ref->chan = NULL; 06646 return 0; 06647 } 06648 } 06649 06650 if (ast_atomic_fetchadd_int((int *) &trunk_ref->trunk->active_stations, 1) == 0 && 06651 trunk_ref->trunk->on_hold) { 06652 trunk_ref->trunk->on_hold = 0; 06653 ast_indicate(trunk_ref->trunk->chan, AST_CONTROL_UNHOLD); 06654 sla_change_trunk_state(trunk_ref->trunk, SLA_TRUNK_STATE_UP, ALL_TRUNK_REFS, NULL); 06655 } 06656 06657 snprintf(conf_name, sizeof(conf_name), "SLA_%s", trunk_ref->trunk->name); 06658 ast_set_flag64(&conf_flags, 06659 CONFFLAG_QUIET | CONFFLAG_MARKEDEXIT | CONFFLAG_PASS_DTMF | CONFFLAG_SLA_STATION); 06660 ast_answer(chan); 06661 conf = build_conf(conf_name, "", "", 0, 0, 1, chan, NULL); 06662 if (conf) { 06663 conf_run(chan, conf, &conf_flags, NULL); 06664 dispose_conf(conf); 06665 conf = NULL; 06666 } 06667 trunk_ref->chan = NULL; 06668 if (ast_atomic_dec_and_test((int *) &trunk_ref->trunk->active_stations) && 06669 trunk_ref->state != SLA_TRUNK_STATE_ONHOLD_BYME) { 06670 strncat(conf_name, ",K", sizeof(conf_name) - strlen(conf_name) - 1); 06671 admin_exec(NULL, conf_name); 06672 trunk_ref->trunk->hold_stations = 0; 06673 sla_change_trunk_state(trunk_ref->trunk, SLA_TRUNK_STATE_IDLE, ALL_TRUNK_REFS, NULL); 06674 } 06675 06676 pbx_builtin_setvar_helper(chan, "SLASTATION_STATUS", "SUCCESS"); 06677 06678 return 0; 06679 }
static int sla_station_hash | ( | const void * | obj, | |
const int | flags | |||
) | [static] |
Definition at line 6943 of file app_meetme.c.
References ast_str_case_hash().
Referenced by sla_load_config().
06944 { 06945 const struct sla_station *station = obj; 06946 06947 return ast_str_case_hash(station->name); 06948 }
static int sla_station_is_marked | ( | void * | obj, | |
void * | arg, | |||
int | flags | |||
) | [static] |
Definition at line 7361 of file app_meetme.c.
References ao2_lock, ao2_ref, ao2_unlock, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, CMP_MATCH, and sla_station_release_refs().
Referenced by sla_load_config().
07362 { 07363 struct sla_station *station = obj; 07364 07365 ao2_lock(station); 07366 07367 if (station->mark) { 07368 /* Only remove all of the trunk references if the station itself is going away */ 07369 sla_station_release_refs(station, NULL, 0); 07370 } else { 07371 struct sla_trunk_ref *trunk_ref; 07372 07373 /* Otherwise only remove references to trunks no longer in the config */ 07374 AST_LIST_TRAVERSE_SAFE_BEGIN(&station->trunks, trunk_ref, entry) { 07375 if (!trunk_ref->mark) { 07376 continue; 07377 } 07378 AST_LIST_REMOVE_CURRENT(entry); 07379 ao2_ref(trunk_ref, -1); 07380 } 07381 AST_LIST_TRAVERSE_SAFE_END 07382 } 07383 07384 ao2_unlock(station); 07385 07386 return station->mark ? CMP_MATCH : 0; 07387 }
static int sla_station_mark | ( | void * | obj, | |
void * | arg, | |||
int | flags | |||
) | [static] |
Definition at line 7315 of file app_meetme.c.
References ao2_lock, ao2_unlock, and AST_LIST_TRAVERSE.
Referenced by sla_load_config().
07316 { 07317 struct sla_station *station = obj; 07318 struct sla_trunk_ref *trunk_ref; 07319 07320 ao2_lock(station); 07321 07322 station->mark = 1; 07323 07324 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) { 07325 trunk_ref->mark = 1; 07326 } 07327 07328 ao2_unlock(station); 07329 07330 return 0; 07331 }
static void sla_station_ref_destructor | ( | void * | obj | ) | [static] |
Definition at line 5462 of file app_meetme.c.
References ao2_ref.
Referenced by sla_create_station_ref().
05463 { 05464 struct sla_station_ref *station_ref = obj; 05465 05466 if (station_ref->station) { 05467 ao2_ref(station_ref->station, -1); 05468 station_ref->station = NULL; 05469 } 05470 }
static int sla_station_release_refs | ( | void * | obj, | |
void * | arg, | |||
int | flags | |||
) | [static] |
Definition at line 6891 of file app_meetme.c.
References ao2_ref, and AST_LIST_REMOVE_HEAD.
Referenced by sla_destroy(), sla_station_destructor(), and sla_station_is_marked().
06892 { 06893 struct sla_station *station = obj; 06894 struct sla_trunk_ref *trunk_ref; 06895 06896 while ((trunk_ref = AST_LIST_REMOVE_HEAD(&station->trunks, entry))) { 06897 ao2_ref(trunk_ref, -1); 06898 } 06899 06900 return 0; 06901 }
static void sla_stop_ringing_station | ( | struct sla_ringing_station * | ringing_station, | |
enum sla_station_hangup | hangup | |||
) | [static] |
Definition at line 5655 of file app_meetme.c.
References ast_dial_destroy(), ast_dial_join(), AST_LIST_INSERT_TAIL, AST_LIST_TRAVERSE, sla, sla_create_station_ref(), sla_ringing_station_destroy(), 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().
05657 { 05658 struct sla_ringing_trunk *ringing_trunk; 05659 struct sla_trunk_ref *trunk_ref; 05660 struct sla_station_ref *station_ref; 05661 05662 ast_dial_join(ringing_station->station->dial); 05663 ast_dial_destroy(ringing_station->station->dial); 05664 ringing_station->station->dial = NULL; 05665 05666 if (hangup == SLA_STATION_HANGUP_NORMAL) 05667 goto done; 05668 05669 /* If the station is being hung up because of a timeout, then add it to the 05670 * list of timed out stations on each of the ringing trunks. This is so 05671 * that when doing further processing to figure out which stations should be 05672 * ringing, which trunk to answer, determining timeouts, etc., we know which 05673 * ringing trunks we should ignore. */ 05674 AST_LIST_TRAVERSE(&sla.ringing_trunks, ringing_trunk, entry) { 05675 AST_LIST_TRAVERSE(&ringing_station->station->trunks, trunk_ref, entry) { 05676 if (ringing_trunk->trunk == trunk_ref->trunk) 05677 break; 05678 } 05679 if (!trunk_ref) 05680 continue; 05681 if (!(station_ref = sla_create_station_ref(ringing_station->station))) 05682 continue; 05683 AST_LIST_INSERT_TAIL(&ringing_trunk->timed_out_stations, station_ref, entry); 05684 } 05685 05686 done: 05687 sla_ringing_station_destroy(ringing_station); 05688 }
static void sla_stop_ringing_trunk | ( | struct sla_ringing_trunk * | ringing_trunk | ) | [static] |
Definition at line 5639 of file app_meetme.c.
References admin_exec(), ALL_TRUNK_REFS, ao2_ref, AST_LIST_REMOVE_HEAD, sla_change_trunk_state(), sla_ringing_trunk_destroy(), SLA_TRUNK_STATE_IDLE, and sla_ringing_trunk::trunk.
Referenced by sla_calc_trunk_timeouts().
05640 { 05641 char buf[80]; 05642 struct sla_station_ref *station_ref; 05643 05644 snprintf(buf, sizeof(buf), "SLA_%s,K", ringing_trunk->trunk->name); 05645 admin_exec(NULL, buf); 05646 sla_change_trunk_state(ringing_trunk->trunk, SLA_TRUNK_STATE_IDLE, ALL_TRUNK_REFS, NULL); 05647 05648 while ((station_ref = AST_LIST_REMOVE_HEAD(&ringing_trunk->timed_out_stations, entry))) { 05649 ao2_ref(station_ref, -1); 05650 } 05651 05652 sla_ringing_trunk_destroy(ringing_trunk); 05653 }
static void* sla_thread | ( | void * | data | ) | [static] |
Definition at line 6313 of file app_meetme.c.
References ast_cond_timedwait, ast_cond_wait, AST_LIST_EMPTY, AST_LIST_REMOVE_HEAD, ast_mutex_lock, ast_mutex_unlock, sla, sla_event_destroy(), SLA_EVENT_DIAL_STATE, SLA_EVENT_HOLD, SLA_EVENT_RINGING_TRUNK, sla_failed_station_destroy(), sla_handle_dial_state_event(), sla_handle_hold_event(), sla_handle_ringing_trunk_event(), sla_process_timers(), sla_ringing_station_destroy(), and sla_event::type.
Referenced by sla_load_config().
06314 { 06315 struct sla_failed_station *failed_station; 06316 struct sla_ringing_station *ringing_station; 06317 06318 ast_mutex_lock(&sla.lock); 06319 06320 while (!sla.stop) { 06321 struct sla_event *event; 06322 struct timespec ts = { 0, }; 06323 unsigned int have_timeout = 0; 06324 06325 if (AST_LIST_EMPTY(&sla.event_q)) { 06326 if ((have_timeout = sla_process_timers(&ts))) 06327 ast_cond_timedwait(&sla.cond, &sla.lock, &ts); 06328 else 06329 ast_cond_wait(&sla.cond, &sla.lock); 06330 if (sla.stop) 06331 break; 06332 } 06333 06334 if (have_timeout) 06335 sla_process_timers(NULL); 06336 06337 while ((event = AST_LIST_REMOVE_HEAD(&sla.event_q, entry))) { 06338 ast_mutex_unlock(&sla.lock); 06339 switch (event->type) { 06340 case SLA_EVENT_HOLD: 06341 sla_handle_hold_event(event); 06342 break; 06343 case SLA_EVENT_DIAL_STATE: 06344 sla_handle_dial_state_event(); 06345 break; 06346 case SLA_EVENT_RINGING_TRUNK: 06347 sla_handle_ringing_trunk_event(); 06348 break; 06349 } 06350 sla_event_destroy(event); 06351 ast_mutex_lock(&sla.lock); 06352 } 06353 } 06354 06355 ast_mutex_unlock(&sla.lock); 06356 06357 while ((ringing_station = AST_LIST_REMOVE_HEAD(&sla.ringing_stations, entry))) { 06358 sla_ringing_station_destroy(ringing_station); 06359 } 06360 06361 while ((failed_station = AST_LIST_REMOVE_HEAD(&sla.failed_stations, entry))) { 06362 sla_failed_station_destroy(failed_station); 06363 } 06364 06365 return NULL; 06366 }
static int sla_trunk_cmp | ( | void * | obj, | |
void * | arg, | |||
int | flags | |||
) | [static] |
Definition at line 6936 of file app_meetme.c.
References CMP_MATCH, and CMP_STOP.
Referenced by sla_load_config().
static void sla_trunk_destructor | ( | void * | obj | ) | [static] |
Definition at line 6996 of file app_meetme.c.
References ast_context_remove_extension(), ast_debug, ast_string_field_free_memory, ast_strlen_zero(), sla_registrar, and sla_trunk_release_refs().
Referenced by sla_build_trunk().
06997 { 06998 struct sla_trunk *trunk = obj; 06999 07000 ast_debug(1, "sla_trunk destructor for '%s'\n", trunk->name); 07001 07002 if (!ast_strlen_zero(trunk->autocontext)) { 07003 ast_context_remove_extension(trunk->autocontext, "s", 1, sla_registrar); 07004 } 07005 07006 sla_trunk_release_refs(trunk, NULL, 0); 07007 07008 ast_string_field_free_memory(trunk); 07009 }
static int sla_trunk_exec | ( | struct ast_channel * | chan, | |
const char * | data | |||
) | [static] |
Definition at line 6751 of file app_meetme.c.
References ALL_TRUNK_REFS, args, AST_APP_ARG, ast_app_parse_options(), AST_CONTROL_RINGING, AST_DECLARE_APP_ARGS, ast_indicate(), AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_set_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(), RAII_VAR, sla, sla_change_trunk_state(), SLA_EVENT_RINGING_TRUNK, sla_find_trunk(), sla_queue_event(), sla_ringing_trunk_destroy(), SLA_TRUNK_OPT_ARG_ARRAY_SIZE, SLA_TRUNK_OPT_MOH, SLA_TRUNK_STATE_IDLE, and sla_ringing_trunk::trunk.
Referenced by load_module().
06752 { 06753 char conf_name[MAX_CONFNUM]; 06754 struct ast_conference *conf; 06755 struct ast_flags64 conf_flags = { 0 }; 06756 RAII_VAR(struct sla_trunk *, trunk, NULL, unref_obj); 06757 struct sla_ringing_trunk *ringing_trunk; 06758 AST_DECLARE_APP_ARGS(args, 06759 AST_APP_ARG(trunk_name); 06760 AST_APP_ARG(options); 06761 ); 06762 char *opts[SLA_TRUNK_OPT_ARG_ARRAY_SIZE] = { NULL, }; 06763 struct ast_flags opt_flags = { 0 }; 06764 char *parse; 06765 06766 if (ast_strlen_zero(data)) { 06767 ast_log(LOG_ERROR, "The SLATrunk application requires an argument, the trunk name\n"); 06768 return -1; 06769 } 06770 06771 parse = ast_strdupa(data); 06772 AST_STANDARD_APP_ARGS(args, parse); 06773 if (args.argc == 2) { 06774 if (ast_app_parse_options(sla_trunk_opts, &opt_flags, opts, args.options)) { 06775 ast_log(LOG_ERROR, "Error parsing options for SLATrunk\n"); 06776 return -1; 06777 } 06778 } 06779 06780 trunk = sla_find_trunk(args.trunk_name); 06781 06782 if (!trunk) { 06783 ast_log(LOG_ERROR, "SLA Trunk '%s' not found!\n", args.trunk_name); 06784 pbx_builtin_setvar_helper(chan, "SLATRUNK_STATUS", "FAILURE"); 06785 return 0; 06786 } 06787 06788 if (trunk->chan) { 06789 ast_log(LOG_ERROR, "Call came in on %s, but the trunk is already in use!\n", 06790 args.trunk_name); 06791 pbx_builtin_setvar_helper(chan, "SLATRUNK_STATUS", "FAILURE"); 06792 return 0; 06793 } 06794 06795 trunk->chan = chan; 06796 06797 if (!(ringing_trunk = queue_ringing_trunk(trunk))) { 06798 pbx_builtin_setvar_helper(chan, "SLATRUNK_STATUS", "FAILURE"); 06799 return 0; 06800 } 06801 06802 snprintf(conf_name, sizeof(conf_name), "SLA_%s", args.trunk_name); 06803 conf = build_conf(conf_name, "", "", 1, 1, 1, chan, NULL); 06804 if (!conf) { 06805 pbx_builtin_setvar_helper(chan, "SLATRUNK_STATUS", "FAILURE"); 06806 return 0; 06807 } 06808 ast_set_flag64(&conf_flags, 06809 CONFFLAG_QUIET | CONFFLAG_MARKEDEXIT | CONFFLAG_MARKEDUSER | CONFFLAG_PASS_DTMF | CONFFLAG_NO_AUDIO_UNTIL_UP); 06810 06811 if (ast_test_flag(&opt_flags, SLA_TRUNK_OPT_MOH)) { 06812 ast_indicate(chan, -1); 06813 ast_set_flag64(&conf_flags, CONFFLAG_MOH); 06814 } else 06815 ast_indicate(chan, AST_CONTROL_RINGING); 06816 06817 conf_run(chan, conf, &conf_flags, opts); 06818 dispose_conf(conf); 06819 conf = NULL; 06820 trunk->chan = NULL; 06821 trunk->on_hold = 0; 06822 06823 sla_change_trunk_state(trunk, SLA_TRUNK_STATE_IDLE, ALL_TRUNK_REFS, NULL); 06824 06825 if (!pbx_builtin_getvar_helper(chan, "SLATRUNK_STATUS")) 06826 pbx_builtin_setvar_helper(chan, "SLATRUNK_STATUS", "SUCCESS"); 06827 06828 /* Remove the entry from the list of ringing trunks if it is still there. */ 06829 ast_mutex_lock(&sla.lock); 06830 AST_LIST_TRAVERSE_SAFE_BEGIN(&sla.ringing_trunks, ringing_trunk, entry) { 06831 if (ringing_trunk->trunk == trunk) { 06832 AST_LIST_REMOVE_CURRENT(entry); 06833 break; 06834 } 06835 } 06836 AST_LIST_TRAVERSE_SAFE_END; 06837 ast_mutex_unlock(&sla.lock); 06838 if (ringing_trunk) { 06839 sla_ringing_trunk_destroy(ringing_trunk); 06840 pbx_builtin_setvar_helper(chan, "SLATRUNK_STATUS", "UNANSWERED"); 06841 /* Queue reprocessing of ringing trunks to make stations stop ringing 06842 * that shouldn't be ringing after this trunk stopped. */ 06843 sla_queue_event(SLA_EVENT_RINGING_TRUNK); 06844 } 06845 06846 return 0; 06847 }
static int sla_trunk_hash | ( | const void * | obj, | |
const int | flags | |||
) | [static] |
Definition at line 6929 of file app_meetme.c.
References ast_str_case_hash().
Referenced by sla_load_config().
06930 { 06931 const struct sla_trunk *trunk = obj; 06932 06933 return ast_str_case_hash(trunk->name); 06934 }
static int sla_trunk_is_marked | ( | void * | obj, | |
void * | arg, | |||
int | flags | |||
) | [static] |
Definition at line 7333 of file app_meetme.c.
References ao2_lock, ao2_ref, ao2_unlock, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, CMP_MATCH, and sla_trunk_release_refs().
Referenced by sla_load_config().
07334 { 07335 struct sla_trunk *trunk = obj; 07336 07337 ao2_lock(trunk); 07338 07339 if (trunk->mark) { 07340 /* Only remove all of the station references if the trunk itself is going away */ 07341 sla_trunk_release_refs(trunk, NULL, 0); 07342 } else { 07343 struct sla_station_ref *station_ref; 07344 07345 /* Otherwise only remove references to stations no longer in the config */ 07346 AST_LIST_TRAVERSE_SAFE_BEGIN(&trunk->stations, station_ref, entry) { 07347 if (!station_ref->mark) { 07348 continue; 07349 } 07350 AST_LIST_REMOVE_CURRENT(entry); 07351 ao2_ref(station_ref, -1); 07352 } 07353 AST_LIST_TRAVERSE_SAFE_END 07354 } 07355 07356 ao2_unlock(trunk); 07357 07358 return trunk->mark ? CMP_MATCH : 0; 07359 }
static int sla_trunk_mark | ( | void * | obj, | |
void * | arg, | |||
int | flags | |||
) | [static] |
Definition at line 7297 of file app_meetme.c.
References ao2_lock, ao2_unlock, and AST_LIST_TRAVERSE.
Referenced by sla_load_config().
07298 { 07299 struct sla_trunk *trunk = obj; 07300 struct sla_station_ref *station_ref; 07301 07302 ao2_lock(trunk); 07303 07304 trunk->mark = 1; 07305 07306 AST_LIST_TRAVERSE(&trunk->stations, station_ref, entry) { 07307 station_ref->mark = 1; 07308 } 07309 07310 ao2_unlock(trunk); 07311 07312 return 0; 07313 }
static void sla_trunk_ref_destructor | ( | void * | obj | ) | [static] |
Definition at line 6681 of file app_meetme.c.
References ao2_ref.
Referenced by create_trunk_ref().
06682 { 06683 struct sla_trunk_ref *trunk_ref = obj; 06684 06685 if (trunk_ref->trunk) { 06686 ao2_ref(trunk_ref->trunk, -1); 06687 trunk_ref->trunk = NULL; 06688 } 06689 }
static int sla_trunk_release_refs | ( | void * | obj, | |
void * | arg, | |||
int | flags | |||
) | [static] |
Definition at line 6879 of file app_meetme.c.
References ao2_ref, and AST_LIST_REMOVE_HEAD.
Referenced by sla_destroy(), sla_trunk_destructor(), and sla_trunk_is_marked().
06880 { 06881 struct sla_trunk *trunk = obj; 06882 struct sla_station_ref *station_ref; 06883 06884 while ((station_ref = AST_LIST_REMOVE_HEAD(&trunk->stations, entry))) { 06885 ao2_ref(station_ref, -1); 06886 } 06887 06888 return 0; 06889 }
static const char* trunkstate2str | ( | enum sla_trunk_state | state | ) | [static] |
Definition at line 1791 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().
01792 { 01793 #define S(e) case e: return # e; 01794 switch (state) { 01795 S(SLA_TRUNK_STATE_IDLE) 01796 S(SLA_TRUNK_STATE_RINGING) 01797 S(SLA_TRUNK_STATE_UP) 01798 S(SLA_TRUNK_STATE_ONHOLD) 01799 S(SLA_TRUNK_STATE_ONHOLD_BYME) 01800 } 01801 return "Uknown State"; 01802 #undef S 01803 }
static void tweak_listen_volume | ( | struct ast_conf_user * | user, | |
enum volume_action | action | |||
) | [static] |
Definition at line 1114 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().
01115 { 01116 tweak_volume(&user->listen, action); 01117 /* attempt to make the adjustment in the channel driver; 01118 if successful, don't adjust in the frame reading routine 01119 */ 01120 if (!set_listen_volume(user, user->listen.desired)) 01121 user->listen.actual = 0; 01122 else 01123 user->listen.actual = user->listen.desired; 01124 }
static void tweak_talk_volume | ( | struct ast_conf_user * | user, | |
enum volume_action | action | |||
) | [static] |
Definition at line 1102 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().
01103 { 01104 tweak_volume(&user->talk, action); 01105 /* attempt to make the adjustment in the channel driver; 01106 if successful, don't adjust in the frame reading routine 01107 */ 01108 if (!set_talk_volume(user, user->talk.desired)) 01109 user->talk.actual = 0; 01110 else 01111 user->talk.actual = user->talk.desired; 01112 }
static void tweak_volume | ( | struct volume * | vol, | |
enum volume_action | action | |||
) | [static] |
Definition at line 1067 of file app_meetme.c.
References volume::desired, VOL_DOWN, and VOL_UP.
Referenced by tweak_listen_volume(), and tweak_talk_volume().
01068 { 01069 switch (action) { 01070 case VOL_UP: 01071 switch (vol->desired) { 01072 case 5: 01073 break; 01074 case 0: 01075 vol->desired = 2; 01076 break; 01077 case -2: 01078 vol->desired = 0; 01079 break; 01080 default: 01081 vol->desired++; 01082 break; 01083 } 01084 break; 01085 case VOL_DOWN: 01086 switch (vol->desired) { 01087 case -5: 01088 break; 01089 case 2: 01090 vol->desired = 0; 01091 break; 01092 case 0: 01093 vol->desired = -2; 01094 break; 01095 default: 01096 vol->desired--; 01097 break; 01098 } 01099 } 01100 }
static int unload_module | ( | void | ) | [static] |
Definition at line 7719 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().
07720 { 07721 int res = 0; 07722 07723 ast_cli_unregister_multiple(cli_meetme, ARRAY_LEN(cli_meetme)); 07724 res = ast_manager_unregister("MeetmeMute"); 07725 res |= ast_manager_unregister("MeetmeUnmute"); 07726 res |= ast_manager_unregister("MeetmeList"); 07727 res |= ast_unregister_application(app4); 07728 res |= ast_unregister_application(app3); 07729 res |= ast_unregister_application(app2); 07730 res |= ast_unregister_application(app); 07731 res |= ast_unregister_application(slastation_app); 07732 res |= ast_unregister_application(slatrunk_app); 07733 07734 #ifdef TEST_FRAMEWORK 07735 AST_TEST_UNREGISTER(test_meetme_data_provider); 07736 #endif 07737 ast_data_unregister(NULL); 07738 07739 ast_devstate_prov_del("Meetme"); 07740 ast_devstate_prov_del("SLA"); 07741 07742 sla_destroy(); 07743 07744 res |= ast_custom_function_unregister(&meetme_info_acf); 07745 ast_unload_realtime("meetme"); 07746 07747 return res; 07748 }
static int user_add_provider_cb | ( | void * | obj, | |
void * | arg, | |||
int | flags | |||
) | [static] |
Definition at line 7570 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().
07571 { 07572 struct ast_data *data_meetme_user; 07573 struct ast_data *data_meetme_user_channel; 07574 struct ast_data *data_meetme_user_volume; 07575 07576 struct ast_conf_user *user = obj; 07577 struct ast_data *data_meetme_users = arg; 07578 07579 data_meetme_user = ast_data_add_node(data_meetme_users, "user"); 07580 if (!data_meetme_user) { 07581 return 0; 07582 } 07583 /* user structure */ 07584 ast_data_add_structure(ast_conf_user, data_meetme_user, user); 07585 07586 /* user's channel */ 07587 data_meetme_user_channel = ast_data_add_node(data_meetme_user, "channel"); 07588 if (!data_meetme_user_channel) { 07589 return 0; 07590 } 07591 07592 ast_channel_data_add_structure(data_meetme_user_channel, user->chan, 1); 07593 07594 /* volume structure */ 07595 data_meetme_user_volume = ast_data_add_node(data_meetme_user, "listen-volume"); 07596 if (!data_meetme_user_volume) { 07597 return 0; 07598 } 07599 ast_data_add_int(data_meetme_user_volume, "desired", user->listen.desired); 07600 ast_data_add_int(data_meetme_user_volume, "actual", user->listen.actual); 07601 07602 data_meetme_user_volume = ast_data_add_node(data_meetme_user, "talk-volume"); 07603 if (!data_meetme_user_volume) { 07604 return 0; 07605 } 07606 ast_data_add_int(data_meetme_user_volume, "desired", user->talk.desired); 07607 ast_data_add_int(data_meetme_user_volume, "actual", user->talk.actual); 07608 07609 return 0; 07610 }
static int user_chan_cb | ( | void * | obj, | |
void * | args, | |||
int | flags | |||
) | [static] |
Definition at line 4792 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 4764 of file app_meetme.c.
References tweak_listen_volume(), and VOL_DOWN.
Referenced by admin_exec().
04765 { 04766 struct ast_conf_user *user = obj; 04767 tweak_listen_volume(user, VOL_DOWN); 04768 return 0; 04769 }
static int user_listen_volup_cb | ( | void * | obj, | |
void * | unused, | |||
int | flags | |||
) | [static] |
Definition at line 4757 of file app_meetme.c.
References tweak_listen_volume(), and VOL_UP.
Referenced by admin_exec().
04758 { 04759 struct ast_conf_user *user = obj; 04760 tweak_listen_volume(user, VOL_UP); 04761 return 0; 04762 }
static int user_max_cmp | ( | void * | obj, | |
void * | arg, | |||
int | flags | |||
) | [static] |
Definition at line 1187 of file app_meetme.c.
References ast_conf_user::user_no.
Referenced by admin_exec(), conf_run(), and meetme_menu_admin().
01188 { 01189 struct ast_conf_user *user = obj; 01190 int *max_no = arg; 01191 01192 if (user->user_no > *max_no) { 01193 *max_no = user->user_no; 01194 } 01195 01196 return 0; 01197 }
static int user_no_cmp | ( | void * | obj, | |
void * | arg, | |||
int | flags | |||
) | [static] |
Definition at line 1175 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 4785 of file app_meetme.c.
References reset_volumes().
Referenced by admin_exec().
04786 { 04787 struct ast_conf_user *user = obj; 04788 reset_volumes(user); 04789 return 0; 04790 }
static int user_set_kickme_cb | ( | void * | obj, | |
void * | check_admin_arg, | |||
int | flags | |||
) | [static] |
Definition at line 2299 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().
02300 { 02301 struct ast_conf_user *user = obj; 02302 /* actual pointer contents of check_admin_arg is irrelevant */ 02303 02304 if (!check_admin_arg || (check_admin_arg && !ast_test_flag64(&user->userflags, CONFFLAG_ADMIN))) { 02305 user->adminflags |= ADMINFLAG_KICKME; 02306 } 02307 return 0; 02308 }
static int user_set_muted_cb | ( | void * | obj, | |
void * | check_admin_arg, | |||
int | flags | |||
) | [static] |
Definition at line 2321 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().
02322 { 02323 struct ast_conf_user *user = obj; 02324 /* actual pointer contents of check_admin_arg is irrelevant */ 02325 02326 if (!check_admin_arg || !ast_test_flag64(&user->userflags, CONFFLAG_ADMIN)) { 02327 user->adminflags |= ADMINFLAG_MUTED; 02328 } 02329 return 0; 02330 }
static int user_set_unmuted_cb | ( | void * | obj, | |
void * | check_admin_arg, | |||
int | flags | |||
) | [static] |
Definition at line 2310 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().
02311 { 02312 struct ast_conf_user *user = obj; 02313 /* actual pointer contents of check_admin_arg is irrelevant */ 02314 02315 if (!check_admin_arg || !ast_test_flag64(&user->userflags, CONFFLAG_ADMIN)) { 02316 user->adminflags &= ~(ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED | ADMINFLAG_T_REQUEST); 02317 } 02318 return 0; 02319 }
static int user_talk_voldown_cb | ( | void * | obj, | |
void * | unused, | |||
int | flags | |||
) | [static] |
Definition at line 4778 of file app_meetme.c.
References tweak_talk_volume(), and VOL_DOWN.
Referenced by admin_exec().
04779 { 04780 struct ast_conf_user *user = obj; 04781 tweak_talk_volume(user, VOL_DOWN); 04782 return 0; 04783 }
static int user_talk_volup_cb | ( | void * | obj, | |
void * | unused, | |||
int | flags | |||
) | [static] |
Definition at line 4771 of file app_meetme.c.
References tweak_talk_volume(), and VOL_UP.
Referenced by admin_exec().
04772 { 04773 struct ast_conf_user *user = obj; 04774 tweak_talk_volume(user, VOL_UP); 04775 return 0; 04776 }
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 979 of file app_meetme.c.
struct ast_cli_entry cli_meetme[] [static] |
Definition at line 1885 of file app_meetme.c.
Definition at line 963 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 988 of file app_meetme.c.
Definition at line 964 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 7650 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 7655 of file app_meetme.c.
struct ast_custom_function meetme_info_acf [static] |
{ .name = "MEETME_INFO", .read = acf_meetme_info, }
Definition at line 7529 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(), queue_ringing_trunk(), sla_calc_station_timeouts(), sla_calc_trunk_timeouts(), sla_check_failed_station(), sla_check_ringing_station(), sla_choose_ringing_trunk(), sla_destroy(), sla_handle_dial_state_event(), sla_handle_ringing_trunk_event(), sla_hangup_stations(), sla_load_config(), sla_queue_event_full(), sla_ring_station(), sla_ring_stations(), sla_station_exec(), sla_stop_ringing_station(), sla_thread(), and sla_trunk_exec().
const char sla_registrar[] = "SLA" [static] |
Definition at line 908 of file app_meetme.c.
Referenced by sla_build_station(), sla_build_trunk(), sla_destroy(), sla_station_destructor(), and sla_trunk_destructor().
struct ao2_container* sla_stations [static] |
Definition at line 905 of file app_meetme.c.
Referenced by sla_build_station(), sla_calc_station_delays(), sla_change_trunk_state(), sla_destroy(), sla_find_station(), sla_in_use(), sla_load_config(), sla_queue_event_conf(), and sla_show_stations().
struct ao2_container* sla_trunks [static] |
Definition at line 906 of file app_meetme.c.
Referenced by sla_build_trunk(), sla_destroy(), sla_find_trunk(), sla_in_use(), sla_load_config(), and sla_show_trunks().
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 962 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().