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, struct dahdi_confinfo *dahdic) |
| static void | meetme_menu_admin (enum menu_modes *menu_mode, int *dtmf, struct ast_conference *conf, struct ast_flags64 *confflags, struct ast_channel *chan, struct ast_conf_user *user) |
| static void | meetme_menu_admin_extended (enum menu_modes *menu_mode, int *dtmf, struct ast_conference *conf, struct ast_flags64 *confflags, struct ast_channel *chan, struct ast_conf_user *user, char *recordingtmp, int recordingtmp_size, struct dahdi_confinfo *dahdic) |
| static void | meetme_menu_normal (enum menu_modes *menu_mode, int *dtmf, struct ast_conference *conf, struct ast_flags64 *confflags, struct ast_channel *chan, struct ast_conf_user *user) |
| static char * | meetme_mute_cmd (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | meetme_show_cmd (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static int | meetmemute (struct mansession *s, const struct message *m, int mute) |
| static enum ast_device_state | meetmestate (const char *data) |
| Callback for devicestate providers. | |
| static struct sla_ringing_trunk * | queue_ringing_trunk (struct sla_trunk *trunk) |
| static void * | recordthread (void *args) |
| static int | reload (void) |
| static void | reset_volumes (struct ast_conf_user *user) |
| static int | rt_extend_conf (const char *confno) |
| static void * | run_station (void *data) |
| static void | send_talking_event (struct ast_channel *chan, struct ast_conference *conf, struct ast_conf_user *user, int talking) |
| static int | set_listen_volume (struct ast_conf_user *user, int volume) |
| static int | set_talk_volume (struct ast_conf_user *user, int volume) |
| static void | set_user_talking (struct ast_channel *chan, struct ast_conference *conf, struct ast_conf_user *user, int talking, int monitor) |
| static void | sla_add_trunk_to_station (struct sla_station *station, struct ast_variable *var) |
| static int | sla_build_station (struct ast_config *cfg, const char *cat) |
| static int | sla_build_trunk (struct ast_config *cfg, const char *cat) |
| static int | sla_calc_station_delays (unsigned int *timeout) |
| Calculate the ring delay for a station. | |
| static int | sla_calc_station_timeouts (unsigned int *timeout) |
| Process station ring timeouts. | |
| static int | sla_calc_trunk_timeouts (unsigned int *timeout) |
| Process trunk ring timeouts. | |
| static void | sla_change_trunk_state (const struct sla_trunk *trunk, enum sla_trunk_state state, enum sla_which_trunk_refs inactive_only, const struct sla_trunk_ref *exclude) |
| static int | sla_check_device (const char *device) |
| static int | sla_check_failed_station (const struct sla_station *station) |
| Check to see if this station has failed to be dialed in the past minute. | |
| static int | sla_check_inuse_station (const struct sla_station *station) |
| Check to see if a station is in use. | |
| static 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 7527 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 7544 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 6724 of file app_meetme.c.
06724 { 06725 SLA_TRUNK_OPT_MOH = (1 << 0), 06726 };
| anonymous enum |
Definition at line 6728 of file app_meetme.c.
06728 { 06729 SLA_TRUNK_OPT_ARG_MOH_CLASS = 0, 06730 SLA_TRUNK_OPT_ARG_ARRAY_SIZE = 1, 06731 };
| 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 7464 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().
07465 { 07466 struct ast_conference *conf; 07467 char *parse; 07468 int result = -2; /* only non-negative numbers valid, -1 is used elsewhere */ 07469 AST_DECLARE_APP_ARGS(args, 07470 AST_APP_ARG(keyword); 07471 AST_APP_ARG(confno); 07472 ); 07473 07474 if (ast_strlen_zero(data)) { 07475 ast_log(LOG_ERROR, "Syntax: MEETME_INFO() requires two arguments\n"); 07476 return -1; 07477 } 07478 07479 parse = ast_strdupa(data); 07480 AST_STANDARD_APP_ARGS(args, parse); 07481 07482 if (ast_strlen_zero(args.keyword)) { 07483 ast_log(LOG_ERROR, "Syntax: MEETME_INFO() requires a keyword\n"); 07484 return -1; 07485 } 07486 07487 if (ast_strlen_zero(args.confno)) { 07488 ast_log(LOG_ERROR, "Syntax: MEETME_INFO() requires a conference number\n"); 07489 return -1; 07490 } 07491 07492 AST_LIST_LOCK(&confs); 07493 AST_LIST_TRAVERSE(&confs, conf, list) { 07494 if (!strcmp(args.confno, conf->confno)) { 07495 result = acf_meetme_info_eval(args.keyword, conf); 07496 break; 07497 } 07498 } 07499 AST_LIST_UNLOCK(&confs); 07500 07501 if (result > -1) { 07502 snprintf(buf, len, "%d", result); 07503 } else if (result == -1) { 07504 ast_log(LOG_NOTICE, "Error: invalid keyword: '%s'\n", args.keyword); 07505 snprintf(buf, len, "0"); 07506 } else if (result == -2) { 07507 ast_log(LOG_NOTICE, "Error: conference (%s) not found\n", args.confno); 07508 snprintf(buf, len, "0"); 07509 } 07510 07511 return 0; 07512 }
| static int acf_meetme_info_eval | ( | const char * | keyword, | |
| const struct ast_conference * | conf | |||
| ) | [static] |
Definition at line 7446 of file app_meetme.c.
References ast_conference::isdynamic, ast_conference::locked, ast_conference::start, and ast_conference::users.
Referenced by acf_meetme_info().
07447 { 07448 if (!strcasecmp("lock", keyword)) { 07449 return conf->locked; 07450 } else if (!strcasecmp("parties", keyword)) { 07451 return conf->users; 07452 } else if (!strcasecmp("activity", keyword)) { 07453 time_t now; 07454 now = time(NULL); 07455 return (now - conf->start); 07456 } else if (!strcasecmp("dynamic", keyword)) { 07457 return conf->isdynamic; 07458 } else { 07459 return -1; 07460 } 07461 07462 }
| static int action_meetmelist | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 5091 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().
05092 { 05093 const char *actionid = astman_get_header(m, "ActionID"); 05094 const char *conference = astman_get_header(m, "Conference"); 05095 char idText[80] = ""; 05096 struct ast_conference *cnf; 05097 struct ast_conf_user *user; 05098 struct ao2_iterator user_iter; 05099 int total = 0; 05100 05101 if (!ast_strlen_zero(actionid)) 05102 snprintf(idText, sizeof(idText), "ActionID: %s\r\n", actionid); 05103 05104 if (AST_LIST_EMPTY(&confs)) { 05105 astman_send_error(s, m, "No active conferences."); 05106 return 0; 05107 } 05108 05109 astman_send_listack(s, m, "Meetme user list will follow", "start"); 05110 05111 /* Find the right conference */ 05112 AST_LIST_LOCK(&confs); 05113 AST_LIST_TRAVERSE(&confs, cnf, list) { 05114 /* If we ask for one particular, and this isn't it, skip it */ 05115 if (!ast_strlen_zero(conference) && strcmp(cnf->confno, conference)) 05116 continue; 05117 05118 /* Show all the users */ 05119 user_iter = ao2_iterator_init(cnf->usercontainer, 0); 05120 while ((user = ao2_iterator_next(&user_iter))) { 05121 total++; 05122 astman_append(s, 05123 "Event: MeetmeList\r\n" 05124 "%s" 05125 "Conference: %s\r\n" 05126 "UserNumber: %d\r\n" 05127 "CallerIDNum: %s\r\n" 05128 "CallerIDName: %s\r\n" 05129 "ConnectedLineNum: %s\r\n" 05130 "ConnectedLineName: %s\r\n" 05131 "Channel: %s\r\n" 05132 "Admin: %s\r\n" 05133 "Role: %s\r\n" 05134 "MarkedUser: %s\r\n" 05135 "Muted: %s\r\n" 05136 "Talking: %s\r\n" 05137 "\r\n", 05138 idText, 05139 cnf->confno, 05140 user->user_no, 05141 S_COR(user->chan->caller.id.number.valid, user->chan->caller.id.number.str, "<unknown>"), 05142 S_COR(user->chan->caller.id.name.valid, user->chan->caller.id.name.str, "<no name>"), 05143 S_COR(user->chan->connected.id.number.valid, user->chan->connected.id.number.str, "<unknown>"), 05144 S_COR(user->chan->connected.id.name.valid, user->chan->connected.id.name.str, "<no name>"), 05145 user->chan->name, 05146 ast_test_flag64(&user->userflags, CONFFLAG_ADMIN) ? "Yes" : "No", 05147 ast_test_flag64(&user->userflags, CONFFLAG_MONITOR) ? "Listen only" : ast_test_flag64(&user->userflags, CONFFLAG_TALKER) ? "Talk only" : "Talk and listen", 05148 ast_test_flag64(&user->userflags, CONFFLAG_MARKEDUSER) ? "Yes" : "No", 05149 user->adminflags & ADMINFLAG_MUTED ? "By admin" : user->adminflags & ADMINFLAG_SELFMUTED ? "By self" : "No", 05150 user->talking > 0 ? "Yes" : user->talking == 0 ? "No" : "Not monitored"); 05151 ao2_ref(user, -1); 05152 } 05153 ao2_iterator_destroy(&user_iter); 05154 } 05155 AST_LIST_UNLOCK(&confs); 05156 /* Send final confirmation */ 05157 astman_append(s, 05158 "Event: MeetmeListComplete\r\n" 05159 "EventList: Complete\r\n" 05160 "ListItems: %d\r\n" 05161 "%s" 05162 "\r\n", total, idText); 05163 return 0; 05164 }
| static int action_meetmemute | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 5081 of file app_meetme.c.
References meetmemute().
Referenced by load_module().
05082 { 05083 return meetmemute(s, m, 1); 05084 }
| static int action_meetmeunmute | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 5086 of file app_meetme.c.
References meetmemute().
Referenced by load_module().
05087 { 05088 return meetmemute(s, m, 0); 05089 }
| static int admin_exec | ( | struct ast_channel * | chan, | |
| const char * | data | |||
| ) | [static] |
The MeetMeadmin application.
MeetMeAdmin(confno, command, caller)
Definition at line 4793 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().
04793 { 04794 char *params; 04795 struct ast_conference *cnf; 04796 struct ast_conf_user *user = NULL; 04797 AST_DECLARE_APP_ARGS(args, 04798 AST_APP_ARG(confno); 04799 AST_APP_ARG(command); 04800 AST_APP_ARG(user); 04801 ); 04802 int res = 0; 04803 04804 if (ast_strlen_zero(data)) { 04805 ast_log(LOG_WARNING, "MeetMeAdmin requires an argument!\n"); 04806 pbx_builtin_setvar_helper(chan, "MEETMEADMINSTATUS", "NOPARSE"); 04807 return -1; 04808 } 04809 04810 params = ast_strdupa(data); 04811 AST_STANDARD_APP_ARGS(args, params); 04812 04813 if (!args.command) { 04814 ast_log(LOG_WARNING, "MeetmeAdmin requires a command!\n"); 04815 pbx_builtin_setvar_helper(chan, "MEETMEADMINSTATUS", "NOPARSE"); 04816 return -1; 04817 } 04818 04819 AST_LIST_LOCK(&confs); 04820 AST_LIST_TRAVERSE(&confs, cnf, list) { 04821 if (!strcmp(cnf->confno, args.confno)) 04822 break; 04823 } 04824 04825 if (!cnf) { 04826 ast_log(LOG_WARNING, "Conference number '%s' not found!\n", args.confno); 04827 AST_LIST_UNLOCK(&confs); 04828 pbx_builtin_setvar_helper(chan, "MEETMEADMINSTATUS", "NOTFOUND"); 04829 return 0; 04830 } 04831 04832 ast_atomic_fetchadd_int(&cnf->refcount, 1); 04833 04834 if (args.user) { 04835 user = find_user(cnf, args.user); 04836 if (!user) { 04837 ast_log(LOG_NOTICE, "Specified User not found!\n"); 04838 res = -2; 04839 goto usernotfound; 04840 } 04841 } else { 04842 /* fail for commands that require a user */ 04843 switch (*args.command) { 04844 case 'm': /* Unmute */ 04845 case 'M': /* Mute */ 04846 case 't': /* Lower user's talk volume */ 04847 case 'T': /* Raise user's talk volume */ 04848 case 'u': /* Lower user's listen volume */ 04849 case 'U': /* Raise user's listen volume */ 04850 case 'r': /* Reset user's volume level */ 04851 case 'k': /* Kick user */ 04852 res = -2; 04853 ast_log(LOG_NOTICE, "No user specified!\n"); 04854 goto usernotfound; 04855 default: 04856 break; 04857 } 04858 } 04859 04860 switch (*args.command) { 04861 case 76: /* L: Lock */ 04862 cnf->locked = 1; 04863 break; 04864 case 108: /* l: Unlock */ 04865 cnf->locked = 0; 04866 break; 04867 case 75: /* K: kick all users */ 04868 ao2_callback(cnf->usercontainer, OBJ_NODATA, user_set_kickme_cb, NULL); 04869 break; 04870 case 101: /* e: Eject last user*/ 04871 { 04872 int max_no = 0; 04873 struct ast_conf_user *eject_user; 04874 04875 ao2_callback(cnf->usercontainer, OBJ_NODATA, user_max_cmp, &max_no); 04876 eject_user = ao2_find(cnf->usercontainer, &max_no, 0); 04877 if (!eject_user) { 04878 res = -1; 04879 ast_log(LOG_NOTICE, "No last user to kick!\n"); 04880 break; 04881 } 04882 04883 if (!ast_test_flag64(&eject_user->userflags, CONFFLAG_ADMIN)) { 04884 eject_user->adminflags |= ADMINFLAG_KICKME; 04885 } else { 04886 res = -1; 04887 ast_log(LOG_NOTICE, "Not kicking last user, is an Admin!\n"); 04888 } 04889 04890 ao2_ref(eject_user, -1); 04891 break; 04892 } 04893 case 77: /* M: Mute */ 04894 user->adminflags |= ADMINFLAG_MUTED; 04895 break; 04896 case 78: /* N: Mute all (non-admin) users */ 04897 ao2_callback(cnf->usercontainer, OBJ_NODATA, user_set_muted_cb, &cnf); 04898 break; 04899 case 109: /* m: Unmute */ 04900 user->adminflags &= ~(ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED | ADMINFLAG_T_REQUEST); 04901 break; 04902 case 110: /* n: Unmute all users */ 04903 ao2_callback(cnf->usercontainer, OBJ_NODATA, user_set_unmuted_cb, NULL); 04904 break; 04905 case 107: /* k: Kick user */ 04906 user->adminflags |= ADMINFLAG_KICKME; 04907 break; 04908 case 118: /* v: Lower all users listen volume */ 04909 ao2_callback(cnf->usercontainer, OBJ_NODATA, user_listen_voldown_cb, NULL); 04910 break; 04911 case 86: /* V: Raise all users listen volume */ 04912 ao2_callback(cnf->usercontainer, OBJ_NODATA, user_listen_volup_cb, NULL); 04913 break; 04914 case 115: /* s: Lower all users speaking volume */ 04915 ao2_callback(cnf->usercontainer, OBJ_NODATA, user_talk_voldown_cb, NULL); 04916 break; 04917 case 83: /* S: Raise all users speaking volume */ 04918 ao2_callback(cnf->usercontainer, OBJ_NODATA, user_talk_volup_cb, NULL); 04919 break; 04920 case 82: /* R: Reset all volume levels */ 04921 ao2_callback(cnf->usercontainer, OBJ_NODATA, user_reset_vol_cb, NULL); 04922 break; 04923 case 114: /* r: Reset user's volume level */ 04924 reset_volumes(user); 04925 break; 04926 case 85: /* U: Raise user's listen volume */ 04927 tweak_listen_volume(user, VOL_UP); 04928 break; 04929 case 117: /* u: Lower user's listen volume */ 04930 tweak_listen_volume(user, VOL_DOWN); 04931 break; 04932 case 84: /* T: Raise user's talk volume */ 04933 tweak_talk_volume(user, VOL_UP); 04934 break; 04935 case 116: /* t: Lower user's talk volume */ 04936 tweak_talk_volume(user, VOL_DOWN); 04937 break; 04938 case 'E': /* E: Extend conference */ 04939 if (rt_extend_conf(args.confno)) { 04940 res = -1; 04941 } 04942 break; 04943 } 04944 04945 if (args.user) { 04946 /* decrement reference from find_user */ 04947 ao2_ref(user, -1); 04948 } 04949 usernotfound: 04950 AST_LIST_UNLOCK(&confs); 04951 04952 dispose_conf(cnf); 04953 pbx_builtin_setvar_helper(chan, "MEETMEADMINSTATUS", res == -2 ? "NOTFOUND" : res ? "FAILED" : "OK"); 04954 04955 return 0; 04956 }
| 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 5571 of file app_meetme.c.
References ast_answer(), and ast_indicate().
Referenced by run_station(), sla_handle_dial_state_event(), and sla_station_exec().
05572 { 05573 ast_answer(chan); 05574 ast_indicate(chan, -1); 05575 }
| 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 4960 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().
04960 { 04961 char *params; 04962 struct ast_conference *conf = NULL; 04963 struct ast_conf_user *user = NULL; 04964 AST_DECLARE_APP_ARGS(args, 04965 AST_APP_ARG(channel); 04966 AST_APP_ARG(command); 04967 ); 04968 04969 if (ast_strlen_zero(data)) { 04970 ast_log(LOG_WARNING, "MeetMeChannelAdmin requires two arguments!\n"); 04971 return -1; 04972 } 04973 04974 params = ast_strdupa(data); 04975 AST_STANDARD_APP_ARGS(args, params); 04976 04977 if (!args.channel) { 04978 ast_log(LOG_WARNING, "MeetMeChannelAdmin requires a channel name!\n"); 04979 return -1; 04980 } 04981 04982 if (!args.command) { 04983 ast_log(LOG_WARNING, "MeetMeChannelAdmin requires a command!\n"); 04984 return -1; 04985 } 04986 04987 AST_LIST_LOCK(&confs); 04988 AST_LIST_TRAVERSE(&confs, conf, list) { 04989 if ((user = ao2_callback(conf->usercontainer, 0, user_chan_cb, args.channel))) { 04990 break; 04991 } 04992 } 04993 04994 if (!user) { 04995 ast_log(LOG_NOTICE, "Specified user (%s) not found\n", args.channel); 04996 AST_LIST_UNLOCK(&confs); 04997 return 0; 04998 } 04999 05000 /* perform the specified action */ 05001 switch (*args.command) { 05002 case 77: /* M: Mute */ 05003 user->adminflags |= ADMINFLAG_MUTED; 05004 break; 05005 case 109: /* m: Unmute */ 05006 user->adminflags &= ~ADMINFLAG_MUTED; 05007 break; 05008 case 107: /* k: Kick user */ 05009 user->adminflags |= ADMINFLAG_KICKME; 05010 break; 05011 default: /* unknown command */ 05012 ast_log(LOG_WARNING, "Unknown MeetMeChannelAdmin command '%s'\n", args.command); 05013 break; 05014 } 05015 ao2_ref(user, -1); 05016 AST_LIST_UNLOCK(&confs); 05017 05018 return 0; 05019 }
| 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 4405 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().
04406 { 04407 int res = -1; 04408 char confno[MAX_CONFNUM] = ""; 04409 int allowretry = 0; 04410 int retrycnt = 0; 04411 struct ast_conference *cnf = NULL; 04412 struct ast_flags64 confflags = {0}; 04413 struct ast_flags config_flags = { 0 }; 04414 int dynamic = 0; 04415 int empty = 0, empty_no_pin = 0; 04416 int always_prompt = 0; 04417 const char *notdata; 04418 char *info, the_pin[MAX_PIN] = ""; 04419 AST_DECLARE_APP_ARGS(args, 04420 AST_APP_ARG(confno); 04421 AST_APP_ARG(options); 04422 AST_APP_ARG(pin); 04423 ); 04424 char *optargs[OPT_ARG_ARRAY_SIZE] = { NULL, }; 04425 04426 if (ast_strlen_zero(data)) { 04427 allowretry = 1; 04428 notdata = ""; 04429 } else { 04430 notdata = data; 04431 } 04432 04433 if (chan->_state != AST_STATE_UP) 04434 ast_answer(chan); 04435 04436 info = ast_strdupa(notdata); 04437 04438 AST_STANDARD_APP_ARGS(args, info); 04439 04440 if (args.confno) { 04441 ast_copy_string(confno, args.confno, sizeof(confno)); 04442 if (ast_strlen_zero(confno)) { 04443 allowretry = 1; 04444 } 04445 } 04446 04447 if (args.pin) 04448 ast_copy_string(the_pin, args.pin, sizeof(the_pin)); 04449 04450 if (args.options) { 04451 ast_app_parse_options64(meetme_opts, &confflags, optargs, args.options); 04452 dynamic = ast_test_flag64(&confflags, CONFFLAG_DYNAMIC | CONFFLAG_DYNAMICPIN); 04453 if (ast_test_flag64(&confflags, CONFFLAG_DYNAMICPIN) && ast_strlen_zero(args.pin)) 04454 strcpy(the_pin, "q"); 04455 04456 empty = ast_test_flag64(&confflags, CONFFLAG_EMPTY | CONFFLAG_EMPTYNOPIN); 04457 empty_no_pin = ast_test_flag64(&confflags, CONFFLAG_EMPTYNOPIN); 04458 always_prompt = ast_test_flag64(&confflags, CONFFLAG_ALWAYSPROMPT | CONFFLAG_DYNAMICPIN); 04459 } 04460 04461 do { 04462 if (retrycnt > 3) 04463 allowretry = 0; 04464 if (empty) { 04465 int i; 04466 struct ast_config *cfg; 04467 struct ast_variable *var; 04468 int confno_int; 04469 04470 /* We only need to load the config file for static and empty_no_pin (otherwise we don't care) */ 04471 if ((empty_no_pin) || (!dynamic)) { 04472 cfg = ast_config_load(CONFIG_FILE_NAME, config_flags); 04473 if (cfg && cfg != CONFIG_STATUS_FILEINVALID) { 04474 var = ast_variable_browse(cfg, "rooms"); 04475 while (var) { 04476 char parse[MAX_SETTINGS], *stringp = parse, *confno_tmp; 04477 if (!strcasecmp(var->name, "conf")) { 04478 int found = 0; 04479 ast_copy_string(parse, var->value, sizeof(parse)); 04480 confno_tmp = strsep(&stringp, "|,"); 04481 if (!dynamic) { 04482 /* For static: run through the list and see if this conference is empty */ 04483 AST_LIST_LOCK(&confs); 04484 AST_LIST_TRAVERSE(&confs, cnf, list) { 04485 if (!strcmp(confno_tmp, cnf->confno)) { 04486 /* The conference exists, therefore it's not empty */ 04487 found = 1; 04488 break; 04489 } 04490 } 04491 AST_LIST_UNLOCK(&confs); 04492 cnf = NULL; 04493 if (!found) { 04494 /* At this point, we have a confno_tmp (static conference) that is empty */ 04495 if ((empty_no_pin && ast_strlen_zero(stringp)) || (!empty_no_pin)) { 04496 /* Case 1: empty_no_pin and pin is nonexistent (NULL) 04497 * Case 2: empty_no_pin and pin is blank (but not NULL) 04498 * Case 3: not empty_no_pin 04499 */ 04500 ast_copy_string(confno, confno_tmp, sizeof(confno)); 04501 break; 04502 } 04503 } 04504 } 04505 } 04506 var = var->next; 04507 } 04508 ast_config_destroy(cfg); 04509 } 04510 04511 if (ast_strlen_zero(confno) && (cfg = ast_load_realtime_multientry("meetme", "confno LIKE", "%", SENTINEL))) { 04512 const char *catg; 04513 for (catg = ast_category_browse(cfg, NULL); catg; catg = ast_category_browse(cfg, catg)) { 04514 const char *confno_tmp = ast_variable_retrieve(cfg, catg, "confno"); 04515 const char *pin_tmp = ast_variable_retrieve(cfg, catg, "pin"); 04516 if (ast_strlen_zero(confno_tmp)) { 04517 continue; 04518 } 04519 if (!dynamic) { 04520 int found = 0; 04521 /* For static: run through the list and see if this conference is empty */ 04522 AST_LIST_LOCK(&confs); 04523 AST_LIST_TRAVERSE(&confs, cnf, list) { 04524 if (!strcmp(confno_tmp, cnf->confno)) { 04525 /* The conference exists, therefore it's not empty */ 04526 found = 1; 04527 break; 04528 } 04529 } 04530 AST_LIST_UNLOCK(&confs); 04531 if (!found) { 04532 /* At this point, we have a confno_tmp (realtime conference) that is empty */ 04533 if ((empty_no_pin && ast_strlen_zero(pin_tmp)) || (!empty_no_pin)) { 04534 /* Case 1: empty_no_pin and pin is nonexistent (NULL) 04535 * Case 2: empty_no_pin and pin is blank (but not NULL) 04536 * Case 3: not empty_no_pin 04537 */ 04538 ast_copy_string(confno, confno_tmp, sizeof(confno)); 04539 break; 04540 } 04541 } 04542 } 04543 } 04544 ast_config_destroy(cfg); 04545 } 04546 } 04547 04548 /* Select first conference number not in use */ 04549 if (ast_strlen_zero(confno) && dynamic) { 04550 AST_LIST_LOCK(&confs); 04551 for (i = 0; i < ARRAY_LEN(conf_map); i++) { 04552 if (!conf_map[i]) { 04553 snprintf(confno, sizeof(confno), "%d", i); 04554 conf_map[i] = 1; 04555 break; 04556 } 04557 } 04558 AST_LIST_UNLOCK(&confs); 04559 } 04560 04561 /* Not found? */ 04562 if (ast_strlen_zero(confno)) { 04563 ast_test_suite_event_notify("PLAYBACK", "Message: conf-noempty"); 04564 res = ast_streamfile(chan, "conf-noempty", chan->language); 04565 if (!res) 04566 ast_waitstream(chan, ""); 04567 } else { 04568 if (sscanf(confno, "%30d", &confno_int) == 1) { 04569 if (!ast_test_flag64(&confflags, CONFFLAG_QUIET)) { 04570 res = ast_streamfile(chan, "conf-enteringno", chan->language); 04571 if (!res) { 04572 ast_waitstream(chan, ""); 04573 res = ast_say_digits(chan, confno_int, "", chan->language); 04574 } 04575 } 04576 } else { 04577 ast_log(LOG_ERROR, "Could not scan confno '%s'\n", confno); 04578 } 04579 } 04580 } 04581 04582 while (allowretry && (ast_strlen_zero(confno)) && (++retrycnt < 4)) { 04583 /* Prompt user for conference number */ 04584 res = ast_app_getdata(chan, "conf-getconfno", confno, sizeof(confno) - 1, 0); 04585 if (res < 0) { 04586 /* Don't try to validate when we catch an error */ 04587 confno[0] = '\0'; 04588 allowretry = 0; 04589 break; 04590 } 04591 } 04592 if (!ast_strlen_zero(confno)) { 04593 /* Check the validity of the conference */ 04594 cnf = find_conf(chan, confno, 1, dynamic, the_pin, 04595 sizeof(the_pin), 1, &confflags); 04596 if (!cnf) { 04597 int too_early = 0; 04598 04599 cnf = find_conf_realtime(chan, confno, 1, dynamic, 04600 the_pin, sizeof(the_pin), 1, &confflags, &too_early, optargs); 04601 if (rt_schedule && too_early) 04602 allowretry = 0; 04603 } 04604 04605 if (!cnf) { 04606 if (allowretry) { 04607 confno[0] = '\0'; 04608 res = ast_streamfile(chan, "conf-invalid", chan->language); 04609 if (!res) 04610 ast_waitstream(chan, ""); 04611 res = -1; 04612 } 04613 } else { 04614 /* Conference requires a pin for specified access level */ 04615 int req_pin = !ast_strlen_zero(cnf->pin) || 04616 (!ast_strlen_zero(cnf->pinadmin) && 04617 ast_test_flag64(&confflags, CONFFLAG_ADMIN)); 04618 /* The following logic was derived from a 04619 * 4 variable truth table and defines which 04620 * circumstances are not exempt from pin 04621 * checking. 04622 * If this needs to be modified, write the 04623 * truth table back out from the boolean 04624 * expression AB+A'D+C', change the erroneous 04625 * result, and rederive the expression. 04626 * Variables: 04627 * A: pin provided? 04628 * B: always prompt? 04629 * C: dynamic? 04630 * D: has users? */ 04631 int not_exempt = !cnf->isdynamic; 04632 not_exempt = not_exempt || (!ast_strlen_zero(args.pin) && ast_test_flag64(&confflags, CONFFLAG_ALWAYSPROMPT)); 04633 not_exempt = not_exempt || (ast_strlen_zero(args.pin) && cnf->users); 04634 if (req_pin && not_exempt) { 04635 char pin[MAX_PIN] = ""; 04636 int j; 04637 04638 /* Allow the pin to be retried up to 3 times */ 04639 for (j = 0; j < 3; j++) { 04640 if (*the_pin && (always_prompt == 0)) { 04641 ast_copy_string(pin, the_pin, sizeof(pin)); 04642 res = 0; 04643 } else { 04644 /* Prompt user for pin if pin is required */ 04645 ast_test_suite_event_notify("PLAYBACK", "Message: conf-getpin\r\n" 04646 "Channel: %s", 04647 chan->name); 04648 res = ast_app_getdata(chan, "conf-getpin", pin + strlen(pin), sizeof(pin) - 1 - strlen(pin), 0); 04649 } 04650 if (res >= 0) { 04651 if ((!strcasecmp(pin, cnf->pin) && 04652 (ast_strlen_zero(cnf->pinadmin) || 04653 !ast_test_flag64(&confflags, CONFFLAG_ADMIN))) || 04654 (!ast_strlen_zero(cnf->pinadmin) && 04655 !strcasecmp(pin, cnf->pinadmin))) { 04656 /* Pin correct */ 04657 allowretry = 0; 04658 if (!ast_strlen_zero(cnf->pinadmin) && !strcasecmp(pin, cnf->pinadmin)) { 04659 if (!ast_strlen_zero(cnf->adminopts)) { 04660 char *opts = ast_strdupa(cnf->adminopts); 04661 ast_app_parse_options64(meetme_opts, &confflags, optargs, opts); 04662 } 04663 } else { 04664 if (!ast_strlen_zero(cnf->useropts)) { 04665 char *opts = ast_strdupa(cnf->useropts); 04666 ast_app_parse_options64(meetme_opts, &confflags, optargs, opts); 04667 } 04668 } 04669 /* Run the conference */ 04670 ast_verb(4, "Starting recording of MeetMe Conference %s into file %s.%s.\n", cnf->confno, cnf->recordingfilename, cnf->recordingformat); 04671 res = conf_run(chan, cnf, &confflags, optargs); 04672 break; 04673 } else { 04674 /* Pin invalid */ 04675 if (!ast_streamfile(chan, "conf-invalidpin", chan->language)) { 04676 res = ast_waitstream(chan, AST_DIGIT_ANY); 04677 ast_stopstream(chan); 04678 } else { 04679 ast_log(LOG_WARNING, "Couldn't play invalid pin msg!\n"); 04680 break; 04681 } 04682 if (res < 0) 04683 break; 04684 pin[0] = res; 04685 pin[1] = '\0'; 04686 res = -1; 04687 if (allowretry) 04688 confno[0] = '\0'; 04689 } 04690 } else { 04691 /* failed when getting the pin */ 04692 res = -1; 04693 allowretry = 0; 04694 /* see if we need to get rid of the conference */ 04695 break; 04696 } 04697 04698 /* Don't retry pin with a static pin */ 04699 if (*the_pin && (always_prompt == 0)) { 04700 break; 04701 } 04702 } 04703 } else { 04704 /* No pin required */ 04705 allowretry = 0; 04706 04707 /* For RealTime conferences without a pin 04708 * should still support loading options 04709 */ 04710 if (!ast_strlen_zero(cnf->useropts)) { 04711 char *opts = ast_strdupa(cnf->useropts); 04712 ast_app_parse_options64(meetme_opts, &confflags, optargs, opts); 04713 } 04714 04715 /* Run the conference */ 04716 res = conf_run(chan, cnf, &confflags, optargs); 04717 } 04718 dispose_conf(cnf); 04719 cnf = NULL; 04720 } 04721 } 04722 } while (allowretry); 04723 04724 if (cnf) 04725 dispose_conf(cnf); 04726 04727 return res; 04728 }
| 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 2754 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().
02755 { 02756 struct ast_conf_user *user = NULL; 02757 int fd; 02758 struct dahdi_confinfo dahdic, dahdic_empty; 02759 struct ast_frame *f; 02760 struct ast_channel *c; 02761 struct ast_frame fr; 02762 int outfd; 02763 int ms; 02764 int nfds; 02765 int res; 02766 int retrydahdi; 02767 int origfd; 02768 int musiconhold = 0, mohtempstopped = 0; 02769 int firstpass = 0; 02770 int lastmarked = 0; 02771 int currentmarked = 0; 02772 int ret = -1; 02773 int x; 02774 enum menu_modes menu_mode = MENU_DISABLED; 02775 int talkreq_manager = 0; 02776 int using_pseudo = 0; 02777 int duration = 20; 02778 int sent_event = 0; 02779 int checked = 0; 02780 int announcement_played = 0; 02781 struct timeval now; 02782 struct ast_dsp *dsp = NULL; 02783 struct ast_app *agi_app; 02784 char *agifile, *mod_speex; 02785 const char *agifiledefault = "conf-background.agi", *tmpvar; 02786 char meetmesecs[30] = ""; 02787 char exitcontext[AST_MAX_CONTEXT] = ""; 02788 char recordingtmp[AST_MAX_EXTENSION] = ""; 02789 char members[10] = ""; 02790 int dtmf = 0, opt_waitmarked_timeout = 0; 02791 time_t timeout = 0; 02792 struct dahdi_bufferinfo bi; 02793 char __buf[CONF_SIZE + AST_FRIENDLY_OFFSET]; 02794 char *buf = __buf + AST_FRIENDLY_OFFSET; 02795 char *exitkeys = NULL; 02796 unsigned int calldurationlimit = 0; 02797 long timelimit = 0; 02798 long play_warning = 0; 02799 long warning_freq = 0; 02800 const char *warning_sound = NULL; 02801 const char *end_sound = NULL; 02802 char *parse; 02803 long time_left_ms = 0; 02804 struct timeval nexteventts = { 0, }; 02805 int to; 02806 int setusercount = 0; 02807 int confsilence = 0, totalsilence = 0; 02808 02809 if (!(user = ao2_alloc(sizeof(*user), NULL))) { 02810 return ret; 02811 } 02812 02813 /* Possible timeout waiting for marked user */ 02814 if (ast_test_flag64(confflags, CONFFLAG_WAITMARKED) && 02815 !ast_strlen_zero(optargs[OPT_ARG_WAITMARKED]) && 02816 (sscanf(optargs[OPT_ARG_WAITMARKED], "%30d", &opt_waitmarked_timeout) == 1) && 02817 (opt_waitmarked_timeout > 0)) { 02818 timeout = time(NULL) + opt_waitmarked_timeout; 02819 } 02820 02821 if (ast_test_flag64(confflags, CONFFLAG_DURATION_STOP) && !ast_strlen_zero(optargs[OPT_ARG_DURATION_STOP])) { 02822 calldurationlimit = atoi(optargs[OPT_ARG_DURATION_STOP]); 02823 ast_verb(3, "Setting call duration limit to %d seconds.\n", calldurationlimit); 02824 } 02825 02826 if (ast_test_flag64(confflags, CONFFLAG_DURATION_LIMIT) && !ast_strlen_zero(optargs[OPT_ARG_DURATION_LIMIT])) { 02827 char *limit_str, *warning_str, *warnfreq_str; 02828 const char *var; 02829 02830 parse = optargs[OPT_ARG_DURATION_LIMIT]; 02831 limit_str = strsep(&parse, ":"); 02832 warning_str = strsep(&parse, ":"); 02833 warnfreq_str = parse; 02834 02835 timelimit = atol(limit_str); 02836 if (warning_str) 02837 play_warning = atol(warning_str); 02838 if (warnfreq_str) 02839 warning_freq = atol(warnfreq_str); 02840 02841 if (!timelimit) { 02842 timelimit = play_warning = warning_freq = 0; 02843 warning_sound = NULL; 02844 } else if (play_warning > timelimit) { 02845 if (!warning_freq) { 02846 play_warning = 0; 02847 } else { 02848 while (play_warning > timelimit) 02849 play_warning -= warning_freq; 02850 if (play_warning < 1) 02851 play_warning = warning_freq = 0; 02852 } 02853 } 02854 02855 ast_verb(3, "Setting conference duration limit to: %ldms.\n", timelimit); 02856 if (play_warning) { 02857 ast_verb(3, "Setting warning time to %ldms from the conference duration limit.\n", play_warning); 02858 } 02859 if (warning_freq) { 02860 ast_verb(3, "Setting warning frequency to %ldms.\n", warning_freq); 02861 } 02862 02863 ast_channel_lock(chan); 02864 if ((var = pbx_builtin_getvar_helper(chan, "CONF_LIMIT_WARNING_FILE"))) { 02865 var = ast_strdupa(var); 02866 } 02867 ast_channel_unlock(chan); 02868 02869 warning_sound = var ? var : "timeleft"; 02870 02871 ast_channel_lock(chan); 02872 if ((var = pbx_builtin_getvar_helper(chan, "CONF_LIMIT_TIMEOUT_FILE"))) { 02873 var = ast_strdupa(var); 02874 } 02875 ast_channel_unlock(chan); 02876 02877 end_sound = var ? var : NULL; 02878 02879 /* undo effect of S(x) in case they are both used */ 02880 calldurationlimit = 0; 02881 /* more efficient do it like S(x) does since no advanced opts */ 02882 if (!play_warning && !end_sound && timelimit) { 02883 calldurationlimit = timelimit / 1000; 02884 timelimit = play_warning = warning_freq = 0; 02885 } else { 02886 ast_debug(2, "Limit Data for this call:\n"); 02887 ast_debug(2, "- timelimit = %ld\n", timelimit); 02888 ast_debug(2, "- play_warning = %ld\n", play_warning); 02889 ast_debug(2, "- warning_freq = %ld\n", warning_freq); 02890 ast_debug(2, "- warning_sound = %s\n", warning_sound ? warning_sound : "UNDEF"); 02891 ast_debug(2, "- end_sound = %s\n", end_sound ? end_sound : "UNDEF"); 02892 } 02893 } 02894 02895 /* Get exit keys */ 02896 if (ast_test_flag64(confflags, CONFFLAG_KEYEXIT)) { 02897 if (!ast_strlen_zero(optargs[OPT_ARG_EXITKEYS])) 02898 exitkeys = ast_strdupa(optargs[OPT_ARG_EXITKEYS]); 02899 else 02900 exitkeys = ast_strdupa("#"); /* Default */ 02901 } 02902 02903 if (ast_test_flag64(confflags, CONFFLAG_RECORDCONF)) { 02904 if (!conf->recordingfilename) { 02905 const char *var; 02906 ast_channel_lock(chan); 02907 if ((var = pbx_builtin_getvar_helper(chan, "MEETME_RECORDINGFILE"))) { 02908 conf->recordingfilename = ast_strdup(var); 02909 } 02910 if ((var = pbx_builtin_getvar_helper(chan, "MEETME_RECORDINGFORMAT"))) { 02911 conf->recordingformat = ast_strdup(var); 02912 } 02913 ast_channel_unlock(chan); 02914 if (!conf->recordingfilename) { 02915 snprintf(recordingtmp, sizeof(recordingtmp), "meetme-conf-rec-%s-%s", conf->confno, chan->uniqueid); 02916 conf->recordingfilename = ast_strdup(recordingtmp); 02917 } 02918 if (!conf->recordingformat) { 02919 conf->recordingformat = ast_strdup("wav"); 02920 } 02921 ast_verb(4, "Starting recording of MeetMe Conference %s into file %s.%s.\n", 02922 conf->confno, conf->recordingfilename, conf->recordingformat); 02923 } 02924 } 02925 02926 ast_mutex_lock(&conf->recordthreadlock); 02927 if ((conf->recordthread == AST_PTHREADT_NULL) && ast_test_flag64(confflags, CONFFLAG_RECORDCONF) && 02928 ((conf->lchan = ast_request("DAHDI", AST_FORMAT_SLINEAR, chan, "pseudo", NULL)))) { 02929 ast_set_read_format(conf->lchan, AST_FORMAT_SLINEAR); 02930 ast_set_write_format(conf->lchan, AST_FORMAT_SLINEAR); 02931 dahdic.chan = 0; 02932 dahdic.confno = conf->dahdiconf; 02933 dahdic.confmode = DAHDI_CONF_CONFANN | DAHDI_CONF_CONFANNMON; 02934 if (ioctl(conf->lchan->fds[0], DAHDI_SETCONF, &dahdic)) { 02935 ast_log(LOG_WARNING, "Error starting listen channel\n"); 02936 ast_hangup(conf->lchan); 02937 conf->lchan = NULL; 02938 } else { 02939 ast_pthread_create_detached_background(&conf->recordthread, NULL, recordthread, conf); 02940 } 02941 } 02942 ast_mutex_unlock(&conf->recordthreadlock); 02943 02944 ast_mutex_lock(&conf->announcethreadlock); 02945 if ((conf->announcethread == AST_PTHREADT_NULL) && !ast_test_flag64(confflags, CONFFLAG_QUIET) && 02946 (ast_test_flag64(confflags, CONFFLAG_INTROUSER) || ast_test_flag64(confflags, CONFFLAG_INTROUSERNOREVIEW))) { 02947 ast_mutex_init(&conf->announcelistlock); 02948 AST_LIST_HEAD_INIT_NOLOCK(&conf->announcelist); 02949 ast_pthread_create_background(&conf->announcethread, NULL, announce_thread, conf); 02950 } 02951 ast_mutex_unlock(&conf->announcethreadlock); 02952 02953 time(&user->jointime); 02954 02955 user->timelimit = timelimit; 02956 user->play_warning = play_warning; 02957 user->warning_freq = warning_freq; 02958 user->warning_sound = warning_sound; 02959 user->end_sound = end_sound; 02960 02961 if (calldurationlimit > 0) { 02962 time(&user->kicktime); 02963 user->kicktime = user->kicktime + calldurationlimit; 02964 } 02965 02966 if (ast_tvzero(user->start_time)) 02967 user->start_time = ast_tvnow(); 02968 time_left_ms = user->timelimit; 02969 02970 if (user->timelimit) { 02971 nexteventts = ast_tvadd(user->start_time, ast_samp2tv(user->timelimit, 1000)); 02972 nexteventts = ast_tvsub(nexteventts, ast_samp2tv(user->play_warning, 1000)); 02973 } 02974 02975 if (conf->locked && (!ast_test_flag64(confflags, CONFFLAG_ADMIN))) { 02976 /* Sorry, but this conference is locked! */ 02977 if (!ast_streamfile(chan, "conf-locked", chan->language)) 02978 ast_waitstream(chan, ""); 02979 goto outrun; 02980 } 02981 02982 ast_mutex_lock(&conf->playlock); 02983 02984 if (rt_schedule && conf->maxusers) { 02985 if (conf->users >= conf->maxusers) { 02986 /* Sorry, but this confernce has reached the participant limit! */ 02987 if (!ast_streamfile(chan, "conf-full", chan->language)) 02988 ast_waitstream(chan, ""); 02989 ast_mutex_unlock(&conf->playlock); 02990 goto outrun; 02991 } 02992 } 02993 02994 ao2_lock(conf->usercontainer); 02995 ao2_callback(conf->usercontainer, OBJ_NODATA, user_max_cmp, &user->user_no); 02996 user->user_no++; 02997 ao2_link(conf->usercontainer, user); 02998 ao2_unlock(conf->usercontainer); 02999 03000 user->chan = chan; 03001 user->userflags = *confflags; 03002 user->adminflags = ast_test_flag64(confflags, CONFFLAG_STARTMUTED) ? ADMINFLAG_SELFMUTED : 0; 03003 user->adminflags |= (conf->gmuted) ? ADMINFLAG_MUTED : 0; 03004 user->talking = -1; 03005 03006 ast_mutex_unlock(&conf->playlock); 03007 03008 if (!ast_test_flag64(confflags, CONFFLAG_QUIET) && (ast_test_flag64(confflags, CONFFLAG_INTROUSER) || 03009 ast_test_flag64(confflags, CONFFLAG_INTROUSERNOREVIEW))) { 03010 char destdir[PATH_MAX]; 03011 03012 snprintf(destdir, sizeof(destdir), "%s/meetme", ast_config_AST_SPOOL_DIR); 03013 03014 if (ast_mkdir(destdir, 0777) != 0) { 03015 ast_log(LOG_WARNING, "mkdir '%s' failed: %s\n", destdir, strerror(errno)); 03016 goto outrun; 03017 } 03018 03019 snprintf(user->namerecloc, sizeof(user->namerecloc), 03020 "%s/meetme-username-%s-%d", destdir, 03021 conf->confno, user->user_no); 03022 if (ast_test_flag64(confflags, CONFFLAG_INTROUSERNOREVIEW)) 03023 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); 03024 else 03025 res = ast_record_review(chan, "vm-rec-name", user->namerecloc, 10, "sln", &duration, NULL); 03026 if (res == -1) 03027 goto outrun; 03028 } 03029 03030 ast_mutex_lock(&conf->playlock); 03031 03032 if (ast_test_flag64(confflags, CONFFLAG_MARKEDUSER)) 03033 conf->markedusers++; 03034 conf->users++; 03035 if (rt_log_members) { 03036 /* Update table */ 03037 snprintf(members, sizeof(members), "%d", conf->users); 03038 ast_realtime_require_field("meetme", 03039 "confno", strlen(conf->confno) > 7 ? RQ_UINTEGER4 : strlen(conf->confno) > 4 ? RQ_UINTEGER3 : RQ_UINTEGER2, strlen(conf->confno), 03040 "members", RQ_UINTEGER1, strlen(members), 03041 NULL); 03042 ast_update_realtime("meetme", "confno", conf->confno, "members", members, NULL); 03043 } 03044 setusercount = 1; 03045 03046 /* This device changed state now - if this is the first user */ 03047 if (conf->users == 1) 03048 ast_devstate_changed(AST_DEVICE_INUSE, (conf->isdynamic ? AST_DEVSTATE_NOT_CACHABLE : AST_DEVSTATE_CACHABLE), "meetme:%s", conf->confno); 03049 03050 ast_mutex_unlock(&conf->playlock); 03051 03052 /* return the unique ID of the conference */ 03053 pbx_builtin_setvar_helper(chan, "MEETMEUNIQUEID", conf->uniqueid); 03054 03055 if (ast_test_flag64(confflags, CONFFLAG_EXIT_CONTEXT)) { 03056 ast_channel_lock(chan); 03057 if ((tmpvar = pbx_builtin_getvar_helper(chan, "MEETME_EXIT_CONTEXT"))) { 03058 ast_copy_string(exitcontext, tmpvar, sizeof(exitcontext)); 03059 } else if (!ast_strlen_zero(chan->macrocontext)) { 03060 ast_copy_string(exitcontext, chan->macrocontext, sizeof(exitcontext)); 03061 } else { 03062 ast_copy_string(exitcontext, chan->context, sizeof(exitcontext)); 03063 } 03064 ast_channel_unlock(chan); 03065 } 03066 03067 /* Play an arbitrary intro message */ 03068 if (ast_test_flag64(confflags, CONFFLAG_INTROMSG) && 03069 !ast_strlen_zero(optargs[OPT_ARG_INTROMSG])) { 03070 if (!ast_streamfile(chan, optargs[OPT_ARG_INTROMSG], chan->language)) { 03071 ast_waitstream(chan, ""); 03072 } 03073 } 03074 03075 if (!ast_test_flag64(confflags, (CONFFLAG_QUIET | CONFFLAG_NOONLYPERSON))) { 03076 if (conf->users == 1 && !ast_test_flag64(confflags, CONFFLAG_WAITMARKED)) 03077 if (!ast_streamfile(chan, "conf-onlyperson", chan->language)) 03078 ast_waitstream(chan, ""); 03079 if (ast_test_flag64(confflags, CONFFLAG_WAITMARKED) && conf->markedusers == 0) 03080 if (!ast_streamfile(chan, "conf-waitforleader", chan->language)) 03081 ast_waitstream(chan, ""); 03082 } 03083 03084 if (!ast_test_flag64(confflags, CONFFLAG_QUIET) && ast_test_flag64(confflags, CONFFLAG_ANNOUNCEUSERCOUNT) && 03085 conf->users > 1) { 03086 int keepplaying = 1; 03087 03088 if (conf->users == 2) { 03089 if (!ast_streamfile(chan, "conf-onlyone", chan->language)) { 03090 res = ast_waitstream(chan, AST_DIGIT_ANY); 03091 ast_stopstream(chan); 03092 if (res > 0) 03093 keepplaying = 0; 03094 else if (res == -1) 03095 goto outrun; 03096 } 03097 } else { 03098 if (!ast_streamfile(chan, "conf-thereare", chan->language)) { 03099 res = ast_waitstream(chan, AST_DIGIT_ANY); 03100 ast_stopstream(chan); 03101 if (res > 0) 03102 keepplaying = 0; 03103 else if (res == -1) 03104 goto outrun; 03105 } 03106 if (keepplaying) { 03107 res = ast_say_number(chan, conf->users - 1, AST_DIGIT_ANY, chan->language, (char *) NULL); 03108 if (res > 0) 03109 keepplaying = 0; 03110 else if (res == -1) 03111 goto outrun; 03112 } 03113 if (keepplaying && !ast_streamfile(chan, "conf-otherinparty", chan->language)) { 03114 res = ast_waitstream(chan, AST_DIGIT_ANY); 03115 ast_stopstream(chan); 03116 if (res > 0) 03117 keepplaying = 0; 03118 else if (res == -1) 03119 goto outrun; 03120 } 03121 } 03122 } 03123 03124 if (!ast_test_flag64(confflags, CONFFLAG_NO_AUDIO_UNTIL_UP)) { 03125 /* We're leaving this alone until the state gets changed to up */ 03126 ast_indicate(chan, -1); 03127 } 03128 03129 if (ast_set_write_format(chan, AST_FORMAT_SLINEAR) < 0) { 03130 ast_log(LOG_WARNING, "Unable to set '%s' to write linear mode\n", chan->name); 03131 goto outrun; 03132 } 03133 03134 if (ast_set_read_format(chan, AST_FORMAT_SLINEAR) < 0) { 03135 ast_log(LOG_WARNING, "Unable to set '%s' to read linear mode\n", chan->name); 03136 goto outrun; 03137 } 03138 03139 /* Reduce background noise from each participant */ 03140 if (!ast_test_flag64(confflags, CONFFLAG_DONT_DENOISE) && 03141 (mod_speex = ast_module_helper("", "func_speex", 0, 0, 0, 0))) { 03142 ast_free(mod_speex); 03143 ast_func_write(chan, "DENOISE(rx)", "on"); 03144 } 03145 03146 retrydahdi = (strcasecmp(chan->tech->type, "DAHDI") || (chan->audiohooks || chan->monitor) ? 1 : 0); 03147 user->dahdichannel = !retrydahdi; 03148 03149 dahdiretry: 03150 origfd = chan->fds[0]; 03151 if (retrydahdi) { 03152 /* open pseudo in non-blocking mode */ 03153 fd = open("/dev/dahdi/pseudo", O_RDWR | O_NONBLOCK); 03154 if (fd < 0) { 03155 ast_log(LOG_WARNING, "Unable to open DAHDI pseudo channel: %s\n", strerror(errno)); 03156 goto outrun; 03157 } 03158 using_pseudo = 1; 03159 /* Setup buffering information */ 03160 memset(&bi, 0, sizeof(bi)); 03161 bi.bufsize = CONF_SIZE / 2; 03162 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE; 03163 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE; 03164 bi.numbufs = audio_buffers; 03165 if (ioctl(fd, DAHDI_SET_BUFINFO, &bi)) { 03166 ast_log(LOG_WARNING, "Unable to set buffering information: %s\n", strerror(errno)); 03167 close(fd); 03168 goto outrun; 03169 } 03170 x = 1; 03171 if (ioctl(fd, DAHDI_SETLINEAR, &x)) { 03172 ast_log(LOG_WARNING, "Unable to set linear mode: %s\n", strerror(errno)); 03173 close(fd); 03174 goto outrun; 03175 } 03176 nfds = 1; 03177 } else { 03178 /* XXX Make sure we're not running on a pseudo channel XXX */ 03179 fd = chan->fds[0]; 03180 nfds = 0; 03181 } 03182 memset(&dahdic, 0, sizeof(dahdic)); 03183 memset(&dahdic_empty, 0, sizeof(dahdic_empty)); 03184 /* Check to see if we're in a conference... */ 03185 dahdic.chan = 0; 03186 if (ioctl(fd, DAHDI_GETCONF, &dahdic)) { 03187 ast_log(LOG_WARNING, "Error getting conference\n"); 03188 close(fd); 03189 goto outrun; 03190 } 03191 if (dahdic.confmode) { 03192 /* Whoa, already in a conference... Retry... */ 03193 if (!retrydahdi) { 03194 ast_debug(1, "DAHDI channel is in a conference already, retrying with pseudo\n"); 03195 retrydahdi = 1; 03196 goto dahdiretry; 03197 } 03198 } 03199 memset(&dahdic, 0, sizeof(dahdic)); 03200 /* Add us to the conference */ 03201 dahdic.chan = 0; 03202 dahdic.confno = conf->dahdiconf; 03203 03204 if (!ast_test_flag64(confflags, CONFFLAG_QUIET) && (ast_test_flag64(confflags, CONFFLAG_INTROUSER) || 03205 ast_test_flag64(confflags, CONFFLAG_INTROUSERNOREVIEW)) && conf->users > 1) { 03206 struct announce_listitem *item; 03207 if (!(item = ao2_alloc(sizeof(*item), NULL))) 03208 goto outrun; 03209 ast_copy_string(item->namerecloc, user->namerecloc, sizeof(item->namerecloc)); 03210 ast_copy_string(item->language, chan->language, sizeof(item->language)); 03211 item->confchan = conf->chan; 03212 item->confusers = conf->users; 03213 item->announcetype = CONF_HASJOIN; 03214 ast_mutex_lock(&conf->announcelistlock); 03215 ao2_ref(item, +1); /* add one more so we can determine when announce_thread is done playing it */ 03216 AST_LIST_INSERT_TAIL(&conf->announcelist, item, entry); 03217 ast_cond_signal(&conf->announcelist_addition); 03218 ast_mutex_unlock(&conf->announcelistlock); 03219 03220 while (!ast_check_hangup(conf->chan) && ao2_ref(item, 0) == 2 && !ast_safe_sleep(chan, 1000)) { 03221 ; 03222 } 03223 ao2_ref(item, -1); 03224 } 03225 03226 if (ast_test_flag64(confflags, CONFFLAG_WAITMARKED) && !conf->markedusers) 03227 dahdic.confmode = DAHDI_CONF_CONF; 03228 else if (ast_test_flag64(confflags, CONFFLAG_MONITOR)) 03229 dahdic.confmode = DAHDI_CONF_CONFMON | DAHDI_CONF_LISTENER; 03230 else if (ast_test_flag64(confflags, CONFFLAG_TALKER)) 03231 dahdic.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER; 03232 else 03233 dahdic.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER; 03234 03235 if (ioctl(fd, DAHDI_SETCONF, &dahdic)) { 03236 ast_log(LOG_WARNING, "Error setting conference\n"); 03237 close(fd); 03238 goto outrun; 03239 } 03240 ast_debug(1, "Placed channel %s in DAHDI conf %d\n", chan->name, conf->dahdiconf); 03241 03242 if (!sent_event) { 03243 ast_manager_event(chan, EVENT_FLAG_CALL, "MeetmeJoin", 03244 "Channel: %s\r\n" 03245 "Uniqueid: %s\r\n" 03246 "Meetme: %s\r\n" 03247 "Usernum: %d\r\n" 03248 "CallerIDnum: %s\r\n" 03249 "CallerIDname: %s\r\n" 03250 "ConnectedLineNum: %s\r\n" 03251 "ConnectedLineName: %s\r\n", 03252 chan->name, chan->uniqueid, conf->confno, 03253 user->user_no, 03254 S_COR(user->chan->caller.id.number.valid, user->chan->caller.id.number.str, "<unknown>"), 03255 S_COR(user->chan->caller.id.name.valid, user->chan->caller.id.name.str, "<unknown>"), 03256 S_COR(user->chan->connected.id.number.valid, user->chan->connected.id.number.str, "<unknown>"), 03257 S_COR(user->chan->connected.id.name.valid, user->chan->connected.id.name.str, "<unknown>") 03258 ); 03259 sent_event = 1; 03260 } 03261 03262 if (!firstpass && !ast_test_flag64(confflags, CONFFLAG_MONITOR) && 03263 !ast_test_flag64(confflags, CONFFLAG_ADMIN)) { 03264 firstpass = 1; 03265 if (!ast_test_flag64(confflags, CONFFLAG_QUIET)) 03266 if (!ast_test_flag64(confflags, CONFFLAG_WAITMARKED) || (ast_test_flag64(confflags, CONFFLAG_MARKEDUSER) && 03267 (conf->markedusers >= 1))) { 03268 conf_play(chan, conf, ENTER); 03269 } 03270 } 03271 03272 conf_flush(fd, chan); 03273 03274 if (dsp) 03275 ast_dsp_free(dsp); 03276 03277 if (!(dsp = ast_dsp_new())) { 03278 ast_log(LOG_WARNING, "Unable to allocate DSP!\n"); 03279 res = -1; 03280 } 03281 03282 if (ast_test_flag64(confflags, CONFFLAG_AGI)) { 03283 /* Get name of AGI file to run from $(MEETME_AGI_BACKGROUND) 03284 or use default filename of conf-background.agi */ 03285 03286 ast_channel_lock(chan); 03287 if ((tmpvar = pbx_builtin_getvar_helper(chan, "MEETME_AGI_BACKGROUND"))) { 03288 agifile = ast_strdupa(tmpvar); 03289 } else { 03290 agifile = ast_strdupa(agifiledefault); 03291 } 03292 ast_channel_unlock(chan); 03293 03294 if (user->dahdichannel) { 03295 /* Set CONFMUTE mode on DAHDI channel to mute DTMF tones */ 03296 x = 1; 03297 ast_channel_setoption(chan, AST_OPTION_TONE_VERIFY, &x, sizeof(char), 0); 03298 } 03299 /* Find a pointer to the agi app and execute the script */ 03300 agi_app = pbx_findapp("agi"); 03301 if (agi_app) { 03302 ret = pbx_exec(chan, agi_app, agifile); 03303 } else { 03304 ast_log(LOG_WARNING, "Could not find application (agi)\n"); 03305 ret = -2; 03306 } 03307 if (user->dahdichannel) { 03308 /* Remove CONFMUTE mode on DAHDI channel */ 03309 x = 0; 03310 ast_channel_setoption(chan, AST_OPTION_TONE_VERIFY, &x, sizeof(char), 0); 03311 } 03312 } else { 03313 int lastusers = conf->users; 03314 if (user->dahdichannel && ast_test_flag64(confflags, CONFFLAG_STARMENU)) { 03315 /* Set CONFMUTE mode on DAHDI channel to mute DTMF tones when the menu is enabled */ 03316 x = 1; 03317 ast_channel_setoption(chan, AST_OPTION_TONE_VERIFY, &x, sizeof(char), 0); 03318 } 03319 03320 for (;;) { 03321 int menu_was_active = 0; 03322 03323 outfd = -1; 03324 ms = -1; 03325 now = ast_tvnow(); 03326 03327 if (rt_schedule && conf->endtime) { 03328 char currenttime[32]; 03329 long localendtime = 0; 03330 int extended = 0; 03331 struct ast_tm tm; 03332 struct ast_variable *var, *origvar; 03333 struct timeval tmp; 03334 03335 if (now.tv_sec % 60 == 0) { 03336 if (!checked) { 03337 ast_localtime(&now, &tm, NULL); 03338 ast_strftime(currenttime, sizeof(currenttime), DATE_FORMAT, &tm); 03339 var = origvar = ast_load_realtime("meetme", "confno", 03340 conf->confno, "starttime <=", currenttime, 03341 "endtime >=", currenttime, NULL); 03342 03343 for ( ; var; var = var->next) { 03344 if (!strcasecmp(var->name, "endtime")) { 03345 struct ast_tm endtime_tm; 03346 ast_strptime(var->value, "%Y-%m-%d %H:%M:%S", &endtime_tm); 03347 tmp = ast_mktime(&endtime_tm, NULL); 03348 localendtime = tmp.tv_sec; 03349 } 03350 } 03351 ast_variables_destroy(origvar); 03352 03353 /* A conference can be extended from the 03354 Admin/User menu or by an external source */ 03355 if (localendtime > conf->endtime){ 03356 conf->endtime = localendtime; 03357 extended = 1; 03358 } 03359 03360 if (conf->endtime && (now.tv_sec >= conf->endtime)) { 03361 ast_verbose("Quitting time...\n"); 03362 goto outrun; 03363 } 03364 03365 if (!announcement_played && conf->endalert) { 03366 if (now.tv_sec + conf->endalert >= conf->endtime) { 03367 if (!ast_streamfile(chan, "conf-will-end-in", chan->language)) 03368 ast_waitstream(chan, ""); 03369 ast_say_digits(chan, (conf->endtime - now.tv_sec) / 60, "", chan->language); 03370 if (!ast_streamfile(chan, "minutes", chan->language)) 03371 ast_waitstream(chan, ""); 03372 if (musiconhold) { 03373 conf_start_moh(chan, optargs[OPT_ARG_MOH_CLASS]); 03374 } 03375 announcement_played = 1; 03376 } 03377 } 03378 03379 if (extended) { 03380 announcement_played = 0; 03381 } 03382 03383 checked = 1; 03384 } 03385 } else { 03386 checked = 0; 03387 } 03388 } 03389 03390 if (user->kicktime && (user->kicktime <= now.tv_sec)) { 03391 if (ast_test_flag64(confflags, CONFFLAG_KICK_CONTINUE)) { 03392 ret = 0; 03393 } else { 03394 ret = -1; 03395 } 03396 break; 03397 } 03398 03399 to = -1; 03400 if (user->timelimit) { 03401 int minutes = 0, seconds = 0, remain = 0; 03402 03403 to = ast_tvdiff_ms(nexteventts, now); 03404 if (to < 0) { 03405 to = 0; 03406 } 03407 time_left_ms = user->timelimit - ast_tvdiff_ms(now, user->start_time); 03408 if (time_left_ms < to) { 03409 to = time_left_ms; 03410 } 03411 03412 if (time_left_ms <= 0) { 03413 if (user->end_sound) { 03414 res = ast_streamfile(chan, user->end_sound, chan->language); 03415 res = ast_waitstream(chan, ""); 03416 } 03417 if (ast_test_flag64(confflags, CONFFLAG_KICK_CONTINUE)) { 03418 ret = 0; 03419 } else { 03420 ret = -1; 03421 } 03422 break; 03423 } 03424 03425 if (!to) { 03426 if (time_left_ms >= 5000) { 03427 03428 remain = (time_left_ms + 500) / 1000; 03429 if (remain / 60 >= 1) { 03430 minutes = remain / 60; 03431 seconds = remain % 60; 03432 } else { 03433 seconds = remain; 03434 } 03435 03436 /* force the time left to round up if appropriate */ 03437 if (user->warning_sound && user->play_warning) { 03438 if (!strcmp(user->warning_sound, "timeleft")) { 03439 03440 res = ast_streamfile(chan, "vm-youhave", chan->language); 03441 res = ast_waitstream(chan, ""); 03442 if (minutes) { 03443 res = ast_say_number(chan, minutes, AST_DIGIT_ANY, chan->language, (char *) NULL); 03444 res = ast_streamfile(chan, "queue-minutes", chan->language); 03445 res = ast_waitstream(chan, ""); 03446 } 03447 if (seconds) { 03448 res = ast_say_number(chan, seconds, AST_DIGIT_ANY, chan->language, (char *) NULL); 03449 res = ast_streamfile(chan, "queue-seconds", chan->language); 03450 res = ast_waitstream(chan, ""); 03451 } 03452 } else { 03453 res = ast_streamfile(chan, user->warning_sound, chan->language); 03454 res = ast_waitstream(chan, ""); 03455 } 03456 if (musiconhold) { 03457 conf_start_moh(chan, optargs[OPT_ARG_MOH_CLASS]); 03458 } 03459 } 03460 } 03461 if (user->warning_freq) { 03462 nexteventts = ast_tvadd(nexteventts, ast_samp2tv(user->warning_freq, 1000)); 03463 } else { 03464 nexteventts = ast_tvadd(user->start_time, ast_samp2tv(user->timelimit, 1000)); 03465 } 03466 } 03467 } 03468 03469 now = ast_tvnow(); 03470 if (timeout && now.tv_sec >= timeout) { 03471 if (ast_test_flag64(confflags, CONFFLAG_KICK_CONTINUE)) { 03472 ret = 0; 03473 } else { 03474 ret = -1; 03475 } 03476 break; 03477 } 03478 03479 /* if we have just exited from the menu, and the user had a channel-driver 03480 volume adjustment, restore it 03481 */ 03482 if (!menu_mode && menu_was_active && user->listen.desired && !user->listen.actual) { 03483 set_talk_volume(user, user->listen.desired); 03484 } 03485 03486 menu_was_active = menu_mode; 03487 03488 currentmarked = conf->markedusers; 03489 if (!ast_test_flag64(confflags, CONFFLAG_QUIET) && 03490 ast_test_flag64(confflags, CONFFLAG_MARKEDUSER) && 03491 ast_test_flag64(confflags, CONFFLAG_WAITMARKED) && 03492 lastmarked == 0) { 03493 if (currentmarked == 1 && conf->users > 1) { 03494 ast_say_number(chan, conf->users - 1, AST_DIGIT_ANY, chan->language, (char *) NULL); 03495 if (conf->users - 1 == 1) { 03496 if (!ast_streamfile(chan, "conf-userwilljoin", chan->language)) { 03497 ast_waitstream(chan, ""); 03498 } 03499 } else { 03500 if (!ast_streamfile(chan, "conf-userswilljoin", chan->language)) { 03501 ast_waitstream(chan, ""); 03502 } 03503 } 03504 } 03505 if (conf->users == 1 && !ast_test_flag64(confflags, CONFFLAG_MARKEDUSER)) { 03506 if (!ast_streamfile(chan, "conf-onlyperson", chan->language)) { 03507 ast_waitstream(chan, ""); 03508 } 03509 } 03510 } 03511 03512 /* Update the struct with the actual confflags */ 03513 user->userflags = *confflags; 03514 03515 if (ast_test_flag64(confflags, CONFFLAG_WAITMARKED)) { 03516 if (currentmarked == 0) { 03517 if (lastmarked != 0) { 03518 if (!ast_test_flag64(confflags, CONFFLAG_QUIET)) { 03519 if (!ast_streamfile(chan, "conf-leaderhasleft", chan->language)) { 03520 ast_waitstream(chan, ""); 03521 } 03522 } 03523 if (ast_test_flag64(confflags, CONFFLAG_MARKEDEXIT)) { 03524 if (ast_test_flag64(confflags, CONFFLAG_KICK_CONTINUE)) { 03525 ret = 0; 03526 } 03527 break; 03528 } else { 03529 dahdic.confmode = DAHDI_CONF_CONF; 03530 if (ioctl(fd, DAHDI_SETCONF, &dahdic)) { 03531 ast_log(LOG_WARNING, "Error setting conference\n"); 03532 close(fd); 03533 goto outrun; 03534 } 03535 } 03536 } 03537 if (!musiconhold && (ast_test_flag64(confflags, CONFFLAG_MOH))) { 03538 conf_start_moh(chan, optargs[OPT_ARG_MOH_CLASS]); 03539 musiconhold = 1; 03540 } 03541 } else if (currentmarked >= 1 && lastmarked == 0) { 03542 /* Marked user entered, so cancel timeout */ 03543 timeout = 0; 03544 if (ast_test_flag64(confflags, CONFFLAG_MONITOR)) { 03545 dahdic.confmode = DAHDI_CONF_CONFMON | DAHDI_CONF_LISTENER; 03546 } else if (ast_test_flag64(confflags, CONFFLAG_TALKER)) { 03547 dahdic.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER; 03548 } else { 03549 dahdic.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER; 03550 } 03551 if (ioctl(fd, DAHDI_SETCONF, &dahdic)) { 03552 ast_log(LOG_WARNING, "Error setting conference\n"); 03553 close(fd); 03554 goto outrun; 03555 } 03556 if (musiconhold && (ast_test_flag64(confflags, CONFFLAG_MOH))) { 03557 ast_moh_stop(chan); 03558 musiconhold = 0; 03559 } 03560 if (!ast_test_flag64(confflags, CONFFLAG_QUIET) && 03561 !ast_test_flag64(confflags, CONFFLAG_MARKEDUSER)) { 03562 if (!ast_streamfile(chan, "conf-placeintoconf", chan->language)) { 03563 ast_waitstream(chan, ""); 03564 } 03565 conf_play(chan, conf, ENTER); 03566 } 03567 } 03568 } 03569 03570 /* trying to add moh for single person conf */ 03571 if (ast_test_flag64(confflags, CONFFLAG_MOH) && !ast_test_flag64(confflags, CONFFLAG_WAITMARKED)) { 03572 if (conf->users == 1) { 03573 if (!musiconhold) { 03574 conf_start_moh(chan, optargs[OPT_ARG_MOH_CLASS]); 03575 musiconhold = 1; 03576 } 03577 } else { 03578 if (musiconhold) { 03579 ast_moh_stop(chan); 03580 musiconhold = 0; 03581 } 03582 } 03583 } 03584 03585 /* Leave if the last marked user left */ 03586 if (currentmarked == 0 && lastmarked != 0 && ast_test_flag64(confflags, CONFFLAG_MARKEDEXIT)) { 03587 if (ast_test_flag64(confflags, CONFFLAG_KICK_CONTINUE)) { 03588 ret = 0; 03589 } else { 03590 ret = -1; 03591 } 03592 break; 03593 } 03594 03595 /* Throw a TestEvent if a user exit did not cause this user to leave the conference */ 03596 if (conf->users != lastusers) { 03597 if (conf->users < lastusers) { 03598 ast_test_suite_event_notify("NOEXIT", "Message: CONFFLAG_MARKEDEXIT\r\nLastUsers: %d\r\nUsers: %d", lastusers, conf->users); 03599 } 03600 lastusers = conf->users; 03601 } 03602 03603 /* Check if my modes have changed */ 03604 03605 /* If I should be muted but am still talker, mute me */ 03606 if ((user->adminflags & (ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED)) && (dahdic.confmode & DAHDI_CONF_TALKER)) { 03607 dahdic.confmode ^= DAHDI_CONF_TALKER; 03608 if (ioctl(fd, DAHDI_SETCONF, &dahdic)) { 03609 ast_log(LOG_WARNING, "Error setting conference - Un/Mute \n"); 03610 ret = -1; 03611 break; 03612 } 03613 03614 /* Indicate user is not talking anymore - change him to unmonitored state */ 03615 if (ast_test_flag64(confflags, (CONFFLAG_MONITORTALKER | CONFFLAG_OPTIMIZETALKER))) { 03616 set_user_talking(chan, conf, user, -1, ast_test_flag64(confflags, CONFFLAG_MONITORTALKER)); 03617 } 03618 03619 ast_manager_event(chan, EVENT_FLAG_CALL, "MeetmeMute", 03620 "Channel: %s\r\n" 03621 "Uniqueid: %s\r\n" 03622 "Meetme: %s\r\n" 03623 "Usernum: %d\r\n" 03624 "Status: on\r\n", 03625 chan->name, chan->uniqueid, conf->confno, user->user_no); 03626 } 03627 03628 /* If I should be un-muted but am not talker, un-mute me */ 03629 if (!(user->adminflags & (ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED)) && !ast_test_flag64(confflags, CONFFLAG_MONITOR) && !(dahdic.confmode & DAHDI_CONF_TALKER)) { 03630 dahdic.confmode |= DAHDI_CONF_TALKER; 03631 if (ioctl(fd, DAHDI_SETCONF, &dahdic)) { 03632 ast_log(LOG_WARNING, "Error setting conference - Un/Mute \n"); 03633 ret = -1; 03634 break; 03635 } 03636 03637 ast_manager_event(chan, EVENT_FLAG_CALL, "MeetmeMute", 03638 "Channel: %s\r\n" 03639 "Uniqueid: %s\r\n" 03640 "Meetme: %s\r\n" 03641 "Usernum: %d\r\n" 03642 "Status: off\r\n", 03643 chan->name, chan->uniqueid, conf->confno, user->user_no); 03644 } 03645 03646 if ((user->adminflags & (ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED)) && 03647 (user->adminflags & ADMINFLAG_T_REQUEST) && !(talkreq_manager)) { 03648 talkreq_manager = 1; 03649 03650 ast_manager_event(chan, EVENT_FLAG_CALL, "MeetmeTalkRequest", 03651 "Channel: %s\r\n" 03652 "Uniqueid: %s\r\n" 03653 "Meetme: %s\r\n" 03654 "Usernum: %d\r\n" 03655 "Status: on\r\n", 03656 chan->name, chan->uniqueid, conf->confno, user->user_no); 03657 } 03658 03659 03660 if (!(user->adminflags & (ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED)) && 03661 !(user->adminflags & ADMINFLAG_T_REQUEST) && (talkreq_manager)) { 03662 talkreq_manager = 0; 03663 ast_manager_event(chan, EVENT_FLAG_CALL, "MeetmeTalkRequest", 03664 "Channel: %s\r\n" 03665 "Uniqueid: %s\r\n" 03666 "Meetme: %s\r\n" 03667 "Usernum: %d\r\n" 03668 "Status: off\r\n", 03669 chan->name, chan->uniqueid, conf->confno, user->user_no); 03670 } 03671 03672 /* If I have been kicked, exit the conference */ 03673 if (user->adminflags & ADMINFLAG_KICKME) { 03674 /* You have been kicked. */ 03675 if (!ast_test_flag64(confflags, CONFFLAG_QUIET) && 03676 !ast_streamfile(chan, "conf-kicked", chan->language)) { 03677 ast_waitstream(chan, ""); 03678 } 03679 ret = 0; 03680 break; 03681 } 03682 03683 /* Perform a hangup check here since ast_waitfor_nandfds will not always be able to get a channel after a hangup has occurred */ 03684 if (ast_check_hangup(chan)) { 03685 break; 03686 } 03687 03688 c = ast_waitfor_nandfds(&chan, 1, &fd, nfds, NULL, &outfd, &ms); 03689 03690 if (c) { 03691 char dtmfstr[2] = ""; 03692 03693 if (c->fds[0] != origfd || (user->dahdichannel && (c->audiohooks || c->monitor))) { 03694 if (using_pseudo) { 03695 /* Kill old pseudo */ 03696 close(fd); 03697 using_pseudo = 0; 03698 } 03699 ast_debug(1, "Ooh, something swapped out under us, starting over\n"); 03700 retrydahdi = (strcasecmp(c->tech->type, "DAHDI") || (c->audiohooks || c->monitor) ? 1 : 0); 03701 user->dahdichannel = !retrydahdi; 03702 goto dahdiretry; 03703 } 03704 if (ast_test_flag64(confflags, CONFFLAG_MONITOR) || (user->adminflags & (ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED))) { 03705 f = ast_read_noaudio(c); 03706 } else { 03707 f = ast_read(c); 03708 } 03709 if (!f) { 03710 break; 03711 } 03712 if (f->frametype == AST_FRAME_DTMF) { 03713 dtmfstr[0] = f->subclass.integer; 03714 dtmfstr[1] = '\0'; 03715 } 03716 03717 if ((f->frametype == AST_FRAME_VOICE) && (f->subclass.codec == AST_FORMAT_SLINEAR)) { 03718 if (user->talk.actual) { 03719 ast_frame_adjust_volume(f, user->talk.actual); 03720 } 03721 03722 if (ast_test_flag64(confflags, (CONFFLAG_OPTIMIZETALKER | CONFFLAG_MONITORTALKER))) { 03723 if (user->talking == -1) { 03724 user->talking = 0; 03725 } 03726 03727 res = ast_dsp_silence(dsp, f, &totalsilence); 03728 if (!user->talking && totalsilence < MEETME_DELAYDETECTTALK) { 03729 set_user_talking(chan, conf, user, 1, ast_test_flag64(confflags, CONFFLAG_MONITORTALKER)); 03730 } 03731 03732 if (user->talking && totalsilence > MEETME_DELAYDETECTENDTALK) { 03733 set_user_talking(chan, conf, user, 0, ast_test_flag64(confflags, CONFFLAG_MONITORTALKER)); 03734 } 03735 } 03736 if (using_pseudo) { 03737 /* Absolutely do _not_ use careful_write here... 03738 it is important that we read data from the channel 03739 as fast as it arrives, and feed it into the conference. 03740 The buffering in the pseudo channel will take care of any 03741 timing differences, unless they are so drastic as to lose 03742 audio frames (in which case carefully writing would only 03743 have delayed the audio even further). 03744 */ 03745 /* As it turns out, we do want to use careful write. We just 03746 don't want to block, but we do want to at least *try* 03747 to write out all the samples. 03748 */ 03749 if (user->talking || !ast_test_flag64(confflags, CONFFLAG_OPTIMIZETALKER)) { 03750 careful_write(fd, f->data.ptr, f->datalen, 0); 03751 } 03752 } 03753 } else if (((f->frametype == AST_FRAME_DTMF) && (f->subclass.integer == '*') && ast_test_flag64(confflags, CONFFLAG_STARMENU)) || ((f->frametype == AST_FRAME_DTMF) && menu_mode)) { 03754 if (ast_test_flag64(confflags, CONFFLAG_PASS_DTMF)) { 03755 conf_queue_dtmf(conf, user, f); 03756 } 03757 if (ioctl(fd, DAHDI_SETCONF, &dahdic_empty)) { 03758 ast_log(LOG_WARNING, "Error setting conference\n"); 03759 close(fd); 03760 ast_frfree(f); 03761 goto outrun; 03762 } 03763 03764 /* if we are entering the menu, and the user has a channel-driver 03765 volume adjustment, clear it 03766 */ 03767 if (!menu_mode && user->talk.desired && !user->talk.actual) { 03768 set_talk_volume(user, 0); 03769 } 03770 03771 if (musiconhold) { 03772 ast_moh_stop(chan); 03773 } else if (!menu_mode) { 03774 char *menu_to_play; 03775 if (ast_test_flag64(confflags, CONFFLAG_ADMIN)) { 03776 menu_mode = MENU_ADMIN; 03777 menu_to_play = "conf-adminmenu-18"; 03778 } else { 03779 menu_mode = MENU_NORMAL; 03780 menu_to_play = "conf-usermenu-162"; 03781 } 03782 03783 if (!ast_streamfile(chan, menu_to_play, chan->language)) { 03784 dtmf = ast_waitstream(chan, AST_DIGIT_ANY); 03785 ast_stopstream(chan); 03786 } else { 03787 dtmf = 0; 03788 } 03789 } else { 03790 dtmf = f->subclass.integer; 03791 } 03792 03793 if (dtmf > 0) { 03794 meetme_menu(&menu_mode, &dtmf, conf, confflags, chan, user, recordingtmp, sizeof(recordingtmp), &dahdic); 03795 } 03796 03797 if (musiconhold && !menu_mode) { 03798 conf_start_moh(chan, optargs[OPT_ARG_MOH_CLASS]); 03799 } 03800 03801 if (ioctl(fd, DAHDI_SETCONF, &dahdic)) { 03802 ast_log(LOG_WARNING, "Error setting conference\n"); 03803 close(fd); 03804 ast_frfree(f); 03805 goto outrun; 03806 } 03807 03808 conf_flush(fd, chan); 03809 /* 03810 * Since options using DTMF could absorb DTMF meant for the 03811 * conference menu, we have to check them after the menu. 03812 */ 03813 } else if ((f->frametype == AST_FRAME_DTMF) && ast_test_flag64(confflags, CONFFLAG_EXIT_CONTEXT) && ast_exists_extension(chan, exitcontext, dtmfstr, 1, "")) { 03814 if (ast_test_flag64(confflags, CONFFLAG_PASS_DTMF)) { 03815 conf_queue_dtmf(conf, user, f); 03816 } 03817 03818 if (!ast_goto_if_exists(chan, exitcontext, dtmfstr, 1)) { 03819 ast_debug(1, "Got DTMF %c, goto context %s\n", dtmfstr[0], exitcontext); 03820 ret = 0; 03821 ast_frfree(f); 03822 break; 03823 } else { 03824 ast_debug(2, "Exit by single digit did not work in meetme. Extension %s does not exist in context %s\n", dtmfstr, exitcontext); 03825 } 03826 } else if ((f->frametype == AST_FRAME_DTMF) && ast_test_flag64(confflags, CONFFLAG_KEYEXIT) && 03827 (strchr(exitkeys, f->subclass.integer))) { 03828 pbx_builtin_setvar_helper(chan, "MEETME_EXIT_KEY", dtmfstr); 03829 03830 if (ast_test_flag64(confflags, CONFFLAG_PASS_DTMF)) { 03831 conf_queue_dtmf(conf, user, f); 03832 } 03833 ret = 0; 03834 ast_frfree(f); 03835 break; 03836 } else if ((f->frametype == AST_FRAME_DTMF_BEGIN || f->frametype == AST_FRAME_DTMF_END) 03837 && ast_test_flag64(confflags, CONFFLAG_PASS_DTMF)) { 03838 conf_queue_dtmf(conf, user, f); 03839 } else if (ast_test_flag64(confflags, CONFFLAG_SLA_STATION) && f->frametype == AST_FRAME_CONTROL) { 03840 switch (f->subclass.integer) { 03841 case AST_CONTROL_HOLD: 03842 sla_queue_event_conf(SLA_EVENT_HOLD, chan, conf); 03843 break; 03844 default: 03845 break; 03846 } 03847 } else if (f->frametype == AST_FRAME_NULL) { 03848 /* Ignore NULL frames. It is perfectly normal to get these if the person is muted. */ 03849 } else if (f->frametype == AST_FRAME_CONTROL) { 03850 switch (f->subclass.integer) { 03851 case AST_CONTROL_BUSY: 03852 case AST_CONTROL_CONGESTION: 03853 ast_frfree(f); 03854 goto outrun; 03855 break; 03856 default: 03857 ast_debug(1, 03858 "Got ignored control frame on channel %s, f->frametype=%d,f->subclass=%d\n", 03859 chan->name, f->frametype, f->subclass.integer); 03860 } 03861 } else { 03862 ast_debug(1, 03863 "Got unrecognized frame on channel %s, f->frametype=%d,f->subclass=%d\n", 03864 chan->name, f->frametype, f->subclass.integer); 03865 } 03866 ast_frfree(f); 03867 } else if (outfd > -1) { 03868 res = read(outfd, buf, CONF_SIZE); 03869 if (res > 0) { 03870 memset(&fr, 0, sizeof(fr)); 03871 fr.frametype = AST_FRAME_VOICE; 03872 fr.subclass.codec = AST_FORMAT_SLINEAR; 03873 fr.datalen = res; 03874 fr.samples = res / 2; 03875 fr.data.ptr = buf; 03876 fr.offset = AST_FRIENDLY_OFFSET; 03877 if (!user->listen.actual && 03878 (ast_test_flag64(confflags, CONFFLAG_MONITOR) || 03879 (user->adminflags & (ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED)) || 03880 (!user->talking && ast_test_flag64(confflags, CONFFLAG_OPTIMIZETALKER)) 03881 )) { 03882 int idx; 03883 for (idx = 0; idx < AST_FRAME_BITS; idx++) { 03884 if (chan->rawwriteformat & (1 << idx)) { 03885 break; 03886 } 03887 } 03888 if (idx >= AST_FRAME_BITS) { 03889 goto bailoutandtrynormal; 03890 } 03891 ast_mutex_lock(&conf->listenlock); 03892 if (!conf->transframe[idx]) { 03893 if (conf->origframe) { 03894 if (musiconhold && !ast_dsp_silence(dsp, conf->origframe, &confsilence) && confsilence < MEETME_DELAYDETECTTALK) { 03895 ast_moh_stop(chan); 03896 mohtempstopped = 1; 03897 } 03898 if (!conf->transpath[idx]) { 03899 conf->transpath[idx] = ast_translator_build_path((1 << idx), AST_FORMAT_SLINEAR); 03900 } 03901 if (conf->transpath[idx]) { 03902 conf->transframe[idx] = ast_translate(conf->transpath[idx], conf->origframe, 0); 03903 if (!conf->transframe[idx]) { 03904 conf->transframe[idx] = &ast_null_frame; 03905 } 03906 } 03907 } 03908 } 03909 if (conf->transframe[idx]) { 03910 if ((conf->transframe[idx]->frametype != AST_FRAME_NULL) && 03911 can_write(chan, confflags)) { 03912 struct ast_frame *cur; 03913 /* the translator may have returned a list of frames, so 03914 write each one onto the channel 03915 */ 03916 for (cur = conf->transframe[idx]; cur; cur = AST_LIST_NEXT(cur, frame_list)) { 03917 if (ast_write(chan, cur)) { 03918 ast_log(LOG_WARNING, "Unable to write frame to channel %s\n", chan->name); 03919 break; 03920 } 03921 } 03922 if (musiconhold && mohtempstopped && confsilence > MEETME_DELAYDETECTENDTALK) { 03923 mohtempstopped = 0; 03924 conf_start_moh(chan, optargs[OPT_ARG_MOH_CLASS]); 03925 } 03926 } 03927 } else { 03928 ast_mutex_unlock(&conf->listenlock); 03929 goto bailoutandtrynormal; 03930 } 03931 ast_mutex_unlock(&conf->listenlock); 03932 } else { 03933 bailoutandtrynormal: 03934 if (musiconhold && !ast_dsp_silence(dsp, &fr, &confsilence) && confsilence < MEETME_DELAYDETECTTALK) { 03935 ast_moh_stop(chan); 03936 mohtempstopped = 1; 03937 } 03938 if (user->listen.actual) { 03939 ast_frame_adjust_volume(&fr, user->listen.actual); 03940 } 03941 if (can_write(chan, confflags) && ast_write(chan, &fr) < 0) { 03942 ast_log(LOG_WARNING, "Unable to write frame to channel %s\n", chan->name); 03943 } 03944 if (musiconhold && mohtempstopped && confsilence > MEETME_DELAYDETECTENDTALK) { 03945 mohtempstopped = 0; 03946 conf_start_moh(chan, optargs[OPT_ARG_MOH_CLASS]); 03947 } 03948 } 03949 } else { 03950 ast_log(LOG_WARNING, "Failed to read frame: %s\n", strerror(errno)); 03951 } 03952 } 03953 lastmarked = currentmarked; 03954 } 03955 } 03956 03957 if (musiconhold) { 03958 ast_moh_stop(chan); 03959 } 03960 03961 if (using_pseudo) { 03962 close(fd); 03963 } else { 03964 /* Take out of conference */ 03965 dahdic.chan = 0; 03966 dahdic.confno = 0; 03967 dahdic.confmode = 0; 03968 if (ioctl(fd, DAHDI_SETCONF, &dahdic)) { 03969 ast_log(LOG_WARNING, "Error setting conference\n"); 03970 } 03971 } 03972 03973 reset_volumes(user); 03974 03975 if (!ast_test_flag64(confflags, CONFFLAG_QUIET) && !ast_test_flag64(confflags, CONFFLAG_MONITOR) && 03976 !ast_test_flag64(confflags, CONFFLAG_ADMIN)) { 03977 conf_play(chan, conf, LEAVE); 03978 } 03979 03980 if (!ast_test_flag64(confflags, CONFFLAG_QUIET) && (ast_test_flag64(confflags, CONFFLAG_INTROUSER) || ast_test_flag64(confflags, CONFFLAG_INTROUSERNOREVIEW)) && conf->users > 1) { 03981 struct announce_listitem *item; 03982 if (!(item = ao2_alloc(sizeof(*item), NULL))) 03983 goto outrun; 03984 ast_copy_string(item->namerecloc, user->namerecloc, sizeof(item->namerecloc)); 03985 ast_copy_string(item->language, chan->language, sizeof(item->language)); 03986 item->confchan = conf->chan; 03987 item->confusers = conf->users; 03988 item->announcetype = CONF_HASLEFT; 03989 ast_mutex_lock(&conf->announcelistlock); 03990 AST_LIST_INSERT_TAIL(&conf->announcelist, item, entry); 03991 ast_cond_signal(&conf->announcelist_addition); 03992 ast_mutex_unlock(&conf->announcelistlock); 03993 } else if (!ast_test_flag64(confflags, CONFFLAG_QUIET) && (ast_test_flag64(confflags, CONFFLAG_INTROUSER) || 03994 ast_test_flag64(confflags, CONFFLAG_INTROUSERNOREVIEW)) && conf->users == 1) { 03995 /* Last person is leaving, so no reason to try and announce, but should delete the name recording */ 03996 ast_filedelete(user->namerecloc, NULL); 03997 } 03998 03999 outrun: 04000 AST_LIST_LOCK(&confs); 04001 04002 if (dsp) { 04003 ast_dsp_free(dsp); 04004 } 04005 04006 if (user->user_no) { 04007 /* Only cleanup users who really joined! */ 04008 now = ast_tvnow(); 04009 04010 if (sent_event) { 04011 ast_manager_event(chan, EVENT_FLAG_CALL, "MeetmeLeave", 04012 "Channel: %s\r\n" 04013 "Uniqueid: %s\r\n" 04014 "Meetme: %s\r\n" 04015 "Usernum: %d\r\n" 04016 "CallerIDNum: %s\r\n" 04017 "CallerIDName: %s\r\n" 04018 "ConnectedLineNum: %s\r\n" 04019 "ConnectedLineName: %s\r\n" 04020 "Duration: %ld\r\n", 04021 chan->name, chan->uniqueid, conf->confno, 04022 user->user_no, 04023 S_COR(user->chan->caller.id.number.valid, user->chan->caller.id.number.str, "<unknown>"), 04024 S_COR(user->chan->caller.id.name.valid, user->chan->caller.id.name.str, "<unknown>"), 04025 S_COR(user->chan->connected.id.number.valid, user->chan->connected.id.number.str, "<unknown>"), 04026 S_COR(user->chan->connected.id.name.valid, user->chan->connected.id.name.str, "<unknown>"), 04027 (long)(now.tv_sec - user->jointime)); 04028 } 04029 04030 if (setusercount) { 04031 conf->users--; 04032 if (rt_log_members) { 04033 /* Update table */ 04034 snprintf(members, sizeof(members), "%d", conf->users); 04035 ast_realtime_require_field("meetme", 04036 "confno", strlen(conf->confno) > 7 ? RQ_UINTEGER4 : strlen(conf->confno) > 4 ? RQ_UINTEGER3 : RQ_UINTEGER2, strlen(conf->confno), 04037 "members", RQ_UINTEGER1, strlen(members), 04038 NULL); 04039 ast_update_realtime("meetme", "confno", conf->confno, "members", members, NULL); 04040 } 04041 if (ast_test_flag64(confflags, CONFFLAG_MARKEDUSER)) { 04042 conf->markedusers--; 04043 } 04044 } 04045 /* Remove ourselves from the container */ 04046 ao2_unlink(conf->usercontainer, user); 04047 04048 /* Change any states */ 04049 if (!conf->users) { 04050 ast_devstate_changed(AST_DEVICE_NOT_INUSE, (conf->isdynamic ? AST_DEVSTATE_NOT_CACHABLE : AST_DEVSTATE_CACHABLE), "meetme:%s", conf->confno); 04051 } 04052 04053 /* Return the number of seconds the user was in the conf */ 04054 snprintf(meetmesecs, sizeof(meetmesecs), "%d", (int) (time(NULL) - user->jointime)); 04055 pbx_builtin_setvar_helper(chan, "MEETMESECS", meetmesecs); 04056 04057 /* Return the RealTime bookid for CDR linking */ 04058 if (rt_schedule) { 04059 pbx_builtin_setvar_helper(chan, "MEETMEBOOKID", conf->bookid); 04060 } 04061 } 04062 ao2_ref(user, -1); 04063 AST_LIST_UNLOCK(&confs); 04064 04065 return ret; 04066 }
| 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 4360 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().
04361 { 04362 int res = 0; 04363 struct ast_conference *conf; 04364 int count; 04365 char *localdata; 04366 char val[80] = "0"; 04367 AST_DECLARE_APP_ARGS(args, 04368 AST_APP_ARG(confno); 04369 AST_APP_ARG(varname); 04370 ); 04371 04372 if (ast_strlen_zero(data)) { 04373 ast_log(LOG_WARNING, "MeetMeCount requires an argument (conference number)\n"); 04374 return -1; 04375 } 04376 04377 localdata = ast_strdupa(data); 04378 04379 AST_STANDARD_APP_ARGS(args, localdata); 04380 04381 conf = find_conf(chan, args.confno, 0, 0, NULL, 0, 1, NULL); 04382 04383 if (conf) { 04384 count = conf->users; 04385 dispose_conf(conf); 04386 conf = NULL; 04387 } else 04388 count = 0; 04389 04390 if (!ast_strlen_zero(args.varname)) { 04391 /* have var so load it and exit */ 04392 snprintf(val, sizeof(val), "%d", count); 04393 pbx_builtin_setvar_helper(chan, args.varname, val); 04394 } else { 04395 if (chan->_state != AST_STATE_UP) { 04396 ast_answer(chan); 04397 } 04398 res = ast_say_number(chan, count, "", chan->language, (char *) NULL); /* Needs gender */ 04399 } 04400 04401 return res; 04402 }
| static struct sla_trunk_ref* create_trunk_ref | ( | struct sla_trunk * | trunk | ) | [static, read] |
Definition at line 6677 of file app_meetme.c.
References ao2_alloc, ao2_ref, and sla_trunk_ref_destructor().
Referenced by sla_add_trunk_to_station().
06678 { 06679 struct sla_trunk_ref *trunk_ref; 06680 06681 if (!(trunk_ref = ao2_alloc(sizeof(*trunk_ref), sla_trunk_ref_destructor))) { 06682 return NULL; 06683 } 06684 06685 ao2_ref(trunk, 1); 06686 trunk_ref->trunk = trunk; 06687 06688 return trunk_ref; 06689 }
| static void* dial_trunk | ( | void * | data | ) | [static] |
Definition at line 6361 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().
06362 { 06363 struct dial_trunk_args *args = data; 06364 struct ast_dial *dial; 06365 char *tech, *tech_data; 06366 enum ast_dial_result dial_res; 06367 char conf_name[MAX_CONFNUM]; 06368 struct ast_conference *conf; 06369 struct ast_flags64 conf_flags = { 0 }; 06370 RAII_VAR(struct sla_trunk_ref *, trunk_ref, args->trunk_ref, unref_obj); 06371 RAII_VAR(struct sla_station *, station, args->station, unref_obj); 06372 int caller_is_saved; 06373 struct ast_party_caller caller; 06374 int last_state = 0; 06375 int current_state = 0; 06376 06377 if (!(dial = ast_dial_create())) { 06378 ast_mutex_lock(args->cond_lock); 06379 ast_cond_signal(args->cond); 06380 ast_mutex_unlock(args->cond_lock); 06381 return NULL; 06382 } 06383 06384 tech_data = ast_strdupa(trunk_ref->trunk->device); 06385 tech = strsep(&tech_data, "/"); 06386 if (ast_dial_append(dial, tech, tech_data) == -1) { 06387 ast_mutex_lock(args->cond_lock); 06388 ast_cond_signal(args->cond); 06389 ast_mutex_unlock(args->cond_lock); 06390 ast_dial_destroy(dial); 06391 return NULL; 06392 } 06393 06394 /* Do we need to save of the caller ID data? */ 06395 caller_is_saved = 0; 06396 if (!sla.attempt_callerid) { 06397 caller_is_saved = 1; 06398 caller = trunk_ref->chan->caller; 06399 ast_party_caller_init(&trunk_ref->chan->caller); 06400 } 06401 06402 dial_res = ast_dial_run(dial, trunk_ref->chan, 1); 06403 06404 /* Restore saved caller ID */ 06405 if (caller_is_saved) { 06406 ast_party_caller_free(&trunk_ref->chan->caller); 06407 trunk_ref->chan->caller = caller; 06408 } 06409 06410 if (dial_res != AST_DIAL_RESULT_TRYING) { 06411 ast_mutex_lock(args->cond_lock); 06412 ast_cond_signal(args->cond); 06413 ast_mutex_unlock(args->cond_lock); 06414 ast_dial_destroy(dial); 06415 return NULL; 06416 } 06417 06418 for (;;) { 06419 unsigned int done = 0; 06420 switch ((dial_res = ast_dial_state(dial))) { 06421 case AST_DIAL_RESULT_ANSWERED: 06422 trunk_ref->trunk->chan = ast_dial_answered(dial); 06423 case AST_DIAL_RESULT_HANGUP: 06424 case AST_DIAL_RESULT_INVALID: 06425 case AST_DIAL_RESULT_FAILED: 06426 case AST_DIAL_RESULT_TIMEOUT: 06427 case AST_DIAL_RESULT_UNANSWERED: 06428 done = 1; 06429 break; 06430 case AST_DIAL_RESULT_TRYING: 06431 current_state = AST_CONTROL_PROGRESS; 06432 break; 06433 case AST_DIAL_RESULT_RINGING: 06434 case AST_DIAL_RESULT_PROGRESS: 06435 case AST_DIAL_RESULT_PROCEEDING: 06436 current_state = AST_CONTROL_RINGING; 06437 break; 06438 } 06439 if (done) 06440 break; 06441 06442 /* check that SLA station that originated trunk call is still alive */ 06443 if (station && ast_device_state(station->device) == AST_DEVICE_NOT_INUSE) { 06444 ast_debug(3, "Originating station device %s no longer active\n", station->device); 06445 trunk_ref->trunk->chan = NULL; 06446 break; 06447 } 06448 06449 /* If trunk line state changed, send indication back to originating SLA Station channel */ 06450 if (current_state != last_state) { 06451 ast_debug(3, "Indicating State Change %d to channel %s\n", current_state, trunk_ref->chan->name); 06452 ast_indicate(trunk_ref->chan, current_state); 06453 last_state = current_state; 06454 } 06455 06456 /* avoid tight loop... sleep for 1/10th second */ 06457 ast_safe_sleep(trunk_ref->chan, 100); 06458 } 06459 06460 if (!trunk_ref->trunk->chan) { 06461 ast_mutex_lock(args->cond_lock); 06462 ast_cond_signal(args->cond); 06463 ast_mutex_unlock(args->cond_lock); 06464 ast_dial_join(dial); 06465 ast_dial_destroy(dial); 06466 return NULL; 06467 } 06468 06469 snprintf(conf_name, sizeof(conf_name), "SLA_%s", trunk_ref->trunk->name); 06470 ast_set_flag64(&conf_flags, 06471 CONFFLAG_QUIET | CONFFLAG_MARKEDEXIT | CONFFLAG_MARKEDUSER | 06472 CONFFLAG_PASS_DTMF | CONFFLAG_SLA_TRUNK); 06473 conf = build_conf(conf_name, "", "", 1, 1, 1, trunk_ref->trunk->chan, NULL); 06474 06475 ast_mutex_lock(args->cond_lock); 06476 ast_cond_signal(args->cond); 06477 ast_mutex_unlock(args->cond_lock); 06478 06479 if (conf) { 06480 conf_run(trunk_ref->trunk->chan, conf, &conf_flags, NULL); 06481 dispose_conf(conf); 06482 conf = NULL; 06483 } 06484 06485 /* If the trunk is going away, it is definitely now IDLE. */ 06486 sla_change_trunk_state(trunk_ref->trunk, SLA_TRUNK_STATE_IDLE, ALL_TRUNK_REFS, NULL); 06487 06488 trunk_ref->trunk->chan = NULL; 06489 trunk_ref->trunk->on_hold = 0; 06490 06491 ast_dial_join(dial); 06492 ast_dial_destroy(dial); 06493 06494 return NULL; 06495 }
| 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 5172 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().
05173 { 05174 char *slash; 05175 if (ast_strlen_zero(filename)) { 05176 ast_log(LOG_WARNING, "No file name was provided for a file save option.\n"); 05177 } else if (filename[0] != '/') { 05178 snprintf(buffer, PATH_MAX, "%s/meetme/%s", ast_config_AST_SPOOL_DIR, filename); 05179 } else { 05180 ast_copy_string(buffer, filename, PATH_MAX); 05181 } 05182 05183 slash = buffer; 05184 if ((slash = strrchr(slash, '/'))) { 05185 *slash = '\0'; 05186 ast_mkdir(buffer, 0777); 05187 *slash = '/'; 05188 } 05189 }
| 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 4256 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().
04258 { 04259 struct ast_config *cfg; 04260 struct ast_variable *var; 04261 struct ast_flags config_flags = { 0 }; 04262 struct ast_conference *cnf; 04263 04264 AST_DECLARE_APP_ARGS(args, 04265 AST_APP_ARG(confno); 04266 AST_APP_ARG(pin); 04267 AST_APP_ARG(pinadmin); 04268 ); 04269 04270 /* Check first in the conference list */ 04271 ast_debug(1, "The requested confno is '%s'?\n", confno); 04272 AST_LIST_LOCK(&confs); 04273 AST_LIST_TRAVERSE(&confs, cnf, list) { 04274 ast_debug(3, "Does conf %s match %s?\n", confno, cnf->confno); 04275 if (!strcmp(confno, cnf->confno)) 04276 break; 04277 } 04278 if (cnf) { 04279 cnf->refcount += refcount; 04280 } 04281 AST_LIST_UNLOCK(&confs); 04282 04283 if (!cnf) { 04284 if (dynamic) { 04285 /* No need to parse meetme.conf */ 04286 ast_debug(1, "Building dynamic conference '%s'\n", confno); 04287 if (dynamic_pin) { 04288 if (dynamic_pin[0] == 'q') { 04289 /* Query the user to enter a PIN */ 04290 if (ast_app_getdata(chan, "conf-getpin", dynamic_pin, pin_buf_len - 1, 0) < 0) 04291 return NULL; 04292 } 04293 cnf = build_conf(confno, dynamic_pin, "", make, dynamic, refcount, chan, NULL); 04294 } else { 04295 cnf = build_conf(confno, "", "", make, dynamic, refcount, chan, NULL); 04296 } 04297 } else { 04298 /* Check the config */ 04299 cfg = ast_config_load(CONFIG_FILE_NAME, config_flags); 04300 if (!cfg) { 04301 ast_log(LOG_WARNING, "No %s file :(\n", CONFIG_FILE_NAME); 04302 return NULL; 04303 } else if (cfg == CONFIG_STATUS_FILEINVALID) { 04304 ast_log(LOG_ERROR, "Config file " CONFIG_FILE_NAME " is in an invalid format. Aborting.\n"); 04305 return NULL; 04306 } 04307 04308 for (var = ast_variable_browse(cfg, "rooms"); var; var = var->next) { 04309 char parse[MAX_SETTINGS]; 04310 04311 if (strcasecmp(var->name, "conf")) 04312 continue; 04313 04314 ast_copy_string(parse, var->value, sizeof(parse)); 04315 04316 AST_STANDARD_APP_ARGS(args, parse); 04317 ast_debug(3, "Will conf %s match %s?\n", confno, args.confno); 04318 if (!strcasecmp(args.confno, confno)) { 04319 /* Bingo it's a valid conference */ 04320 cnf = build_conf(args.confno, 04321 S_OR(args.pin, ""), 04322 S_OR(args.pinadmin, ""), 04323 make, dynamic, refcount, chan, NULL); 04324 break; 04325 } 04326 } 04327 if (!var) { 04328 ast_debug(1, "%s isn't a valid conference\n", confno); 04329 } 04330 ast_config_destroy(cfg); 04331 } 04332 } else if (dynamic_pin) { 04333 /* Correct for the user selecting 'D' instead of 'd' to have 04334 someone join into a conference that has already been created 04335 with a pin. */ 04336 if (dynamic_pin[0] == 'q') { 04337 dynamic_pin[0] = '\0'; 04338 } 04339 } 04340 04341 if (cnf) { 04342 if (confflags && !cnf->chan && 04343 !ast_test_flag64(confflags, CONFFLAG_QUIET) && 04344 ast_test_flag64(confflags, CONFFLAG_INTROUSER | CONFFLAG_INTROUSERNOREVIEW)) { 04345 ast_log(LOG_WARNING, "No DAHDI channel available for conference, user introduction disabled (is chan_dahdi loaded?)\n"); 04346 ast_clear_flag64(confflags, CONFFLAG_INTROUSER | CONFFLAG_INTROUSERNOREVIEW); 04347 } 04348 04349 if (confflags && !cnf->chan && 04350 ast_test_flag64(confflags, CONFFLAG_RECORDCONF)) { 04351 ast_log(LOG_WARNING, "No DAHDI channel available for conference, conference recording disabled (is chan_dahdi loaded?)\n"); 04352 ast_clear_flag64(confflags, CONFFLAG_RECORDCONF); 04353 } 04354 } 04355 04356 return cnf; 04357 }
| 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 4068 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().
04070 { 04071 struct ast_variable *var, *origvar; 04072 struct ast_conference *cnf; 04073 04074 *too_early = 0; 04075 04076 /* Check first in the conference list */ 04077 AST_LIST_LOCK(&confs); 04078 AST_LIST_TRAVERSE(&confs, cnf, list) { 04079 if (!strcmp(confno, cnf->confno)) { 04080 break; 04081 } 04082 } 04083 if (cnf) { 04084 cnf->refcount += refcount; 04085 } 04086 AST_LIST_UNLOCK(&confs); 04087 04088 if (!cnf) { 04089 char *pin = NULL, *pinadmin = NULL; /* For temp use */ 04090 int maxusers = 0; 04091 struct timeval now; 04092 char recordingfilename[256] = ""; 04093 char recordingformat[11] = ""; 04094 char currenttime[32] = ""; 04095 char eatime[32] = ""; 04096 char bookid[51] = ""; 04097 char recordingtmp[AST_MAX_EXTENSION] = ""; 04098 char useropts[OPTIONS_LEN + 1] = ""; /* Used for RealTime conferences */ 04099 char adminopts[OPTIONS_LEN + 1] = ""; 04100 struct ast_tm tm, etm; 04101 struct timeval endtime = { .tv_sec = 0 }; 04102 const char *var2; 04103 04104 if (rt_schedule) { 04105 now = ast_tvnow(); 04106 04107 ast_localtime(&now, &tm, NULL); 04108 ast_strftime(currenttime, sizeof(currenttime), DATE_FORMAT, &tm); 04109 04110 ast_debug(1, "Looking for conference %s that starts after %s\n", confno, currenttime); 04111 04112 var = ast_load_realtime("meetme", "confno", 04113 confno, "starttime <= ", currenttime, "endtime >= ", 04114 currenttime, NULL); 04115 04116 if (!var && fuzzystart) { 04117 now = ast_tvnow(); 04118 now.tv_sec += fuzzystart; 04119 04120 ast_localtime(&now, &tm, NULL); 04121 ast_strftime(currenttime, sizeof(currenttime), DATE_FORMAT, &tm); 04122 var = ast_load_realtime("meetme", "confno", 04123 confno, "starttime <= ", currenttime, "endtime >= ", 04124 currenttime, NULL); 04125 } 04126 04127 if (!var && earlyalert) { 04128 now = ast_tvnow(); 04129 now.tv_sec += earlyalert; 04130 ast_localtime(&now, &etm, NULL); 04131 ast_strftime(eatime, sizeof(eatime), DATE_FORMAT, &etm); 04132 var = ast_load_realtime("meetme", "confno", 04133 confno, "starttime <= ", eatime, "endtime >= ", 04134 currenttime, NULL); 04135 if (var) { 04136 *too_early = 1; 04137 } 04138 } 04139 04140 } else { 04141 var = ast_load_realtime("meetme", "confno", confno, NULL); 04142 } 04143 04144 if (!var) { 04145 return NULL; 04146 } 04147 04148 if (rt_schedule && *too_early) { 04149 /* Announce that the caller is early and exit */ 04150 if (!ast_streamfile(chan, "conf-has-not-started", chan->language)) { 04151 ast_waitstream(chan, ""); 04152 } 04153 ast_variables_destroy(var); 04154 return NULL; 04155 } 04156 04157 for (origvar = var; var; var = var->next) { 04158 if (!strcasecmp(var->name, "pin")) { 04159 pin = ast_strdupa(var->value); 04160 } else if (!strcasecmp(var->name, "adminpin")) { 04161 pinadmin = ast_strdupa(var->value); 04162 } else if (!strcasecmp(var->name, "bookId")) { 04163 ast_copy_string(bookid, var->value, sizeof(bookid)); 04164 } else if (!strcasecmp(var->name, "opts")) { 04165 ast_copy_string(useropts, var->value, sizeof(char[OPTIONS_LEN + 1])); 04166 } else if (!strcasecmp(var->name, "maxusers")) { 04167 maxusers = atoi(var->value); 04168 } else if (!strcasecmp(var->name, "adminopts")) { 04169 ast_copy_string(adminopts, var->value, sizeof(char[OPTIONS_LEN + 1])); 04170 } else if (!strcasecmp(var->name, "recordingfilename")) { 04171 ast_copy_string(recordingfilename, var->value, sizeof(recordingfilename)); 04172 } else if (!strcasecmp(var->name, "recordingformat")) { 04173 ast_copy_string(recordingformat, var->value, sizeof(recordingformat)); 04174 } else if (!strcasecmp(var->name, "endtime")) { 04175 struct ast_tm endtime_tm; 04176 ast_strptime(var->value, "%Y-%m-%d %H:%M:%S", &endtime_tm); 04177 endtime = ast_mktime(&endtime_tm, NULL); 04178 } 04179 } 04180 04181 ast_variables_destroy(origvar); 04182 04183 cnf = build_conf(confno, pin ? pin : "", pinadmin ? pinadmin : "", make, dynamic, refcount, chan, NULL); 04184 04185 if (cnf) { 04186 struct ast_flags64 tmp_flags; 04187 04188 cnf->maxusers = maxusers; 04189 cnf->endalert = endalert; 04190 cnf->endtime = endtime.tv_sec; 04191 cnf->useropts = ast_strdup(useropts); 04192 cnf->adminopts = ast_strdup(adminopts); 04193 cnf->bookid = ast_strdup(bookid); 04194 if (!ast_strlen_zero(recordingfilename)) { 04195 cnf->recordingfilename = ast_strdup(recordingfilename); 04196 } 04197 if (!ast_strlen_zero(recordingformat)) { 04198 cnf->recordingformat = ast_strdup(recordingformat); 04199 } 04200 04201 /* Parse the other options into confflags -- need to do this in two 04202 * steps, because the parse_options routine zeroes the buffer. */ 04203 ast_app_parse_options64(meetme_opts, &tmp_flags, optargs, useropts); 04204 ast_copy_flags64(confflags, &tmp_flags, tmp_flags.flags); 04205 04206 if (strchr(cnf->useropts, 'r')) { 04207 if (ast_strlen_zero(recordingfilename)) { /* If the recordingfilename in the database is empty, use the channel definition or use the default. */ 04208 ast_channel_lock(chan); 04209 if ((var2 = pbx_builtin_getvar_helper(chan, "MEETME_RECORDINGFILE"))) { 04210 ast_free(cnf->recordingfilename); 04211 cnf->recordingfilename = ast_strdup(var2); 04212 } 04213 ast_channel_unlock(chan); 04214 if (ast_strlen_zero(cnf->recordingfilename)) { 04215 snprintf(recordingtmp, sizeof(recordingtmp), "meetme-conf-rec-%s-%s", cnf->confno, chan->uniqueid); 04216 ast_free(cnf->recordingfilename); 04217 cnf->recordingfilename = ast_strdup(recordingtmp); 04218 } 04219 } 04220 if (ast_strlen_zero(cnf->recordingformat)) {/* If the recording format is empty, use the wav as default */ 04221 ast_channel_lock(chan); 04222 if ((var2 = pbx_builtin_getvar_helper(chan, "MEETME_RECORDINGFORMAT"))) { 04223 ast_free(cnf->recordingformat); 04224 cnf->recordingformat = ast_strdup(var2); 04225 } 04226 ast_channel_unlock(chan); 04227 if (ast_strlen_zero(cnf->recordingformat)) { 04228 ast_free(cnf->recordingformat); 04229 cnf->recordingformat = ast_strdup("wav"); 04230 } 04231 } 04232 ast_verb(4, "Starting recording of MeetMe Conference %s into file %s.%s.\n", cnf->confno, cnf->recordingfilename, cnf->recordingformat); 04233 } 04234 } 04235 } 04236 04237 if (cnf) { 04238 if (confflags->flags && !cnf->chan && 04239 !ast_test_flag64(confflags, CONFFLAG_QUIET) && 04240 ast_test_flag64(confflags, CONFFLAG_INTROUSER | CONFFLAG_INTROUSERNOREVIEW)) { 04241 ast_log(LOG_WARNING, "No DAHDI channel available for conference, user introduction disabled (is chan_dahdi loaded?)\n"); 04242 ast_clear_flag64(confflags, CONFFLAG_INTROUSER | CONFFLAG_INTROUSERNOREVIEW); 04243 } 04244 04245 if (confflags && !cnf->chan && 04246 ast_test_flag64(confflags, CONFFLAG_RECORDCONF)) { 04247 ast_log(LOG_WARNING, "No DAHDI channel available for conference, conference recording disabled (is chan_dahdi loaded?)\n"); 04248 ast_clear_flag64(confflags, CONFFLAG_RECORDCONF); 04249 } 04250 } 04251 04252 return cnf; 04253 }
| static struct ast_conf_user* find_user | ( | struct ast_conference * | conf, | |
| const char * | callerident | |||
| ) | [static, read] |
Definition at line 4730 of file app_meetme.c.
References ao2_find, and ast_conference::usercontainer.
Referenced by admin_exec().
04731 { 04732 struct ast_conf_user *user = NULL; 04733 int cid; 04734 04735 if (conf && callerident && sscanf(callerident, "%30d", &cid) == 1) { 04736 user = ao2_find(conf->usercontainer, &cid, 0); 04737 /* reference decremented later in admin_exec */ 04738 return user; 04739 } 04740 return NULL; 04741 }
| 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 7521 of file app_meetme.c.
References load_config_meetme(), and sla_load_config().
Referenced by load_module(), and reload().
07522 { 07523 load_config_meetme(); 07524 return sla_load_config(reload); 07525 }
| static void load_config_meetme | ( | void | ) | [static] |
Definition at line 5282 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().
05283 { 05284 struct ast_config *cfg; 05285 struct ast_flags config_flags = { 0 }; 05286 const char *val; 05287 05288 if (!(cfg = ast_config_load(CONFIG_FILE_NAME, config_flags))) { 05289 return; 05290 } else if (cfg == CONFIG_STATUS_FILEINVALID) { 05291 ast_log(LOG_ERROR, "Config file " CONFIG_FILE_NAME " is in an invalid format. Aborting.\n"); 05292 return; 05293 } 05294 05295 audio_buffers = DEFAULT_AUDIO_BUFFERS; 05296 05297 /* Scheduling support is off by default */ 05298 rt_schedule = 0; 05299 fuzzystart = 0; 05300 earlyalert = 0; 05301 endalert = 0; 05302 extendby = 0; 05303 05304 /* Logging of participants defaults to ON for compatibility reasons */ 05305 rt_log_members = 1; 05306 05307 if ((val = ast_variable_retrieve(cfg, "general", "audiobuffers"))) { 05308 if ((sscanf(val, "%30d", &audio_buffers) != 1)) { 05309 ast_log(LOG_WARNING, "audiobuffers setting must be a number, not '%s'\n", val); 05310 audio_buffers = DEFAULT_AUDIO_BUFFERS; 05311 } else if ((audio_buffers < DAHDI_DEFAULT_NUM_BUFS) || (audio_buffers > DAHDI_MAX_NUM_BUFS)) { 05312 ast_log(LOG_WARNING, "audiobuffers setting must be between %d and %d\n", 05313 DAHDI_DEFAULT_NUM_BUFS, DAHDI_MAX_NUM_BUFS); 05314 audio_buffers = DEFAULT_AUDIO_BUFFERS; 05315 } 05316 if (audio_buffers != DEFAULT_AUDIO_BUFFERS) 05317 ast_log(LOG_NOTICE, "Audio buffers per channel set to %d\n", audio_buffers); 05318 } 05319 05320 if ((val = ast_variable_retrieve(cfg, "general", "schedule"))) 05321 rt_schedule = ast_true(val); 05322 if ((val = ast_variable_retrieve(cfg, "general", "logmembercount"))) 05323 rt_log_members = ast_true(val); 05324 if ((val = ast_variable_retrieve(cfg, "general", "fuzzystart"))) { 05325 if ((sscanf(val, "%30d", &fuzzystart) != 1)) { 05326 ast_log(LOG_WARNING, "fuzzystart must be a number, not '%s'\n", val); 05327 fuzzystart = 0; 05328 } 05329 } 05330 if ((val = ast_variable_retrieve(cfg, "general", "earlyalert"))) { 05331 if ((sscanf(val, "%30d", &earlyalert) != 1)) { 05332 ast_log(LOG_WARNING, "earlyalert must be a number, not '%s'\n", val); 05333 earlyalert = 0; 05334 } 05335 } 05336 if ((val = ast_variable_retrieve(cfg, "general", "endalert"))) { 05337 if ((sscanf(val, "%30d", &endalert) != 1)) { 05338 ast_log(LOG_WARNING, "endalert must be a number, not '%s'\n", val); 05339 endalert = 0; 05340 } 05341 } 05342 if ((val = ast_variable_retrieve(cfg, "general", "extendby"))) { 05343 if ((sscanf(val, "%30d", &extendby) != 1)) { 05344 ast_log(LOG_WARNING, "extendby must be a number, not '%s'\n", val); 05345 extendby = 0; 05346 } 05347 } 05348 05349 ast_config_destroy(cfg); 05350 }
| static int load_module | ( | void | ) | [static] |
Definition at line 7736 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().
07737 { 07738 int res = 0; 07739 07740 res |= load_config(0); 07741 07742 ast_cli_register_multiple(cli_meetme, ARRAY_LEN(cli_meetme)); 07743 res |= ast_manager_register_xml("MeetmeMute", EVENT_FLAG_CALL, action_meetmemute); 07744 res |= ast_manager_register_xml("MeetmeUnmute", EVENT_FLAG_CALL, action_meetmeunmute); 07745 res |= ast_manager_register_xml("MeetmeList", EVENT_FLAG_REPORTING, action_meetmelist); 07746 res |= ast_register_application_xml(app4, channel_admin_exec); 07747 res |= ast_register_application_xml(app3, admin_exec); 07748 res |= ast_register_application_xml(app2, count_exec); 07749 res |= ast_register_application_xml(app, conf_exec); 07750 res |= ast_register_application_xml(slastation_app, sla_station_exec); 07751 res |= ast_register_application_xml(slatrunk_app, sla_trunk_exec); 07752 07753 #ifdef TEST_FRAMEWORK 07754 AST_TEST_REGISTER(test_meetme_data_provider); 07755 #endif 07756 ast_data_register_multiple(meetme_data_providers, ARRAY_LEN(meetme_data_providers)); 07757 07758 res |= ast_devstate_prov_add("Meetme", meetmestate); 07759 res |= ast_devstate_prov_add("SLA", sla_state); 07760 07761 res |= ast_custom_function_register(&meetme_info_acf); 07762 ast_realtime_require_field("meetme", "confno", RQ_UINTEGER2, 3, "members", RQ_UINTEGER1, 3, NULL); 07763 07764 return res; 07765 }
| 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 7602 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.
07604 { 07605 struct ast_conference *cnf; 07606 struct ast_data *data_meetme, *data_meetme_users; 07607 07608 AST_LIST_LOCK(&confs); 07609 AST_LIST_TRAVERSE(&confs, cnf, list) { 07610 data_meetme = ast_data_add_node(data_root, "meetme"); 07611 if (!data_meetme) { 07612 continue; 07613 } 07614 07615 ast_data_add_structure(ast_conference, data_meetme, cnf); 07616 07617 if (ao2_container_count(cnf->usercontainer)) { 07618 data_meetme_users = ast_data_add_node(data_meetme, "users"); 07619 if (!data_meetme_users) { 07620 ast_data_remove_node(data_root, data_meetme); 07621 continue; 07622 } 07623 07624 ao2_callback(cnf->usercontainer, OBJ_NODATA, user_add_provider_cb, data_meetme_users); 07625 } 07626 07627 if (!ast_data_search_match(search, data_meetme)) { 07628 ast_data_remove_node(data_root, data_meetme); 07629 } 07630 } 07631 AST_LIST_UNLOCK(&confs); 07632 07633 return 0; 07634 }
| 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, | |||
| struct dahdi_confinfo * | dahdic | |||
| ) | [static] |
Definition at line 2734 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().
02735 { 02736 switch (*menu_mode) { 02737 case MENU_DISABLED: 02738 break; 02739 case MENU_NORMAL: 02740 meetme_menu_normal(menu_mode, dtmf, conf, confflags, chan, user); 02741 break; 02742 case MENU_ADMIN: 02743 meetme_menu_admin(menu_mode, dtmf, conf, confflags, chan, user); 02744 /* Admin Menu is capable of branching into another menu, in which case it will reset dtmf and change the menu mode. */ 02745 if (*menu_mode != MENU_ADMIN_EXTENDED || (*dtmf <= 0)) { 02746 break; 02747 } 02748 case MENU_ADMIN_EXTENDED: 02749 meetme_menu_admin_extended(menu_mode, dtmf, conf, confflags, chan, user, recordingtmp, recordingtmp_size, dahdic); 02750 break; 02751 } 02752 }
| 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, | |||
| struct dahdi_confinfo * | dahdic | |||
| ) | [static] |
Definition at line 2550 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().
02551 { 02552 int keepplaying; 02553 int playednamerec; 02554 int res; 02555 struct ao2_iterator user_iter; 02556 struct ast_conf_user *usr = NULL; 02557 02558 switch(*dtmf) { 02559 case '1': /* *81 Roll call */ 02560 keepplaying = 1; 02561 playednamerec = 0; 02562 if (conf->users == 1) { 02563 if (keepplaying && !ast_streamfile(chan, "conf-onlyperson", chan->language)) { 02564 res = ast_waitstream(chan, AST_DIGIT_ANY); 02565 ast_stopstream(chan); 02566 if (res > 0) { 02567 keepplaying = 0; 02568 } 02569 } 02570 } else if (conf->users == 2) { 02571 if (keepplaying && !ast_streamfile(chan, "conf-onlyone", chan->language)) { 02572 res = ast_waitstream(chan, AST_DIGIT_ANY); 02573 ast_stopstream(chan); 02574 if (res > 0) { 02575 keepplaying = 0; 02576 } 02577 } 02578 } else { 02579 if (keepplaying && !ast_streamfile(chan, "conf-thereare", chan->language)) { 02580 res = ast_waitstream(chan, AST_DIGIT_ANY); 02581 ast_stopstream(chan); 02582 if (res > 0) { 02583 keepplaying = 0; 02584 } 02585 } 02586 if (keepplaying) { 02587 res = ast_say_number(chan, conf->users - 1, AST_DIGIT_ANY, chan->language, (char *) NULL); 02588 ast_stopstream(chan); 02589 if (res > 0) { 02590 keepplaying = 0; 02591 } 02592 } 02593 if (keepplaying && !ast_streamfile(chan, "conf-otherinparty", chan->language)) { 02594 res = ast_waitstream(chan, AST_DIGIT_ANY); 02595 ast_stopstream(chan); 02596 if (res > 0) { 02597 keepplaying = 0; 02598 } 02599 } 02600 } 02601 user_iter = ao2_iterator_init(conf->usercontainer, 0); 02602 while((usr = ao2_iterator_next(&user_iter))) { 02603 if (ast_fileexists(usr->namerecloc, NULL, NULL)) { 02604 if (keepplaying && !ast_streamfile(chan, usr->namerecloc, chan->language)) { 02605 res = ast_waitstream(chan, AST_DIGIT_ANY); 02606 ast_stopstream(chan); 02607 if (res > 0) { 02608 keepplaying = 0; 02609 } 02610 } 02611 playednamerec = 1; 02612 } 02613 ao2_ref(usr, -1); 02614 } 02615 ao2_iterator_destroy(&user_iter); 02616 if (keepplaying && playednamerec && !ast_streamfile(chan, "conf-roll-callcomplete", chan->language)) { 02617 res = ast_waitstream(chan, AST_DIGIT_ANY); 02618 ast_stopstream(chan); 02619 if (res > 0) { 02620 keepplaying = 0; 02621 } 02622 } 02623 02624 *menu_mode = MENU_DISABLED; 02625 break; 02626 02627 case '2': /* *82 Eject all non-admins */ 02628 if (conf->users == 1) { 02629 if(!ast_streamfile(chan, "conf-errormenu", chan->language)) { 02630 ast_waitstream(chan, ""); 02631 } 02632 } else { 02633 ao2_callback(conf->usercontainer, OBJ_NODATA, user_set_kickme_cb, &conf); 02634 } 02635 ast_stopstream(chan); 02636 *menu_mode = MENU_DISABLED; 02637 break; 02638 02639 case '3': /* *83 (Admin) mute/unmute all non-admins */ 02640 if(conf->gmuted) { 02641 conf->gmuted = 0; 02642 ao2_callback(conf->usercontainer, OBJ_NODATA, user_set_unmuted_cb, &conf); 02643 if (!ast_streamfile(chan, "conf-now-unmuted", chan->language)) { 02644 ast_waitstream(chan, ""); 02645 } 02646 } else { 02647 conf->gmuted = 1; 02648 ao2_callback(conf->usercontainer, OBJ_NODATA, user_set_muted_cb, &conf); 02649 if (!ast_streamfile(chan, "conf-now-muted", chan->language)) { 02650 ast_waitstream(chan, ""); 02651 } 02652 } 02653 ast_stopstream(chan); 02654 *menu_mode = MENU_DISABLED; 02655 break; 02656 02657 case '4': /* *84 Record conference */ 02658 if (conf->recording != MEETME_RECORD_ACTIVE) { 02659 ast_set_flag64(confflags, CONFFLAG_RECORDCONF); 02660 if (!conf->recordingfilename) { 02661 const char *var; 02662 ast_channel_lock(chan); 02663 if ((var = pbx_builtin_getvar_helper(chan, "MEETME_RECORDINGFILE"))) { 02664 conf->recordingfilename = ast_strdup(var); 02665 } 02666 if ((var = pbx_builtin_getvar_helper(chan, "MEETME_RECORDINGFORMAT"))) { 02667 conf->recordingformat = ast_strdup(var); 02668 } 02669 ast_channel_unlock(chan); 02670 if (!conf->recordingfilename) { 02671 snprintf(recordingtmp, recordingtmp_size, "meetme-conf-rec-%s-%s", conf->confno, chan->uniqueid); 02672 conf->recordingfilename = ast_strdup(recordingtmp); 02673 } 02674 if (!conf->recordingformat) { 02675 conf->recordingformat = ast_strdup("wav"); 02676 } 02677 ast_verb(4, "Starting recording of MeetMe Conference %s into file %s.%s.\n", 02678 conf->confno, conf->recordingfilename, conf->recordingformat); 02679 } 02680 02681 ast_mutex_lock(&conf->recordthreadlock); 02682 if ((conf->recordthread == AST_PTHREADT_NULL) && ast_test_flag64(confflags, CONFFLAG_RECORDCONF) && ((conf->lchan = ast_request("DAHDI", AST_FORMAT_SLINEAR, chan, "pseudo", NULL)))) { 02683 ast_set_read_format(conf->lchan, AST_FORMAT_SLINEAR); 02684 ast_set_write_format(conf->lchan, AST_FORMAT_SLINEAR); 02685 dahdic->chan = 0; 02686 dahdic->confno = conf->dahdiconf; 02687 dahdic->confmode = DAHDI_CONF_CONFANN | DAHDI_CONF_CONFANNMON; 02688 if (ioctl(conf->lchan->fds[0], DAHDI_SETCONF, dahdic)) { 02689 ast_log(LOG_WARNING, "Error starting listen channel\n"); 02690 ast_hangup(conf->lchan); 02691 conf->lchan = NULL; 02692 } else { 02693 ast_pthread_create_detached_background(&conf->recordthread, NULL, recordthread, conf); 02694 } 02695 } 02696 ast_mutex_unlock(&conf->recordthreadlock); 02697 if (!ast_streamfile(chan, "conf-now-recording", chan->language)) { 02698 ast_waitstream(chan, ""); 02699 } 02700 } 02701 02702 ast_stopstream(chan); 02703 *menu_mode = MENU_DISABLED; 02704 break; 02705 02706 case '8': /* *88 Exit the menu and return to the conference... without an error message */ 02707 ast_stopstream(chan); 02708 *menu_mode = MENU_DISABLED; 02709 break; 02710 02711 default: 02712 if (!ast_streamfile(chan, "conf-errormenu", chan->language)) { 02713 ast_waitstream(chan, ""); 02714 } 02715 ast_stopstream(chan); 02716 *menu_mode = MENU_DISABLED; 02717 break; 02718 } 02719 }
| 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 5021 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().
05022 { 05023 struct ast_conference *conf; 05024 struct ast_conf_user *user; 05025 const char *confid = astman_get_header(m, "Meetme"); 05026 char *userid = ast_strdupa(astman_get_header(m, "Usernum")); 05027 int userno; 05028 05029 if (ast_strlen_zero(confid)) { 05030 astman_send_error(s, m, "Meetme conference not specified"); 05031 return 0; 05032 } 05033 05034 if (ast_strlen_zero(userid)) { 05035 astman_send_error(s, m, "Meetme user number not specified"); 05036 return 0; 05037 } 05038 05039 userno = strtoul(userid, &userid, 10); 05040 05041 if (*userid) { 05042 astman_send_error(s, m, "Invalid user number"); 05043 return 0; 05044 } 05045 05046 /* Look in the conference list */ 05047 AST_LIST_LOCK(&confs); 05048 AST_LIST_TRAVERSE(&confs, conf, list) { 05049 if (!strcmp(confid, conf->confno)) 05050 break; 05051 } 05052 05053 if (!conf) { 05054 AST_LIST_UNLOCK(&confs); 05055 astman_send_error(s, m, "Meetme conference does not exist"); 05056 return 0; 05057 } 05058 05059 user = ao2_find(conf->usercontainer, &userno, 0); 05060 05061 if (!user) { 05062 AST_LIST_UNLOCK(&confs); 05063 astman_send_error(s, m, "User number not found"); 05064 return 0; 05065 } 05066 05067 if (mute) 05068 user->adminflags |= ADMINFLAG_MUTED; /* request user muting */ 05069 else 05070 user->adminflags &= ~(ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED | ADMINFLAG_T_REQUEST); /* request user unmuting */ 05071 05072 AST_LIST_UNLOCK(&confs); 05073 05074 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); 05075 05076 ao2_ref(user, -1); 05077 astman_send_ack(s, m, mute ? "User muted" : "User unmuted"); 05078 return 0; 05079 }
| static enum ast_device_state meetmestate | ( | const char * | data | ) | [static] |
Callback for devicestate providers.
Definition at line 5260 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().
05261 { 05262 struct ast_conference *conf; 05263 05264 /* Find conference */ 05265 AST_LIST_LOCK(&confs); 05266 AST_LIST_TRAVERSE(&confs, conf, list) { 05267 if (!strcmp(data, conf->confno)) 05268 break; 05269 } 05270 AST_LIST_UNLOCK(&confs); 05271 if (!conf) 05272 return AST_DEVICE_INVALID; 05273 05274 05275 /* SKREP to fill */ 05276 if (!conf->users) 05277 return AST_DEVICE_NOT_INUSE; 05278 05279 return AST_DEVICE_INUSE; 05280 }
| static struct sla_ringing_trunk* queue_ringing_trunk | ( | struct sla_trunk * | trunk | ) | [static, read] |
Definition at line 6691 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().
06692 { 06693 struct sla_ringing_trunk *ringing_trunk; 06694 06695 if (!(ringing_trunk = ast_calloc(1, sizeof(*ringing_trunk)))) { 06696 return NULL; 06697 } 06698 06699 ao2_ref(trunk, 1); 06700 ringing_trunk->trunk = trunk; 06701 ringing_trunk->ring_begin = ast_tvnow(); 06702 06703 sla_change_trunk_state(trunk, SLA_TRUNK_STATE_RINGING, ALL_TRUNK_REFS, NULL); 06704 06705 ast_mutex_lock(&sla.lock); 06706 AST_LIST_INSERT_HEAD(&sla.ringing_trunks, ringing_trunk, entry); 06707 ast_mutex_unlock(&sla.lock); 06708 06709 sla_queue_event(SLA_EVENT_RINGING_TRUNK); 06710 06711 return ringing_trunk; 06712 }
| static void * recordthread | ( | void * | args | ) | [static] |
Definition at line 5191 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.
05192 { 05193 struct ast_conference *cnf = args; 05194 struct ast_frame *f = NULL; 05195 int flags; 05196 struct ast_filestream *s = NULL; 05197 int res = 0; 05198 int x; 05199 const char *oldrecordingfilename = NULL; 05200 char filename_buffer[PATH_MAX]; 05201 05202 if (!cnf || !cnf->lchan) { 05203 pthread_exit(0); 05204 } 05205 05206 filename_buffer[0] = '\0'; 05207 filename_parse(cnf->recordingfilename, filename_buffer); 05208 05209 ast_stopstream(cnf->lchan); 05210 flags = O_CREAT | O_TRUNC | O_WRONLY; 05211 05212 05213 cnf->recording = MEETME_RECORD_ACTIVE; 05214 while (ast_waitfor(cnf->lchan, -1) > -1) { 05215 if (cnf->recording == MEETME_RECORD_TERMINATE) { 05216 AST_LIST_LOCK(&confs); 05217 AST_LIST_UNLOCK(&confs); 05218 break; 05219 } 05220 if (!s && !(ast_strlen_zero(filename_buffer)) && (filename_buffer != oldrecordingfilename)) { 05221 s = ast_writefile(filename_buffer, cnf->recordingformat, NULL, flags, 0, AST_FILE_MODE); 05222 oldrecordingfilename = filename_buffer; 05223 } 05224 05225 f = ast_read(cnf->lchan); 05226 if (!f) { 05227 res = -1; 05228 break; 05229 } 05230 if (f->frametype == AST_FRAME_VOICE) { 05231 ast_mutex_lock(&cnf->listenlock); 05232 for (x = 0; x < AST_FRAME_BITS; x++) { 05233 /* Free any translations that have occured */ 05234 if (cnf->transframe[x]) { 05235 ast_frfree(cnf->transframe[x]); 05236 cnf->transframe[x] = NULL; 05237 } 05238 } 05239 if (cnf->origframe) 05240 ast_frfree(cnf->origframe); 05241 cnf->origframe = ast_frdup(f); 05242 ast_mutex_unlock(&cnf->listenlock); 05243 if (s) 05244 res = ast_writestream(s, f); 05245 if (res) { 05246 ast_frfree(f); 05247 break; 05248 } 05249 } 05250 ast_frfree(f); 05251 } 05252 cnf->recording = MEETME_RECORD_OFF; 05253 if (s) 05254 ast_closestream(s); 05255 05256 pthread_exit(0); 05257 }
| static int reload | ( | void | ) | [static] |
Definition at line 7767 of file app_meetme.c.
References ast_unload_realtime(), and load_config().
07768 { 07769 ast_unload_realtime("meetme"); 07770 return load_config(1); 07771 }
| 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 5577 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().
05578 { 05579 RAII_VAR(struct sla_station *, station, NULL, unref_obj); 05580 RAII_VAR(struct sla_trunk_ref *, trunk_ref, NULL, unref_obj); 05581 struct ast_str *conf_name = ast_str_create(16); 05582 struct ast_flags64 conf_flags = { 0 }; 05583 struct ast_conference *conf; 05584 05585 { 05586 struct run_station_args *args = data; 05587 station = args->station; 05588 trunk_ref = args->trunk_ref; 05589 ast_mutex_lock(args->cond_lock); 05590 ast_cond_signal(args->cond); 05591 ast_mutex_unlock(args->cond_lock); 05592 /* args is no longer valid here. */ 05593 } 05594 05595 ast_atomic_fetchadd_int((int *) &trunk_ref->trunk->active_stations, 1); 05596 ast_str_set(&conf_name, 0, "SLA_%s", trunk_ref->trunk->name); 05597 ast_set_flag64(&conf_flags, 05598 CONFFLAG_QUIET | CONFFLAG_MARKEDEXIT | CONFFLAG_PASS_DTMF | CONFFLAG_SLA_STATION); 05599 answer_trunk_chan(trunk_ref->chan); 05600 conf = build_conf(ast_str_buffer(conf_name), "", "", 0, 0, 1, trunk_ref->chan, NULL); 05601 if (conf) { 05602 conf_run(trunk_ref->chan, conf, &conf_flags, NULL); 05603 dispose_conf(conf); 05604 conf = NULL; 05605 } 05606 trunk_ref->chan = NULL; 05607 if (ast_atomic_dec_and_test((int *) &trunk_ref->trunk->active_stations) && 05608 trunk_ref->state != SLA_TRUNK_STATE_ONHOLD_BYME) { 05609 ast_str_append(&conf_name, 0, ",K"); 05610 admin_exec(NULL, ast_str_buffer(conf_name)); 05611 trunk_ref->trunk->hold_stations = 0; 05612 sla_change_trunk_state(trunk_ref->trunk, SLA_TRUNK_STATE_IDLE, ALL_TRUNK_REFS, NULL); 05613 } 05614 05615 ast_dial_join(station->dial); 05616 ast_dial_destroy(station->dial); 05617 station->dial = NULL; 05618 ast_free(conf_name); 05619 05620 return NULL; 05621 }
| 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 7086 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().
07087 { 07088 RAII_VAR(struct sla_trunk *, trunk, NULL, unref_obj); 07089 struct sla_trunk_ref *trunk_ref = NULL; 07090 struct sla_station_ref *station_ref; 07091 char *trunk_name, *options, *cur; 07092 int existing_trunk_ref = 0; 07093 int existing_station_ref = 0; 07094 07095 options = ast_strdupa(var->value); 07096 trunk_name = strsep(&options, ","); 07097 07098 trunk = sla_find_trunk(trunk_name); 07099 if (!trunk) { 07100 ast_log(LOG_ERROR, "Trunk '%s' not found!\n", var->value); 07101 return; 07102 } 07103 07104 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) { 07105 if (trunk_ref->trunk == trunk) { 07106 trunk_ref->mark = 0; 07107 existing_trunk_ref = 1; 07108 break; 07109 } 07110 } 07111 07112 if (!trunk_ref && !(trunk_ref = create_trunk_ref(trunk))) { 07113 return; 07114 } 07115 07116 trunk_ref->state = SLA_TRUNK_STATE_IDLE; 07117 07118 while ((cur = strsep(&options, ","))) { 07119 char *name, *value = cur; 07120 name = strsep(&value, "="); 07121 if (!strcasecmp(name, "ringtimeout")) { 07122 if (sscanf(value, "%30u", &trunk_ref->ring_timeout) != 1) { 07123 ast_log(LOG_WARNING, "Invalid ringtimeout value '%s' for " 07124 "trunk '%s' on station '%s'\n", value, trunk->name, station->name); 07125 trunk_ref->ring_timeout = 0; 07126 } 07127 } else if (!strcasecmp(name, "ringdelay")) { 07128 if (sscanf(value, "%30u", &trunk_ref->ring_delay) != 1) { 07129 ast_log(LOG_WARNING, "Invalid ringdelay value '%s' for " 07130 "trunk '%s' on station '%s'\n", value, trunk->name, station->name); 07131 trunk_ref->ring_delay = 0; 07132 } 07133 } else { 07134 ast_log(LOG_WARNING, "Invalid option '%s' for " 07135 "trunk '%s' on station '%s'\n", name, trunk->name, station->name); 07136 } 07137 } 07138 07139 AST_LIST_TRAVERSE(&trunk->stations, station_ref, entry) { 07140 if (station_ref->station == station) { 07141 station_ref->mark = 0; 07142 existing_station_ref = 1; 07143 break; 07144 } 07145 } 07146 07147 if (!station_ref && !(station_ref = sla_create_station_ref(station))) { 07148 if (!existing_trunk_ref) { 07149 ao2_ref(trunk_ref, -1); 07150 } else { 07151 trunk_ref->mark = 1; 07152 } 07153 return; 07154 } 07155 07156 if (!existing_station_ref) { 07157 ao2_lock(trunk); 07158 AST_LIST_INSERT_TAIL(&trunk->stations, station_ref, entry); 07159 ast_atomic_fetchadd_int((int *) &trunk->num_stations, 1); 07160 ao2_unlock(trunk); 07161 } 07162 07163 if (!existing_trunk_ref) { 07164 ao2_lock(station); 07165 AST_LIST_INSERT_TAIL(&station->trunks, trunk_ref, entry); 07166 ao2_unlock(station); 07167 } 07168 }
| static int sla_build_station | ( | struct ast_config * | cfg, | |
| const char * | cat | |||
| ) | [static] |
Definition at line 7170 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().
07171 { 07172 RAII_VAR(struct sla_station *, station, NULL, unref_obj); 07173 struct ast_variable *var; 07174 const char *dev; 07175 int existing_station = 0; 07176 07177 if (!(dev = ast_variable_retrieve(cfg, cat, "device"))) { 07178 ast_log(LOG_ERROR, "SLA Station '%s' defined with no device!\n", cat); 07179 return -1; 07180 } 07181 07182 if ((station = sla_find_station(cat))) { 07183 station->mark = 0; 07184 existing_station = 1; 07185 } else if ((station = ao2_alloc(sizeof(*station), sla_station_destructor))) { 07186 if (ast_string_field_init(station, 32)) { 07187 return -1; 07188 } 07189 ast_string_field_set(station, name, cat); 07190 } else { 07191 return -1; 07192 } 07193 07194 ao2_lock(station); 07195 07196 ast_string_field_set(station, device, dev); 07197 07198 for (var = ast_variable_browse(cfg, cat); var; var = var->next) { 07199 if (!strcasecmp(var->name, "trunk")) { 07200 ao2_unlock(station); 07201 sla_add_trunk_to_station(station, var); 07202 ao2_lock(station); 07203 } else if (!strcasecmp(var->name, "autocontext")) { 07204 ast_string_field_set(station, autocontext, var->value); 07205 } else if (!strcasecmp(var->name, "ringtimeout")) { 07206 if (sscanf(var->value, "%30u", &station->ring_timeout) != 1) { 07207 ast_log(LOG_WARNING, "Invalid ringtimeout '%s' specified for station '%s'\n", 07208 var->value, station->name); 07209 station->ring_timeout = 0; 07210 } 07211 } else if (!strcasecmp(var->name, "ringdelay")) { 07212 if (sscanf(var->value, "%30u", &station->ring_delay) != 1) { 07213 ast_log(LOG_WARNING, "Invalid ringdelay '%s' specified for station '%s'\n", 07214 var->value, station->name); 07215 station->ring_delay = 0; 07216 } 07217 } else if (!strcasecmp(var->name, "hold")) { 07218 if (!strcasecmp(var->value, "private")) 07219 station->hold_access = SLA_HOLD_PRIVATE; 07220 else if (!strcasecmp(var->value, "open")) 07221 station->hold_access = SLA_HOLD_OPEN; 07222 else { 07223 ast_log(LOG_WARNING, "Invalid value '%s' for hold on station %s\n", 07224 var->value, station->name); 07225 } 07226 07227 } else if (strcasecmp(var->name, "type") && strcasecmp(var->name, "device")) { 07228 ast_log(LOG_ERROR, "Invalid option '%s' specified at line %d of %s!\n", 07229 var->name, var->lineno, SLA_CONFIG_FILE); 07230 } 07231 } 07232 07233 ao2_unlock(station); 07234 07235 if (!ast_strlen_zero(station->autocontext)) { 07236 struct ast_context *context; 07237 struct sla_trunk_ref *trunk_ref; 07238 context = ast_context_find_or_create(NULL, NULL, station->autocontext, sla_registrar); 07239 if (!context) { 07240 ast_log(LOG_ERROR, "Failed to automatically find or create " 07241 "context '%s' for SLA!\n", station->autocontext); 07242 return -1; 07243 } 07244 /* The extension for when the handset goes off-hook. 07245 * exten => station1,1,SLAStation(station1) */ 07246 if (ast_add_extension2(context, 0 /* don't replace */, station->name, 1, 07247 NULL, NULL, slastation_app, ast_strdup(station->name), ast_free_ptr, sla_registrar)) { 07248 ast_log(LOG_ERROR, "Failed to automatically create extension " 07249 "for trunk '%s'!\n", station->name); 07250 return -1; 07251 } 07252 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) { 07253 char exten[AST_MAX_EXTENSION]; 07254 char hint[AST_MAX_APP]; 07255 snprintf(exten, sizeof(exten), "%s_%s", station->name, trunk_ref->trunk->name); 07256 snprintf(hint, sizeof(hint), "SLA:%s", exten); 07257 /* Extension for this line button 07258 * exten => station1_line1,1,SLAStation(station1_line1) */ 07259 if (ast_add_extension2(context, 0 /* don't replace */, exten, 1, 07260 NULL, NULL, slastation_app, ast_strdup(exten), ast_free_ptr, sla_registrar)) { 07261 ast_log(LOG_ERROR, "Failed to automatically create extension " 07262 "for trunk '%s'!\n", station->name); 07263 return -1; 07264 } 07265 /* Hint for this line button 07266 * exten => station1_line1,hint,SLA:station1_line1 */ 07267 if (ast_add_extension2(context, 0 /* don't replace */, exten, PRIORITY_HINT, 07268 NULL, NULL, hint, NULL, NULL, sla_registrar)) { 07269 ast_log(LOG_ERROR, "Failed to automatically create hint " 07270 "for trunk '%s'!\n", station->name); 07271 return -1; 07272 } 07273 } 07274 } 07275 07276 if (!existing_station) { 07277 ao2_link(sla_stations, station); 07278 } 07279 07280 return 0; 07281 }
| static int sla_build_trunk | ( | struct ast_config * | cfg, | |
| const char * | cat | |||
| ) | [static] |
Definition at line 6997 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().
06998 { 06999 RAII_VAR(struct sla_trunk *, trunk, NULL, unref_obj); 07000 struct ast_variable *var; 07001 const char *dev; 07002 int existing_trunk = 0; 07003 07004 if (!(dev = ast_variable_retrieve(cfg, cat, "device"))) { 07005 ast_log(LOG_ERROR, "SLA Trunk '%s' defined with no device!\n", cat); 07006 return -1; 07007 } 07008 07009 if (sla_check_device(dev)) { 07010 ast_log(LOG_ERROR, "SLA Trunk '%s' defined with invalid device '%s'!\n", 07011 cat, dev); 07012 return -1; 07013 } 07014 07015 if ((trunk = sla_find_trunk(cat))) { 07016 trunk->mark = 0; 07017 existing_trunk = 1; 07018 } else if ((trunk = ao2_alloc(sizeof(*trunk), sla_trunk_destructor))) { 07019 if (ast_string_field_init(trunk, 32)) { 07020 return -1; 07021 } 07022 ast_string_field_set(trunk, name, cat); 07023 } else { 07024 return -1; 07025 } 07026 07027 ao2_lock(trunk); 07028 07029 ast_string_field_set(trunk, device, dev); 07030 07031 for (var = ast_variable_browse(cfg, cat); var; var = var->next) { 07032 if (!strcasecmp(var->name, "autocontext")) 07033 ast_string_field_set(trunk, autocontext, var->value); 07034 else if (!strcasecmp(var->name, "ringtimeout")) { 07035 if (sscanf(var->value, "%30u", &trunk->ring_timeout) != 1) { 07036 ast_log(LOG_WARNING, "Invalid ringtimeout '%s' specified for trunk '%s'\n", 07037 var->value, trunk->name); 07038 trunk->ring_timeout = 0; 07039 } 07040 } else if (!strcasecmp(var->name, "barge")) 07041 trunk->barge_disabled = ast_false(var->value); 07042 else if (!strcasecmp(var->name, "hold")) { 07043 if (!strcasecmp(var->value, "private")) 07044 trunk->hold_access = SLA_HOLD_PRIVATE; 07045 else if (!strcasecmp(var->value, "open")) 07046 trunk->hold_access = SLA_HOLD_OPEN; 07047 else { 07048 ast_log(LOG_WARNING, "Invalid value '%s' for hold on trunk %s\n", 07049 var->value, trunk->name); 07050 } 07051 } else if (strcasecmp(var->name, "type") && strcasecmp(var->name, "device")) { 07052 ast_log(LOG_ERROR, "Invalid option '%s' specified at line %d of %s!\n", 07053 var->name, var->lineno, SLA_CONFIG_FILE); 07054 } 07055 } 07056 07057 ao2_unlock(trunk); 07058 07059 if (!ast_strlen_zero(trunk->autocontext)) { 07060 struct ast_context *context; 07061 context = ast_context_find_or_create(NULL, NULL, trunk->autocontext, sla_registrar); 07062 if (!context) { 07063 ast_log(LOG_ERROR, "Failed to automatically find or create " 07064 "context '%s' for SLA!\n", trunk->autocontext); 07065 return -1; 07066 } 07067 if (ast_add_extension2(context, 0 /* don't replace */, "s", 1, 07068 NULL, NULL, slatrunk_app, ast_strdup(trunk->name), ast_free_ptr, sla_registrar)) { 07069 ast_log(LOG_ERROR, "Failed to automatically create extension " 07070 "for trunk '%s'!\n", trunk->name); 07071 return -1; 07072 } 07073 } 07074 07075 if (!existing_trunk) { 07076 ao2_link(sla_trunks, trunk); 07077 } 07078 07079 return 0; 07080 }
| static int sla_calc_station_delays | ( | unsigned int * | timeout | ) | [static] |
Calculate the ring delay for a station.
Definition at line 6205 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().
06206 { 06207 struct sla_station *station; 06208 int res = 0; 06209 struct ao2_iterator i; 06210 06211 i = ao2_iterator_init(sla_stations, 0); 06212 for (; (station = ao2_iterator_next(&i)); ao2_ref(station, -1)) { 06213 struct sla_ringing_trunk *ringing_trunk; 06214 int time_left; 06215 06216 /* Ignore stations already ringing */ 06217 if (sla_check_ringing_station(station)) 06218 continue; 06219 06220 /* Ignore stations already on a call */ 06221 if (sla_check_inuse_station(station)) 06222 continue; 06223 06224 /* Ignore stations that don't have one of their trunks ringing */ 06225 if (!(ringing_trunk = sla_choose_ringing_trunk(station, NULL, 0))) 06226 continue; 06227 06228 if ((time_left = sla_check_station_delay(station, ringing_trunk)) == INT_MAX) 06229 continue; 06230 06231 /* If there is no time left, then the station needs to start ringing. 06232 * Return non-zero so that an event will be queued up an event to 06233 * make that happen. */ 06234 if (time_left <= 0) { 06235 res = 1; 06236 continue; 06237 } 06238 06239 if (time_left < *timeout) 06240 *timeout = time_left; 06241 } 06242 ao2_iterator_destroy(&i); 06243 06244 return res; 06245 }
| static int sla_calc_station_timeouts | ( | unsigned int * | timeout | ) | [static] |
Process station ring timeouts.
Definition at line 6122 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().
06123 { 06124 struct sla_ringing_trunk *ringing_trunk; 06125 struct sla_ringing_station *ringing_station; 06126 int res = 0; 06127 06128 AST_LIST_TRAVERSE_SAFE_BEGIN(&sla.ringing_stations, ringing_station, entry) { 06129 unsigned int ring_timeout = 0; 06130 int time_elapsed, time_left = INT_MAX, final_trunk_time_left = INT_MIN; 06131 struct sla_trunk_ref *trunk_ref; 06132 06133 /* If there are any ring timeouts specified for a specific trunk 06134 * on the station, then use the highest per-trunk ring timeout. 06135 * Otherwise, use the ring timeout set for the entire station. */ 06136 AST_LIST_TRAVERSE(&ringing_station->station->trunks, trunk_ref, entry) { 06137 struct sla_station_ref *station_ref; 06138 int trunk_time_elapsed, trunk_time_left; 06139 06140 AST_LIST_TRAVERSE(&sla.ringing_trunks, ringing_trunk, entry) { 06141 if (ringing_trunk->trunk == trunk_ref->trunk) 06142 break; 06143 } 06144 if (!ringing_trunk) 06145 continue; 06146 06147 /* If there is a trunk that is ringing without a timeout, then the 06148 * only timeout that could matter is a global station ring timeout. */ 06149 if (!trunk_ref->ring_timeout) 06150 break; 06151 06152 /* This trunk on this station is ringing and has a timeout. 06153 * However, make sure this trunk isn't still ringing from a 06154 * previous timeout. If so, don't consider it. */ 06155 AST_LIST_TRAVERSE(&ringing_trunk->timed_out_stations, station_ref, entry) { 06156 if (station_ref->station == ringing_station->station) 06157 break; 06158 } 06159 if (station_ref) 06160 continue; 06161 06162 trunk_time_elapsed = ast_tvdiff_ms(ast_tvnow(), ringing_trunk->ring_begin); 06163 trunk_time_left = (trunk_ref->ring_timeout * 1000) - trunk_time_elapsed; 06164 if (trunk_time_left > final_trunk_time_left) 06165 final_trunk_time_left = trunk_time_left; 06166 } 06167 06168 /* No timeout was found for ringing trunks, and no timeout for the entire station */ 06169 if (final_trunk_time_left == INT_MIN && !ringing_station->station->ring_timeout) 06170 continue; 06171 06172 /* Compute how much time is left for a global station timeout */ 06173 if (ringing_station->station->ring_timeout) { 06174 ring_timeout = ringing_station->station->ring_timeout; 06175 time_elapsed = ast_tvdiff_ms(ast_tvnow(), ringing_station->ring_begin); 06176 time_left = (ring_timeout * 1000) - time_elapsed; 06177 } 06178 06179 /* If the time left based on the per-trunk timeouts is smaller than the 06180 * global station ring timeout, use that. */ 06181 if (final_trunk_time_left > INT_MIN && final_trunk_time_left < time_left) 06182 time_left = final_trunk_time_left; 06183 06184 /* If there is no time left, the station needs to stop ringing */ 06185 if (time_left <= 0) { 06186 AST_LIST_REMOVE_CURRENT(entry); 06187 sla_stop_ringing_station(ringing_station, SLA_STATION_HANGUP_TIMEOUT); 06188 res = 1; 06189 continue; 06190 } 06191 06192 /* There is still some time left for this station to ring, so save that 06193 * timeout if it is the first event scheduled to occur */ 06194 if (time_left < *timeout) 06195 *timeout = time_left; 06196 } 06197 AST_LIST_TRAVERSE_SAFE_END; 06198 06199 return res; 06200 }
| static int sla_calc_trunk_timeouts | ( | unsigned int * | timeout | ) | [static] |
Process trunk ring timeouts.
Definition at line 6092 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().
06093 { 06094 struct sla_ringing_trunk *ringing_trunk; 06095 int res = 0; 06096 06097 AST_LIST_TRAVERSE_SAFE_BEGIN(&sla.ringing_trunks, ringing_trunk, entry) { 06098 int time_left, time_elapsed; 06099 if (!ringing_trunk->trunk->ring_timeout) 06100 continue; 06101 time_elapsed = ast_tvdiff_ms(ast_tvnow(), ringing_trunk->ring_begin); 06102 time_left = (ringing_trunk->trunk->ring_timeout * 1000) - time_elapsed; 06103 if (time_left <= 0) { 06104 pbx_builtin_setvar_helper(ringing_trunk->trunk->chan, "SLATRUNK_STATUS", "RINGTIMEOUT"); 06105 AST_LIST_REMOVE_CURRENT(entry); 06106 sla_stop_ringing_trunk(ringing_trunk); 06107 res = 1; 06108 continue; 06109 } 06110 if (time_left < *timeout) 06111 *timeout = time_left; 06112 } 06113 AST_LIST_TRAVERSE_SAFE_END; 06114 06115 return res; 06116 }
| 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 5538 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().
05540 { 05541 struct sla_station *station; 05542 struct sla_trunk_ref *trunk_ref; 05543 struct ao2_iterator i; 05544 05545 i = ao2_iterator_init(sla_stations, 0); 05546 while ((station = ao2_iterator_next(&i))) { 05547 ao2_lock(station); 05548 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) { 05549 if (trunk_ref->trunk != trunk || (inactive_only ? trunk_ref->chan : 0) 05550 || trunk_ref == exclude) { 05551 continue; 05552 } 05553 trunk_ref->state = state; 05554 ast_devstate_changed(sla_state_to_devstate(state), AST_DEVSTATE_CACHABLE, 05555 "SLA:%s_%s", station->name, trunk->name); 05556 break; 05557 } 05558 ao2_unlock(station); 05559 ao2_ref(station, -1); 05560 } 05561 ao2_iterator_destroy(&i); 05562 }
| static int sla_check_device | ( | const char * | device | ) | [static] |
Definition at line 6969 of file app_meetme.c.
References ast_strdupa, and ast_strlen_zero().
Referenced by sla_build_trunk().
06970 { 06971 char *tech, *tech_data; 06972 06973 tech_data = ast_strdupa(device); 06974 tech = strsep(&tech_data, "/"); 06975 06976 if (ast_strlen_zero(tech) || ast_strlen_zero(tech_data)) 06977 return -1; 06978 06979 return 0; 06980 }
| 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 5841 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().
05842 { 05843 struct sla_failed_station *failed_station; 05844 int res = 0; 05845 05846 AST_LIST_TRAVERSE_SAFE_BEGIN(&sla.failed_stations, failed_station, entry) { 05847 if (station != failed_station->station) 05848 continue; 05849 if (ast_tvdiff_ms(ast_tvnow(), failed_station->last_try) > 1000) { 05850 AST_LIST_REMOVE_CURRENT(entry); 05851 sla_failed_station_destroy(failed_station); 05852 break; 05853 } 05854 res = 1; 05855 } 05856 AST_LIST_TRAVERSE_SAFE_END 05857 05858 return res; 05859 }
| static int sla_check_inuse_station | ( | const struct sla_station * | station | ) | [static] |
Check to see if a station is in use.
Definition at line 5924 of file app_meetme.c.
References AST_LIST_TRAVERSE.
Referenced by sla_calc_station_delays(), and sla_ring_stations().
05925 { 05926 struct sla_trunk_ref *trunk_ref; 05927 05928 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) { 05929 if (trunk_ref->chan) 05930 return 1; 05931 } 05932 05933 return 0; 05934 }
| static int sla_check_ringing_station | ( | const struct sla_station * | station | ) | [static] |
Check to see if this station is already ringing.
Definition at line 5826 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().
05827 { 05828 struct sla_ringing_station *ringing_station; 05829 05830 AST_LIST_TRAVERSE(&sla.ringing_stations, ringing_station, entry) { 05831 if (station == ringing_station->station) 05832 return 1; 05833 } 05834 05835 return 0; 05836 }
| 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 5956 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().
05958 { 05959 RAII_VAR(struct sla_trunk_ref *, trunk_ref, NULL, unref_obj); 05960 unsigned int delay = UINT_MAX; 05961 int time_left, time_elapsed; 05962 05963 if (!ringing_trunk) 05964 ringing_trunk = sla_choose_ringing_trunk(station, &trunk_ref, 0); 05965 else 05966 trunk_ref = sla_find_trunk_ref(station, ringing_trunk->trunk); 05967 05968 if (!ringing_trunk || !trunk_ref) 05969 return delay; 05970 05971 /* If this station has a ring delay specific to the highest priority 05972 * ringing trunk, use that. Otherwise, use the ring delay specified 05973 * globally for the station. */ 05974 delay = trunk_ref->ring_delay; 05975 if (!delay) 05976 delay = station->ring_delay; 05977 if (!delay) 05978 return INT_MAX; 05979 05980 time_elapsed = ast_tvdiff_ms(ast_tvnow(), ringing_trunk->ring_begin); 05981 time_left = (delay * 1000) - time_elapsed; 05982 05983 return time_left; 05984 }
| static int sla_check_station_hold_access | ( | const struct sla_trunk * | trunk, | |
| const struct sla_station * | station | |||
| ) | [static] |
Definition at line 5389 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().
05391 { 05392 struct sla_station_ref *station_ref; 05393 struct sla_trunk_ref *trunk_ref; 05394 05395 /* For each station that has this call on hold, check for private hold. */ 05396 AST_LIST_TRAVERSE(&trunk->stations, station_ref, entry) { 05397 AST_LIST_TRAVERSE(&station_ref->station->trunks, trunk_ref, entry) { 05398 if (trunk_ref->trunk != trunk || station_ref->station == station) 05399 continue; 05400 if (trunk_ref->state == SLA_TRUNK_STATE_ONHOLD_BYME && 05401 station_ref->station->hold_access == SLA_HOLD_PRIVATE) 05402 return 1; 05403 return 0; 05404 } 05405 } 05406 05407 return 0; 05408 }
| 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 5684 of file app_meetme.c.
References AST_LIST_TRAVERSE.
Referenced by sla_choose_ringing_trunk(), and sla_ring_stations().
05686 { 05687 struct sla_station_ref *timed_out_station; 05688 05689 AST_LIST_TRAVERSE(&ringing_trunk->timed_out_stations, timed_out_station, entry) { 05690 if (station == timed_out_station->station) 05691 return 1; 05692 } 05693 05694 return 0; 05695 }
| 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 6501 of file app_meetme.c.
References ao2_ref, AST_LIST_TRAVERSE, and SLA_TRUNK_STATE_IDLE.
Referenced by sla_station_exec().
06502 { 06503 struct sla_trunk_ref *trunk_ref = NULL; 06504 06505 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) { 06506 if (trunk_ref->state == SLA_TRUNK_STATE_IDLE) { 06507 ao2_ref(trunk_ref, 1); 06508 break; 06509 } 06510 } 06511 06512 return trunk_ref; 06513 }
| 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 5705 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().
05707 { 05708 struct sla_trunk_ref *s_trunk_ref; 05709 struct sla_ringing_trunk *ringing_trunk = NULL; 05710 05711 AST_LIST_TRAVERSE(&station->trunks, s_trunk_ref, entry) { 05712 AST_LIST_TRAVERSE_SAFE_BEGIN(&sla.ringing_trunks, ringing_trunk, entry) { 05713 /* Make sure this is the trunk we're looking for */ 05714 if (s_trunk_ref->trunk != ringing_trunk->trunk) 05715 continue; 05716 05717 /* This trunk on the station is ringing. But, make sure this station 05718 * didn't already time out while this trunk was ringing. */ 05719 if (sla_check_timed_out_station(ringing_trunk, station)) 05720 continue; 05721 05722 if (rm) 05723 AST_LIST_REMOVE_CURRENT(entry); 05724 05725 if (trunk_ref) { 05726 ao2_ref(s_trunk_ref, 1); 05727 *trunk_ref = s_trunk_ref; 05728 } 05729 05730 break; 05731 } 05732 AST_LIST_TRAVERSE_SAFE_END; 05733 05734 if (ringing_trunk) 05735 break; 05736 } 05737 05738 return ringing_trunk; 05739 }
| static struct sla_failed_station* sla_create_failed_station | ( | struct sla_station * | station | ) | [static, read] |
Definition at line 5496 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().
05497 { 05498 struct sla_failed_station *failed_station; 05499 05500 if (!(failed_station = ast_calloc(1, sizeof(*failed_station)))) { 05501 return NULL; 05502 } 05503 05504 ao2_ref(station, 1); 05505 failed_station->station = station; 05506 failed_station->last_try = ast_tvnow(); 05507 05508 return failed_station; 05509 }
| static struct sla_ringing_station* sla_create_ringing_station | ( | struct sla_station * | station | ) | [static, read] |
Definition at line 5472 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().
05473 { 05474 struct sla_ringing_station *ringing_station; 05475 05476 if (!(ringing_station = ast_calloc(1, sizeof(*ringing_station)))) 05477 return NULL; 05478 05479 ao2_ref(station, 1); 05480 ringing_station->station = station; 05481 ringing_station->ring_begin = ast_tvnow(); 05482 05483 return ringing_station; 05484 }
| static struct sla_station_ref* sla_create_station_ref | ( | struct sla_station * | station | ) | [static, read] |
Definition at line 5458 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().
05459 { 05460 struct sla_station_ref *station_ref; 05461 05462 if (!(station_ref = ao2_alloc(sizeof(*station_ref), sla_station_ref_destructor))) { 05463 return NULL; 05464 } 05465 05466 ao2_ref(station, 1); 05467 station_ref->station = station; 05468 05469 return station_ref; 05470 }
| static void sla_destroy | ( | void | ) | [static] |
Definition at line 6943 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().
06944 { 06945 if (sla.thread != AST_PTHREADT_NULL) { 06946 ast_mutex_lock(&sla.lock); 06947 sla.stop = 1; 06948 ast_cond_signal(&sla.cond); 06949 ast_mutex_unlock(&sla.lock); 06950 pthread_join(sla.thread, NULL); 06951 } 06952 06953 /* Drop any created contexts from the dialplan */ 06954 ast_context_destroy(NULL, sla_registrar); 06955 06956 ast_mutex_destroy(&sla.lock); 06957 ast_cond_destroy(&sla.cond); 06958 06959 ao2_callback(sla_trunks, 0, sla_trunk_release_refs, NULL); 06960 ao2_callback(sla_stations, 0, sla_station_release_refs, NULL); 06961 06962 ao2_ref(sla_trunks, -1); 06963 sla_trunks = NULL; 06964 06965 ao2_ref(sla_stations, -1); 06966 sla_stations = NULL; 06967 }
| static void sla_dial_state_callback | ( | struct ast_dial * | dial | ) | [static] |
Definition at line 5676 of file app_meetme.c.
References SLA_EVENT_DIAL_STATE, and sla_queue_event().
Referenced by sla_ring_station().
05677 { 05678 sla_queue_event(SLA_EVENT_DIAL_STATE); 05679 }
| static void sla_event_destroy | ( | struct sla_event * | event | ) | [static] |
Definition at line 6284 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 5511 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 5380 of file app_meetme.c.
References ao2_find, OBJ_POINTER, and sla_stations.
Referenced by sla_build_station(), sla_state(), and sla_station_exec().
05381 { 05382 struct sla_station tmp_station = { 05383 .name = name, 05384 }; 05385 05386 return ao2_find(sla_stations, &tmp_station, OBJ_POINTER); 05387 }
| static struct sla_trunk* sla_find_trunk | ( | const char * | name | ) | [static, read] |
Definition at line 5367 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().
05368 { 05369 struct sla_trunk tmp_trunk = { 05370 .name = name, 05371 }; 05372 05373 return ao2_find(sla_trunks, &tmp_trunk, OBJ_POINTER); 05374 }
| static struct sla_trunk_ref* sla_find_trunk_ref | ( | const struct sla_station * | station, | |
| const struct sla_trunk * | trunk | |||
| ) | [static, read] |
Definition at line 5936 of file app_meetme.c.
References ao2_ref, and AST_LIST_TRAVERSE.
Referenced by sla_check_station_delay().
05938 { 05939 struct sla_trunk_ref *trunk_ref = NULL; 05940 05941 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) { 05942 if (trunk_ref->trunk == trunk) 05943 break; 05944 } 05945 05946 ao2_ref(trunk_ref, 1); 05947 05948 return trunk_ref; 05949 }
| 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 5419 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().
05421 { 05422 struct sla_trunk_ref *trunk_ref = NULL; 05423 05424 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) { 05425 if (strcasecmp(trunk_ref->trunk->name, name)) 05426 continue; 05427 05428 if ( (trunk_ref->trunk->barge_disabled 05429 && trunk_ref->state == SLA_TRUNK_STATE_UP) || 05430 (trunk_ref->trunk->hold_stations 05431 && trunk_ref->trunk->hold_access == SLA_HOLD_PRIVATE 05432 && trunk_ref->state != SLA_TRUNK_STATE_ONHOLD_BYME) || 05433 sla_check_station_hold_access(trunk_ref->trunk, station) ) 05434 { 05435 trunk_ref = NULL; 05436 } 05437 05438 break; 05439 } 05440 05441 if (trunk_ref) { 05442 ao2_ref(trunk_ref, 1); 05443 } 05444 05445 return trunk_ref; 05446 }
| static void sla_handle_dial_state_event | ( | void | ) | [static] |
Definition at line 5741 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().
05742 { 05743 struct sla_ringing_station *ringing_station; 05744 05745 AST_LIST_TRAVERSE_SAFE_BEGIN(&sla.ringing_stations, ringing_station, entry) { 05746 RAII_VAR(struct sla_trunk_ref *, s_trunk_ref, NULL, unref_obj); 05747 struct sla_ringing_trunk *ringing_trunk = NULL; 05748 struct run_station_args args; 05749 enum ast_dial_result dial_res; 05750 pthread_t dont_care; 05751 ast_mutex_t cond_lock; 05752 ast_cond_t cond; 05753 05754 switch ((dial_res = ast_dial_state(ringing_station->station->dial))) { 05755 case AST_DIAL_RESULT_HANGUP: 05756 case AST_DIAL_RESULT_INVALID: 05757 case AST_DIAL_RESULT_FAILED: 05758 case AST_DIAL_RESULT_TIMEOUT: 05759 case AST_DIAL_RESULT_UNANSWERED: 05760 AST_LIST_REMOVE_CURRENT(entry); 05761 sla_stop_ringing_station(ringing_station, SLA_STATION_HANGUP_NORMAL); 05762 break; 05763 case AST_DIAL_RESULT_ANSWERED: 05764 AST_LIST_REMOVE_CURRENT(entry); 05765 /* Find the appropriate trunk to answer. */ 05766 ast_mutex_lock(&sla.lock); 05767 ringing_trunk = sla_choose_ringing_trunk(ringing_station->station, &s_trunk_ref, 1); 05768 ast_mutex_unlock(&sla.lock); 05769 if (!ringing_trunk) { 05770 /* This case happens in a bit of a race condition. If two stations answer 05771 * the outbound call at the same time, the first one will get connected to 05772 * the trunk. When the second one gets here, it will not see any trunks 05773 * ringing so we have no idea what to conect it to. So, we just hang up 05774 * on it. */ 05775 ast_debug(1, "Found no ringing trunk for station '%s' to answer!\n", ringing_station->station->name); 05776 ast_dial_join(ringing_station->station->dial); 05777 ast_dial_destroy(ringing_station->station->dial); 05778 ringing_station->station->dial = NULL; 05779 sla_ringing_station_destroy(ringing_station); 05780 break; 05781 } 05782 /* Track the channel that answered this trunk */ 05783 s_trunk_ref->chan = ast_dial_answered(ringing_station->station->dial); 05784 /* Actually answer the trunk */ 05785 answer_trunk_chan(ringing_trunk->trunk->chan); 05786 sla_change_trunk_state(ringing_trunk->trunk, SLA_TRUNK_STATE_UP, ALL_TRUNK_REFS, NULL); 05787 /* Now, start a thread that will connect this station to the trunk. The rest of 05788 * the code here sets up the thread and ensures that it is able to save the arguments 05789 * before they are no longer valid since they are allocated on the stack. */ 05790 ao2_ref(s_trunk_ref, 1); 05791 args.trunk_ref = s_trunk_ref; 05792 ao2_ref(ringing_station->station, 1); 05793 args.station = ringing_station->station; 05794 args.cond = &cond; 05795 args.cond_lock = &cond_lock; 05796 sla_ringing_trunk_destroy(ringing_trunk); 05797 sla_ringing_station_destroy(ringing_station); 05798 ast_mutex_init(&cond_lock); 05799 ast_cond_init(&cond, NULL); 05800 ast_mutex_lock(&cond_lock); 05801 ast_pthread_create_detached_background(&dont_care, NULL, run_station, &args); 05802 ast_cond_wait(&cond, &cond_lock); 05803 ast_mutex_unlock(&cond_lock); 05804 ast_mutex_destroy(&cond_lock); 05805 ast_cond_destroy(&cond); 05806 break; 05807 case AST_DIAL_RESULT_TRYING: 05808 case AST_DIAL_RESULT_RINGING: 05809 case AST_DIAL_RESULT_PROGRESS: 05810 case AST_DIAL_RESULT_PROCEEDING: 05811 break; 05812 } 05813 if (dial_res == AST_DIAL_RESULT_ANSWERED) { 05814 /* Queue up reprocessing ringing trunks, and then ringing stations again */ 05815 sla_queue_event(SLA_EVENT_RINGING_TRUNK); 05816 sla_queue_event(SLA_EVENT_DIAL_STATE); 05817 break; 05818 } 05819 } 05820 AST_LIST_TRAVERSE_SAFE_END; 05821 }
| static void sla_handle_hold_event | ( | struct sla_event * | event | ) | [static] |
Definition at line 6068 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().
06069 { 06070 ast_atomic_fetchadd_int((int *) &event->trunk_ref->trunk->hold_stations, 1); 06071 event->trunk_ref->state = SLA_TRUNK_STATE_ONHOLD_BYME; 06072 ast_devstate_changed(AST_DEVICE_ONHOLD, AST_DEVSTATE_CACHABLE, "SLA:%s_%s", 06073 event->station->name, event->trunk_ref->trunk->name); 06074 sla_change_trunk_state(event->trunk_ref->trunk, SLA_TRUNK_STATE_ONHOLD, 06075 INACTIVE_TRUNK_REFS, event->trunk_ref); 06076 06077 if (event->trunk_ref->trunk->active_stations == 1) { 06078 /* The station putting it on hold is the only one on the call, so start 06079 * Music on hold to the trunk. */ 06080 event->trunk_ref->trunk->on_hold = 1; 06081 ast_indicate(event->trunk_ref->trunk->chan, AST_CONTROL_HOLD); 06082 } 06083 06084 ast_softhangup(event->trunk_ref->chan, AST_SOFTHANGUP_DEV); 06085 event->trunk_ref->chan = NULL; 06086 }
| static void sla_handle_ringing_trunk_event | ( | void | ) | [static] |
Definition at line 6058 of file app_meetme.c.
References ast_mutex_lock, ast_mutex_unlock, sla, sla_hangup_stations(), and sla_ring_stations().
Referenced by sla_thread().
06059 { 06060 ast_mutex_lock(&sla.lock); 06061 sla_ring_stations(); 06062 ast_mutex_unlock(&sla.lock); 06063 06064 /* Find stations that shouldn't be ringing anymore. */ 06065 sla_hangup_stations(); 06066 }
| static void sla_hangup_stations | ( | void | ) | [static] |
Definition at line 6030 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().
06031 { 06032 struct sla_trunk_ref *trunk_ref; 06033 struct sla_ringing_station *ringing_station; 06034 06035 AST_LIST_TRAVERSE_SAFE_BEGIN(&sla.ringing_stations, ringing_station, entry) { 06036 AST_LIST_TRAVERSE(&ringing_station->station->trunks, trunk_ref, entry) { 06037 struct sla_ringing_trunk *ringing_trunk; 06038 ast_mutex_lock(&sla.lock); 06039 AST_LIST_TRAVERSE(&sla.ringing_trunks, ringing_trunk, entry) { 06040 if (trunk_ref->trunk == ringing_trunk->trunk) 06041 break; 06042 } 06043 ast_mutex_unlock(&sla.lock); 06044 if (ringing_trunk) 06045 break; 06046 } 06047 if (!trunk_ref) { 06048 AST_LIST_REMOVE_CURRENT(entry); 06049 ast_dial_join(ringing_station->station->dial); 06050 ast_dial_destroy(ringing_station->station->dial); 06051 ringing_station->station->dial = NULL; 06052 sla_ringing_station_destroy(ringing_station); 06053 } 06054 } 06055 AST_LIST_TRAVERSE_SAFE_END 06056 }
| 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 7375 of file app_meetme.c.
References ao2_container_count(), sla_stations, and sla_trunks.
Referenced by sla_load_config().
07376 { 07377 return ao2_container_count(sla_trunks) || ao2_container_count(sla_stations); 07378 }
| static int sla_load_config | ( | int | reload | ) | [static] |
Definition at line 7380 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().
07381 { 07382 struct ast_config *cfg; 07383 struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; 07384 const char *cat = NULL; 07385 int res = 0; 07386 const char *val; 07387 07388 if (!reload) { 07389 ast_mutex_init(&sla.lock); 07390 ast_cond_init(&sla.cond, NULL); 07391 sla_trunks = ao2_container_alloc(1, sla_trunk_hash, sla_trunk_cmp); 07392 sla_stations = ao2_container_alloc(1, sla_station_hash, sla_station_cmp); 07393 } 07394 07395 if (!(cfg = ast_config_load(SLA_CONFIG_FILE, config_flags))) { 07396 return 0; /* Treat no config as normal */ 07397 } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) { 07398 return 0; 07399 } else if (cfg == CONFIG_STATUS_FILEINVALID) { 07400 ast_log(LOG_ERROR, "Config file " SLA_CONFIG_FILE " is in an invalid format. Aborting.\n"); 07401 return 0; 07402 } 07403 07404 if (reload) { 07405 ao2_callback(sla_trunks, 0, sla_trunk_mark, NULL); 07406 ao2_callback(sla_stations, 0, sla_station_mark, NULL); 07407 } 07408 07409 if ((val = ast_variable_retrieve(cfg, "general", "attemptcallerid"))) 07410 sla.attempt_callerid = ast_true(val); 07411 07412 while ((cat = ast_category_browse(cfg, cat)) && !res) { 07413 const char *type; 07414 if (!strcasecmp(cat, "general")) 07415 continue; 07416 if (!(type = ast_variable_retrieve(cfg, cat, "type"))) { 07417 ast_log(LOG_WARNING, "Invalid entry in %s defined with no type!\n", 07418 SLA_CONFIG_FILE); 07419 continue; 07420 } 07421 if (!strcasecmp(type, "trunk")) 07422 res = sla_build_trunk(cfg, cat); 07423 else if (!strcasecmp(type, "station")) 07424 res = sla_build_station(cfg, cat); 07425 else { 07426 ast_log(LOG_WARNING, "Entry in %s defined with invalid type '%s'!\n", 07427 SLA_CONFIG_FILE, type); 07428 } 07429 } 07430 07431 ast_config_destroy(cfg); 07432 07433 if (reload) { 07434 ao2_callback(sla_trunks, OBJ_NODATA | OBJ_UNLINK | OBJ_MULTIPLE, sla_trunk_is_marked, NULL); 07435 ao2_callback(sla_stations, OBJ_NODATA | OBJ_UNLINK | OBJ_MULTIPLE, sla_station_is_marked, NULL); 07436 } 07437 07438 /* Start SLA event processing thread once SLA has been configured. */ 07439 if (sla.thread == AST_PTHREADT_NULL && sla_in_use()) { 07440 ast_pthread_create(&sla.thread, NULL, sla_thread, NULL); 07441 } 07442 07443 return res; 07444 }
| static int sla_process_timers | ( | struct timespec * | ts | ) | [static] |
Calculate the time until the next known event.
Definition at line 6249 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().
06250 { 06251 unsigned int timeout = UINT_MAX; 06252 struct timeval wait; 06253 unsigned int change_made = 0; 06254 06255 /* Check for ring timeouts on ringing trunks */ 06256 if (sla_calc_trunk_timeouts(&timeout)) 06257 change_made = 1; 06258 06259 /* Check for ring timeouts on ringing stations */ 06260 if (sla_calc_station_timeouts(&timeout)) 06261 change_made = 1; 06262 06263 /* Check for station ring delays */ 06264 if (sla_calc_station_delays(&timeout)) 06265 change_made = 1; 06266 06267 /* queue reprocessing of ringing trunks */ 06268 if (change_made) 06269 sla_queue_event_nolock(SLA_EVENT_RINGING_TRUNK); 06270 06271 /* No timeout */ 06272 if (timeout == UINT_MAX) 06273 return 0; 06274 06275 if (ts) { 06276 wait = ast_tvadd(ast_tvnow(), ast_samp2tv(timeout, 1000)); 06277 ts->tv_sec = wait.tv_sec; 06278 ts->tv_nsec = wait.tv_usec * 1000; 06279 } 06280 06281 return 1; 06282 }
| 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 5864 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().
05865 { 05866 char *tech, *tech_data; 05867 struct ast_dial *dial; 05868 struct sla_ringing_station *ringing_station; 05869 enum ast_dial_result res; 05870 int caller_is_saved; 05871 struct ast_party_caller caller; 05872 05873 if (!(dial = ast_dial_create())) 05874 return -1; 05875 05876 ast_dial_set_state_callback(dial, sla_dial_state_callback); 05877 tech_data = ast_strdupa(station->device); 05878 tech = strsep(&tech_data, "/"); 05879 05880 if (ast_dial_append(dial, tech, tech_data) == -1) { 05881 ast_dial_destroy(dial); 05882 return -1; 05883 } 05884 05885 /* Do we need to save off the caller ID data? */ 05886 caller_is_saved = 0; 05887 if (!sla.attempt_callerid) { 05888 caller_is_saved = 1; 05889 caller = ringing_trunk->trunk->chan->caller; 05890 ast_party_caller_init(&ringing_trunk->trunk->chan->caller); 05891 } 05892 05893 res = ast_dial_run(dial, ringing_trunk->trunk->chan, 1); 05894 05895 /* Restore saved caller ID */ 05896 if (caller_is_saved) { 05897 ast_party_caller_free(&ringing_trunk->trunk->chan->caller); 05898 ringing_trunk->trunk->chan->caller = caller; 05899 } 05900 05901 if (res != AST_DIAL_RESULT_TRYING) { 05902 struct sla_failed_station *failed_station; 05903 ast_dial_destroy(dial); 05904 if ((failed_station = sla_create_failed_station(station))) { 05905 AST_LIST_INSERT_HEAD(&sla.failed_stations, failed_station, entry); 05906 } 05907 return -1; 05908 } 05909 if (!(ringing_station = sla_create_ringing_station(station))) { 05910 ast_dial_join(dial); 05911 ast_dial_destroy(dial); 05912 return -1; 05913 } 05914 05915 station->dial = dial; 05916 05917 AST_LIST_INSERT_HEAD(&sla.ringing_stations, ringing_station, entry); 05918 05919 return 0; 05920 }
| static void sla_ring_stations | ( | void | ) | [static] |
Ring stations based on current set of ringing trunks.
Definition at line 5989 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().
05990 { 05991 struct sla_station_ref *station_ref; 05992 struct sla_ringing_trunk *ringing_trunk; 05993 05994 /* Make sure that every station that uses at least one of the ringing 05995 * trunks, is ringing. */ 05996 AST_LIST_TRAVERSE(&sla.ringing_trunks, ringing_trunk, entry) { 05997 AST_LIST_TRAVERSE(&ringing_trunk->trunk->stations, station_ref, entry) { 05998 int time_left; 05999 06000 /* Is this station already ringing? */ 06001 if (sla_check_ringing_station(station_ref->station)) 06002 continue; 06003 06004 /* Is this station already in a call? */ 06005 if (sla_check_inuse_station(station_ref->station)) 06006 continue; 06007 06008 /* Did we fail to dial this station earlier? If so, has it been 06009 * a minute since we tried? */ 06010 if (sla_check_failed_station(station_ref->station)) 06011 continue; 06012 06013 /* If this station already timed out while this trunk was ringing, 06014 * do not dial it again for this ringing trunk. */ 06015 if (sla_check_timed_out_station(ringing_trunk, station_ref->station)) 06016 continue; 06017 06018 /* Check for a ring delay in progress */ 06019 time_left = sla_check_station_delay(station_ref->station, ringing_trunk); 06020 if (time_left != INT_MAX && time_left > 0) 06021 continue; 06022 06023 /* It is time to make this station begin to ring. Do it! */ 06024 sla_ring_station(ringing_trunk, station_ref->station); 06025 } 06026 } 06027 /* Now, all of the stations that should be ringing, are ringing. */ 06028 }
| static void sla_ringing_station_destroy | ( | struct sla_ringing_station * | ringing_station | ) | [static] |
Definition at line 5486 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 6714 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 6835 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().
06836 { 06837 char *buf, *station_name, *trunk_name; 06838 RAII_VAR(struct sla_station *, station, NULL, unref_obj); 06839 struct sla_trunk_ref *trunk_ref; 06840 enum ast_device_state res = AST_DEVICE_INVALID; 06841 06842 trunk_name = buf = ast_strdupa(data); 06843 station_name = strsep(&trunk_name, "_"); 06844 06845 station = sla_find_station(station_name); 06846 if (station) { 06847 ao2_lock(station); 06848 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) { 06849 if (!strcasecmp(trunk_name, trunk_ref->trunk->name)) { 06850 res = sla_state_to_devstate(trunk_ref->state); 06851 break; 06852 } 06853 } 06854 ao2_unlock(station); 06855 } 06856 06857 if (res == AST_DEVICE_INVALID) { 06858 ast_log(LOG_ERROR, "Could not determine state for trunk %s on station %s!\n", 06859 trunk_name, station_name); 06860 } 06861 06862 return res; 06863 }
| static enum ast_device_state sla_state_to_devstate | ( | enum sla_trunk_state | state | ) | [static] |
Definition at line 5521 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().
05522 { 05523 switch (state) { 05524 case SLA_TRUNK_STATE_IDLE: 05525 return AST_DEVICE_NOT_INUSE; 05526 case SLA_TRUNK_STATE_RINGING: 05527 return AST_DEVICE_RINGING; 05528 case SLA_TRUNK_STATE_UP: 05529 return AST_DEVICE_INUSE; 05530 case SLA_TRUNK_STATE_ONHOLD: 05531 case SLA_TRUNK_STATE_ONHOLD_BYME: 05532 return AST_DEVICE_ONHOLD; 05533 } 05534 05535 return AST_DEVICE_UNKNOWN; 05536 }
| static int sla_station_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().
06937 { 06938 struct sla_station *station = obj, *station2 = arg; 06939 06940 return !strcasecmp(station->name, station2->name) ? CMP_MATCH | CMP_STOP : 0; 06941 }
| static void sla_station_destructor | ( | void * | obj | ) | [static] |
Definition at line 6889 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().
06890 { 06891 struct sla_station *station = obj; 06892 06893 ast_debug(1, "sla_station destructor for '%s'\n", station->name); 06894 06895 if (!ast_strlen_zero(station->autocontext)) { 06896 struct sla_trunk_ref *trunk_ref; 06897 06898 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) { 06899 char exten[AST_MAX_EXTENSION]; 06900 char hint[AST_MAX_APP]; 06901 snprintf(exten, sizeof(exten), "%s_%s", station->name, trunk_ref->trunk->name); 06902 snprintf(hint, sizeof(hint), "SLA:%s", exten); 06903 ast_context_remove_extension(station->autocontext, exten, 06904 1, sla_registrar); 06905 ast_context_remove_extension(station->autocontext, hint, 06906 PRIORITY_HINT, sla_registrar); 06907 } 06908 } 06909 06910 sla_station_release_refs(station, NULL, 0); 06911 06912 ast_string_field_free_memory(station); 06913 }
| static int sla_station_exec | ( | struct ast_channel * | chan, | |
| const char * | data | |||
| ) | [static] |
Definition at line 6515 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().
06516 { 06517 char *station_name, *trunk_name; 06518 RAII_VAR(struct sla_station *, station, NULL, unref_obj); 06519 RAII_VAR(struct sla_trunk_ref *, trunk_ref, NULL, unref_obj); 06520 char conf_name[MAX_CONFNUM]; 06521 struct ast_flags64 conf_flags = { 0 }; 06522 struct ast_conference *conf; 06523 06524 if (ast_strlen_zero(data)) { 06525 ast_log(LOG_WARNING, "Invalid Arguments to SLAStation!\n"); 06526 pbx_builtin_setvar_helper(chan, "SLASTATION_STATUS", "FAILURE"); 06527 return 0; 06528 } 06529 06530 trunk_name = ast_strdupa(data); 06531 station_name = strsep(&trunk_name, "_"); 06532 06533 if (ast_strlen_zero(station_name)) { 06534 ast_log(LOG_WARNING, "Invalid Arguments to SLAStation!\n"); 06535 pbx_builtin_setvar_helper(chan, "SLASTATION_STATUS", "FAILURE"); 06536 return 0; 06537 } 06538 06539 station = sla_find_station(station_name); 06540 06541 if (!station) { 06542 ast_log(LOG_WARNING, "Station '%s' not found!\n", station_name); 06543 pbx_builtin_setvar_helper(chan, "SLASTATION_STATUS", "FAILURE"); 06544 return 0; 06545 } 06546 06547 ao2_lock(station); 06548 if (!ast_strlen_zero(trunk_name)) { 06549 trunk_ref = sla_find_trunk_ref_byname(station, trunk_name); 06550 } else { 06551 trunk_ref = sla_choose_idle_trunk(station); 06552 } 06553 ao2_unlock(station); 06554 06555 if (!trunk_ref) { 06556 if (ast_strlen_zero(trunk_name)) 06557 ast_log(LOG_NOTICE, "No trunks available for call.\n"); 06558 else { 06559 ast_log(LOG_NOTICE, "Can't join existing call on trunk " 06560 "'%s' due to access controls.\n", trunk_name); 06561 } 06562 pbx_builtin_setvar_helper(chan, "SLASTATION_STATUS", "CONGESTION"); 06563 return 0; 06564 } 06565 06566 if (trunk_ref->state == SLA_TRUNK_STATE_ONHOLD_BYME) { 06567 if (ast_atomic_dec_and_test((int *) &trunk_ref->trunk->hold_stations) == 1) 06568 sla_change_trunk_state(trunk_ref->trunk, SLA_TRUNK_STATE_UP, ALL_TRUNK_REFS, NULL); 06569 else { 06570 trunk_ref->state = SLA_TRUNK_STATE_UP; 06571 ast_devstate_changed(AST_DEVICE_INUSE, AST_DEVSTATE_CACHABLE, 06572 "SLA:%s_%s", station->name, trunk_ref->trunk->name); 06573 } 06574 } else if (trunk_ref->state == SLA_TRUNK_STATE_RINGING) { 06575 struct sla_ringing_trunk *ringing_trunk; 06576 06577 ast_mutex_lock(&sla.lock); 06578 AST_LIST_TRAVERSE_SAFE_BEGIN(&sla.ringing_trunks, ringing_trunk, entry) { 06579 if (ringing_trunk->trunk == trunk_ref->trunk) { 06580 AST_LIST_REMOVE_CURRENT(entry); 06581 break; 06582 } 06583 } 06584 AST_LIST_TRAVERSE_SAFE_END 06585 ast_mutex_unlock(&sla.lock); 06586 06587 if (ringing_trunk) { 06588 answer_trunk_chan(ringing_trunk->trunk->chan); 06589 sla_change_trunk_state(ringing_trunk->trunk, SLA_TRUNK_STATE_UP, ALL_TRUNK_REFS, NULL); 06590 06591 sla_ringing_trunk_destroy(ringing_trunk); 06592 06593 /* Queue up reprocessing ringing trunks, and then ringing stations again */ 06594 sla_queue_event(SLA_EVENT_RINGING_TRUNK); 06595 sla_queue_event(SLA_EVENT_DIAL_STATE); 06596 } 06597 } 06598 06599 trunk_ref->chan = chan; 06600 06601 if (!trunk_ref->trunk->chan) { 06602 ast_mutex_t cond_lock; 06603 ast_cond_t cond; 06604 pthread_t dont_care; 06605 struct dial_trunk_args args = { 06606 .trunk_ref = trunk_ref, 06607 .station = station, 06608 .cond_lock = &cond_lock, 06609 .cond = &cond, 06610 }; 06611 ao2_ref(trunk_ref, 1); 06612 ao2_ref(station, 1); 06613 sla_change_trunk_state(trunk_ref->trunk, SLA_TRUNK_STATE_UP, ALL_TRUNK_REFS, NULL); 06614 /* Create a thread to dial the trunk and dump it into the conference. 06615 * However, we want to wait until the trunk has been dialed and the 06616 * conference is created before continuing on here. */ 06617 ast_autoservice_start(chan); 06618 ast_mutex_init(&cond_lock); 06619 ast_cond_init(&cond, NULL); 06620 ast_mutex_lock(&cond_lock); 06621 ast_pthread_create_detached_background(&dont_care, NULL, dial_trunk, &args); 06622 ast_cond_wait(&cond, &cond_lock); 06623 ast_mutex_unlock(&cond_lock); 06624 ast_mutex_destroy(&cond_lock); 06625 ast_cond_destroy(&cond); 06626 ast_autoservice_stop(chan); 06627 if (!trunk_ref->trunk->chan) { 06628 ast_debug(1, "Trunk didn't get created. chan: %lx\n", (long) trunk_ref->trunk->chan); 06629 pbx_builtin_setvar_helper(chan, "SLASTATION_STATUS", "CONGESTION"); 06630 sla_change_trunk_state(trunk_ref->trunk, SLA_TRUNK_STATE_IDLE, ALL_TRUNK_REFS, NULL); 06631 trunk_ref->chan = NULL; 06632 return 0; 06633 } 06634 } 06635 06636 if (ast_atomic_fetchadd_int((int *) &trunk_ref->trunk->active_stations, 1) == 0 && 06637 trunk_ref->trunk->on_hold) { 06638 trunk_ref->trunk->on_hold = 0; 06639 ast_indicate(trunk_ref->trunk->chan, AST_CONTROL_UNHOLD); 06640 sla_change_trunk_state(trunk_ref->trunk, SLA_TRUNK_STATE_UP, ALL_TRUNK_REFS, NULL); 06641 } 06642 06643 snprintf(conf_name, sizeof(conf_name), "SLA_%s", trunk_ref->trunk->name); 06644 ast_set_flag64(&conf_flags, 06645 CONFFLAG_QUIET | CONFFLAG_MARKEDEXIT | CONFFLAG_PASS_DTMF | CONFFLAG_SLA_STATION); 06646 ast_answer(chan); 06647 conf = build_conf(conf_name, "", "", 0, 0, 1, chan, NULL); 06648 if (conf) { 06649 conf_run(chan, conf, &conf_flags, NULL); 06650 dispose_conf(conf); 06651 conf = NULL; 06652 } 06653 trunk_ref->chan = NULL; 06654 if (ast_atomic_dec_and_test((int *) &trunk_ref->trunk->active_stations) && 06655 trunk_ref->state != SLA_TRUNK_STATE_ONHOLD_BYME) { 06656 strncat(conf_name, ",K", sizeof(conf_name) - strlen(conf_name) - 1); 06657 admin_exec(NULL, conf_name); 06658 trunk_ref->trunk->hold_stations = 0; 06659 sla_change_trunk_state(trunk_ref->trunk, SLA_TRUNK_STATE_IDLE, ALL_TRUNK_REFS, NULL); 06660 } 06661 06662 pbx_builtin_setvar_helper(chan, "SLASTATION_STATUS", "SUCCESS"); 06663 06664 return 0; 06665 }
| static int sla_station_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_station *station = obj; 06932 06933 return ast_str_case_hash(station->name); 06934 }
| static int sla_station_is_marked | ( | void * | obj, | |
| void * | arg, | |||
| int | flags | |||
| ) | [static] |
Definition at line 7347 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().
07348 { 07349 struct sla_station *station = obj; 07350 07351 ao2_lock(station); 07352 07353 if (station->mark) { 07354 /* Only remove all of the trunk references if the station itself is going away */ 07355 sla_station_release_refs(station, NULL, 0); 07356 } else { 07357 struct sla_trunk_ref *trunk_ref; 07358 07359 /* Otherwise only remove references to trunks no longer in the config */ 07360 AST_LIST_TRAVERSE_SAFE_BEGIN(&station->trunks, trunk_ref, entry) { 07361 if (!trunk_ref->mark) { 07362 continue; 07363 } 07364 AST_LIST_REMOVE_CURRENT(entry); 07365 ao2_ref(trunk_ref, -1); 07366 } 07367 AST_LIST_TRAVERSE_SAFE_END 07368 } 07369 07370 ao2_unlock(station); 07371 07372 return station->mark ? CMP_MATCH : 0; 07373 }
| static int sla_station_mark | ( | void * | obj, | |
| void * | arg, | |||
| int | flags | |||
| ) | [static] |
Definition at line 7301 of file app_meetme.c.
References ao2_lock, ao2_unlock, and AST_LIST_TRAVERSE.
Referenced by sla_load_config().
07302 { 07303 struct sla_station *station = obj; 07304 struct sla_trunk_ref *trunk_ref; 07305 07306 ao2_lock(station); 07307 07308 station->mark = 1; 07309 07310 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) { 07311 trunk_ref->mark = 1; 07312 } 07313 07314 ao2_unlock(station); 07315 07316 return 0; 07317 }
| static void sla_station_ref_destructor | ( | void * | obj | ) | [static] |
Definition at line 5448 of file app_meetme.c.
References ao2_ref.
Referenced by sla_create_station_ref().
05449 { 05450 struct sla_station_ref *station_ref = obj; 05451 05452 if (station_ref->station) { 05453 ao2_ref(station_ref->station, -1); 05454 station_ref->station = NULL; 05455 } 05456 }
| static int sla_station_release_refs | ( | void * | obj, | |
| void * | arg, | |||
| int | flags | |||
| ) | [static] |
Definition at line 6877 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().
06878 { 06879 struct sla_station *station = obj; 06880 struct sla_trunk_ref *trunk_ref; 06881 06882 while ((trunk_ref = AST_LIST_REMOVE_HEAD(&station->trunks, entry))) { 06883 ao2_ref(trunk_ref, -1); 06884 } 06885 06886 return 0; 06887 }
| static void sla_stop_ringing_station | ( | struct sla_ringing_station * | ringing_station, | |
| enum sla_station_hangup | hangup | |||
| ) | [static] |
Definition at line 5641 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().
05643 { 05644 struct sla_ringing_trunk *ringing_trunk; 05645 struct sla_trunk_ref *trunk_ref; 05646 struct sla_station_ref *station_ref; 05647 05648 ast_dial_join(ringing_station->station->dial); 05649 ast_dial_destroy(ringing_station->station->dial); 05650 ringing_station->station->dial = NULL; 05651 05652 if (hangup == SLA_STATION_HANGUP_NORMAL) 05653 goto done; 05654 05655 /* If the station is being hung up because of a timeout, then add it to the 05656 * list of timed out stations on each of the ringing trunks. This is so 05657 * that when doing further processing to figure out which stations should be 05658 * ringing, which trunk to answer, determining timeouts, etc., we know which 05659 * ringing trunks we should ignore. */ 05660 AST_LIST_TRAVERSE(&sla.ringing_trunks, ringing_trunk, entry) { 05661 AST_LIST_TRAVERSE(&ringing_station->station->trunks, trunk_ref, entry) { 05662 if (ringing_trunk->trunk == trunk_ref->trunk) 05663 break; 05664 } 05665 if (!trunk_ref) 05666 continue; 05667 if (!(station_ref = sla_create_station_ref(ringing_station->station))) 05668 continue; 05669 AST_LIST_INSERT_TAIL(&ringing_trunk->timed_out_stations, station_ref, entry); 05670 } 05671 05672 done: 05673 sla_ringing_station_destroy(ringing_station); 05674 }
| static void sla_stop_ringing_trunk | ( | struct sla_ringing_trunk * | ringing_trunk | ) | [static] |
Definition at line 5625 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().
05626 { 05627 char buf[80]; 05628 struct sla_station_ref *station_ref; 05629 05630 snprintf(buf, sizeof(buf), "SLA_%s,K", ringing_trunk->trunk->name); 05631 admin_exec(NULL, buf); 05632 sla_change_trunk_state(ringing_trunk->trunk, SLA_TRUNK_STATE_IDLE, ALL_TRUNK_REFS, NULL); 05633 05634 while ((station_ref = AST_LIST_REMOVE_HEAD(&ringing_trunk->timed_out_stations, entry))) { 05635 ao2_ref(station_ref, -1); 05636 } 05637 05638 sla_ringing_trunk_destroy(ringing_trunk); 05639 }
| static void* sla_thread | ( | void * | data | ) | [static] |
Definition at line 6299 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().
06300 { 06301 struct sla_failed_station *failed_station; 06302 struct sla_ringing_station *ringing_station; 06303 06304 ast_mutex_lock(&sla.lock); 06305 06306 while (!sla.stop) { 06307 struct sla_event *event; 06308 struct timespec ts = { 0, }; 06309 unsigned int have_timeout = 0; 06310 06311 if (AST_LIST_EMPTY(&sla.event_q)) { 06312 if ((have_timeout = sla_process_timers(&ts))) 06313 ast_cond_timedwait(&sla.cond, &sla.lock, &ts); 06314 else 06315 ast_cond_wait(&sla.cond, &sla.lock); 06316 if (sla.stop) 06317 break; 06318 } 06319 06320 if (have_timeout) 06321 sla_process_timers(NULL); 06322 06323 while ((event = AST_LIST_REMOVE_HEAD(&sla.event_q, entry))) { 06324 ast_mutex_unlock(&sla.lock); 06325 switch (event->type) { 06326 case SLA_EVENT_HOLD: 06327 sla_handle_hold_event(event); 06328 break; 06329 case SLA_EVENT_DIAL_STATE: 06330 sla_handle_dial_state_event(); 06331 break; 06332 case SLA_EVENT_RINGING_TRUNK: 06333 sla_handle_ringing_trunk_event(); 06334 break; 06335 } 06336 sla_event_destroy(event); 06337 ast_mutex_lock(&sla.lock); 06338 } 06339 } 06340 06341 ast_mutex_unlock(&sla.lock); 06342 06343 while ((ringing_station = AST_LIST_REMOVE_HEAD(&sla.ringing_stations, entry))) { 06344 sla_ringing_station_destroy(ringing_station); 06345 } 06346 06347 while ((failed_station = AST_LIST_REMOVE_HEAD(&sla.failed_stations, entry))) { 06348 sla_failed_station_destroy(failed_station); 06349 } 06350 06351 return NULL; 06352 }
| static int sla_trunk_cmp | ( | void * | obj, | |
| void * | arg, | |||
| int | flags | |||
| ) | [static] |
Definition at line 6922 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 6982 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().
06983 { 06984 struct sla_trunk *trunk = obj; 06985 06986 ast_debug(1, "sla_trunk destructor for '%s'\n", trunk->name); 06987 06988 if (!ast_strlen_zero(trunk->autocontext)) { 06989 ast_context_remove_extension(trunk->autocontext, "s", 1, sla_registrar); 06990 } 06991 06992 sla_trunk_release_refs(trunk, NULL, 0); 06993 06994 ast_string_field_free_memory(trunk); 06995 }
| static int sla_trunk_exec | ( | struct ast_channel * | chan, | |
| const char * | data | |||
| ) | [static] |
Definition at line 6737 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().
06738 { 06739 char conf_name[MAX_CONFNUM]; 06740 struct ast_conference *conf; 06741 struct ast_flags64 conf_flags = { 0 }; 06742 RAII_VAR(struct sla_trunk *, trunk, NULL, unref_obj); 06743 struct sla_ringing_trunk *ringing_trunk; 06744 AST_DECLARE_APP_ARGS(args, 06745 AST_APP_ARG(trunk_name); 06746 AST_APP_ARG(options); 06747 ); 06748 char *opts[SLA_TRUNK_OPT_ARG_ARRAY_SIZE] = { NULL, }; 06749 struct ast_flags opt_flags = { 0 }; 06750 char *parse; 06751 06752 if (ast_strlen_zero(data)) { 06753 ast_log(LOG_ERROR, "The SLATrunk application requires an argument, the trunk name\n"); 06754 return -1; 06755 } 06756 06757 parse = ast_strdupa(data); 06758 AST_STANDARD_APP_ARGS(args, parse); 06759 if (args.argc == 2) { 06760 if (ast_app_parse_options(sla_trunk_opts, &opt_flags, opts, args.options)) { 06761 ast_log(LOG_ERROR, "Error parsing options for SLATrunk\n"); 06762 return -1; 06763 } 06764 } 06765 06766 trunk = sla_find_trunk(args.trunk_name); 06767 06768 if (!trunk) { 06769 ast_log(LOG_ERROR, "SLA Trunk '%s' not found!\n", args.trunk_name); 06770 pbx_builtin_setvar_helper(chan, "SLATRUNK_STATUS", "FAILURE"); 06771 return 0; 06772 } 06773 06774 if (trunk->chan) { 06775 ast_log(LOG_ERROR, "Call came in on %s, but the trunk is already in use!\n", 06776 args.trunk_name); 06777 pbx_builtin_setvar_helper(chan, "SLATRUNK_STATUS", "FAILURE"); 06778 return 0; 06779 } 06780 06781 trunk->chan = chan; 06782 06783 if (!(ringing_trunk = queue_ringing_trunk(trunk))) { 06784 pbx_builtin_setvar_helper(chan, "SLATRUNK_STATUS", "FAILURE"); 06785 return 0; 06786 } 06787 06788 snprintf(conf_name, sizeof(conf_name), "SLA_%s", args.trunk_name); 06789 conf = build_conf(conf_name, "", "", 1, 1, 1, chan, NULL); 06790 if (!conf) { 06791 pbx_builtin_setvar_helper(chan, "SLATRUNK_STATUS", "FAILURE"); 06792 return 0; 06793 } 06794 ast_set_flag64(&conf_flags, 06795 CONFFLAG_QUIET | CONFFLAG_MARKEDEXIT | CONFFLAG_MARKEDUSER | CONFFLAG_PASS_DTMF | CONFFLAG_NO_AUDIO_UNTIL_UP); 06796 06797 if (ast_test_flag(&opt_flags, SLA_TRUNK_OPT_MOH)) { 06798 ast_indicate(chan, -1); 06799 ast_set_flag64(&conf_flags, CONFFLAG_MOH); 06800 } else 06801 ast_indicate(chan, AST_CONTROL_RINGING); 06802 06803 conf_run(chan, conf, &conf_flags, opts); 06804 dispose_conf(conf); 06805 conf = NULL; 06806 trunk->chan = NULL; 06807 trunk->on_hold = 0; 06808 06809 sla_change_trunk_state(trunk, SLA_TRUNK_STATE_IDLE, ALL_TRUNK_REFS, NULL); 06810 06811 if (!pbx_builtin_getvar_helper(chan, "SLATRUNK_STATUS")) 06812 pbx_builtin_setvar_helper(chan, "SLATRUNK_STATUS", "SUCCESS"); 06813 06814 /* Remove the entry from the list of ringing trunks if it is still there. */ 06815 ast_mutex_lock(&sla.lock); 06816 AST_LIST_TRAVERSE_SAFE_BEGIN(&sla.ringing_trunks, ringing_trunk, entry) { 06817 if (ringing_trunk->trunk == trunk) { 06818 AST_LIST_REMOVE_CURRENT(entry); 06819 break; 06820 } 06821 } 06822 AST_LIST_TRAVERSE_SAFE_END; 06823 ast_mutex_unlock(&sla.lock); 06824 if (ringing_trunk) { 06825 sla_ringing_trunk_destroy(ringing_trunk); 06826 pbx_builtin_setvar_helper(chan, "SLATRUNK_STATUS", "UNANSWERED"); 06827 /* Queue reprocessing of ringing trunks to make stations stop ringing 06828 * that shouldn't be ringing after this trunk stopped. */ 06829 sla_queue_event(SLA_EVENT_RINGING_TRUNK); 06830 } 06831 06832 return 0; 06833 }
| static int sla_trunk_hash | ( | const void * | obj, | |
| const int | flags | |||
| ) | [static] |
Definition at line 6915 of file app_meetme.c.
References ast_str_case_hash().
Referenced by sla_load_config().
06916 { 06917 const struct sla_trunk *trunk = obj; 06918 06919 return ast_str_case_hash(trunk->name); 06920 }
| static int sla_trunk_is_marked | ( | void * | obj, | |
| void * | arg, | |||
| int | flags | |||
| ) | [static] |
Definition at line 7319 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().
07320 { 07321 struct sla_trunk *trunk = obj; 07322 07323 ao2_lock(trunk); 07324 07325 if (trunk->mark) { 07326 /* Only remove all of the station references if the trunk itself is going away */ 07327 sla_trunk_release_refs(trunk, NULL, 0); 07328 } else { 07329 struct sla_station_ref *station_ref; 07330 07331 /* Otherwise only remove references to stations no longer in the config */ 07332 AST_LIST_TRAVERSE_SAFE_BEGIN(&trunk->stations, station_ref, entry) { 07333 if (!station_ref->mark) { 07334 continue; 07335 } 07336 AST_LIST_REMOVE_CURRENT(entry); 07337 ao2_ref(station_ref, -1); 07338 } 07339 AST_LIST_TRAVERSE_SAFE_END 07340 } 07341 07342 ao2_unlock(trunk); 07343 07344 return trunk->mark ? CMP_MATCH : 0; 07345 }
| static int sla_trunk_mark | ( | void * | obj, | |
| void * | arg, | |||
| int | flags | |||
| ) | [static] |
Definition at line 7283 of file app_meetme.c.
References ao2_lock, ao2_unlock, and AST_LIST_TRAVERSE.
Referenced by sla_load_config().
07284 { 07285 struct sla_trunk *trunk = obj; 07286 struct sla_station_ref *station_ref; 07287 07288 ao2_lock(trunk); 07289 07290 trunk->mark = 1; 07291 07292 AST_LIST_TRAVERSE(&trunk->stations, station_ref, entry) { 07293 station_ref->mark = 1; 07294 } 07295 07296 ao2_unlock(trunk); 07297 07298 return 0; 07299 }
| static void sla_trunk_ref_destructor | ( | void * | obj | ) | [static] |
Definition at line 6667 of file app_meetme.c.
References ao2_ref.
Referenced by create_trunk_ref().
06668 { 06669 struct sla_trunk_ref *trunk_ref = obj; 06670 06671 if (trunk_ref->trunk) { 06672 ao2_ref(trunk_ref->trunk, -1); 06673 trunk_ref->trunk = NULL; 06674 } 06675 }
| static int sla_trunk_release_refs | ( | void * | obj, | |
| void * | arg, | |||
| int | flags | |||
| ) | [static] |
Definition at line 6865 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().
06866 { 06867 struct sla_trunk *trunk = obj; 06868 struct sla_station_ref *station_ref; 06869 06870 while ((station_ref = AST_LIST_REMOVE_HEAD(&trunk->stations, entry))) { 06871 ao2_ref(station_ref, -1); 06872 } 06873 06874 return 0; 06875 }
| 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 7705 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().
07706 { 07707 int res = 0; 07708 07709 ast_cli_unregister_multiple(cli_meetme, ARRAY_LEN(cli_meetme)); 07710 res = ast_manager_unregister("MeetmeMute"); 07711 res |= ast_manager_unregister("MeetmeUnmute"); 07712 res |= ast_manager_unregister("MeetmeList"); 07713 res |= ast_unregister_application(app4); 07714 res |= ast_unregister_application(app3); 07715 res |= ast_unregister_application(app2); 07716 res |= ast_unregister_application(app); 07717 res |= ast_unregister_application(slastation_app); 07718 res |= ast_unregister_application(slatrunk_app); 07719 07720 #ifdef TEST_FRAMEWORK 07721 AST_TEST_UNREGISTER(test_meetme_data_provider); 07722 #endif 07723 ast_data_unregister(NULL); 07724 07725 ast_devstate_prov_del("Meetme"); 07726 ast_devstate_prov_del("SLA"); 07727 07728 sla_destroy(); 07729 07730 res |= ast_custom_function_unregister(&meetme_info_acf); 07731 ast_unload_realtime("meetme"); 07732 07733 return res; 07734 }
| static int user_add_provider_cb | ( | void * | obj, | |
| void * | arg, | |||
| int | flags | |||
| ) | [static] |
Definition at line 7556 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().
07557 { 07558 struct ast_data *data_meetme_user; 07559 struct ast_data *data_meetme_user_channel; 07560 struct ast_data *data_meetme_user_volume; 07561 07562 struct ast_conf_user *user = obj; 07563 struct ast_data *data_meetme_users = arg; 07564 07565 data_meetme_user = ast_data_add_node(data_meetme_users, "user"); 07566 if (!data_meetme_user) { 07567 return 0; 07568 } 07569 /* user structure */ 07570 ast_data_add_structure(ast_conf_user, data_meetme_user, user); 07571 07572 /* user's channel */ 07573 data_meetme_user_channel = ast_data_add_node(data_meetme_user, "channel"); 07574 if (!data_meetme_user_channel) { 07575 return 0; 07576 } 07577 07578 ast_channel_data_add_structure(data_meetme_user_channel, user->chan, 1); 07579 07580 /* volume structure */ 07581 data_meetme_user_volume = ast_data_add_node(data_meetme_user, "listen-volume"); 07582 if (!data_meetme_user_volume) { 07583 return 0; 07584 } 07585 ast_data_add_int(data_meetme_user_volume, "desired", user->listen.desired); 07586 ast_data_add_int(data_meetme_user_volume, "actual", user->listen.actual); 07587 07588 data_meetme_user_volume = ast_data_add_node(data_meetme_user, "talk-volume"); 07589 if (!data_meetme_user_volume) { 07590 return 0; 07591 } 07592 ast_data_add_int(data_meetme_user_volume, "desired", user->talk.desired); 07593 ast_data_add_int(data_meetme_user_volume, "actual", user->talk.actual); 07594 07595 return 0; 07596 }
| static int user_chan_cb | ( | void * | obj, | |
| void * | args, | |||
| int | flags | |||
| ) | [static] |
Definition at line 4778 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 4750 of file app_meetme.c.
References tweak_listen_volume(), and VOL_DOWN.
Referenced by admin_exec().
04751 { 04752 struct ast_conf_user *user = obj; 04753 tweak_listen_volume(user, VOL_DOWN); 04754 return 0; 04755 }
| static int user_listen_volup_cb | ( | void * | obj, | |
| void * | unused, | |||
| int | flags | |||
| ) | [static] |
Definition at line 4743 of file app_meetme.c.
References tweak_listen_volume(), and VOL_UP.
Referenced by admin_exec().
04744 { 04745 struct ast_conf_user *user = obj; 04746 tweak_listen_volume(user, VOL_UP); 04747 return 0; 04748 }
| 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 4771 of file app_meetme.c.
References reset_volumes().
Referenced by admin_exec().
04772 { 04773 struct ast_conf_user *user = obj; 04774 reset_volumes(user); 04775 return 0; 04776 }
| 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 4764 of file app_meetme.c.
References tweak_talk_volume(), and VOL_DOWN.
Referenced by admin_exec().
04765 { 04766 struct ast_conf_user *user = obj; 04767 tweak_talk_volume(user, VOL_DOWN); 04768 return 0; 04769 }
| static int user_talk_volup_cb | ( | void * | obj, | |
| void * | unused, | |||
| int | flags | |||
| ) | [static] |
Definition at line 4757 of file app_meetme.c.
References tweak_talk_volume(), and VOL_UP.
Referenced by admin_exec().
04758 { 04759 struct ast_conf_user *user = obj; 04760 tweak_talk_volume(user, VOL_UP); 04761 return 0; 04762 }
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 7636 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 7641 of file app_meetme.c.
struct ast_custom_function meetme_info_acf [static] |
{
.name = "MEETME_INFO",
.read = acf_meetme_info,
}
Definition at line 7515 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().
1.6.1