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