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