#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 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 = "88eaa8f5c1bd988bedd71113385e0886" , .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 6951 of file app_meetme.c.
#define MEETME_DELAYDETECTENDTALK 1000 |
#define MEETME_DELAYDETECTTALK 300 |
#define MEETME_USER_DATA_EXPORT | ( | MEMBER | ) |
Definition at line 6968 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 6312 of file app_meetme.c.
06312 { 06313 SLA_TRUNK_OPT_ARG_MOH_CLASS = 0, 06314 SLA_TRUNK_OPT_ARG_ARRAY_SIZE = 1, 06315 };
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 7204 of file app_meetme.c.
static void __unreg_module | ( | void | ) | [static] |
Definition at line 7204 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 6880 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().
06881 { 06882 struct ast_conference *conf; 06883 char *parse; 06884 int result = -2; /* only non-negative numbers valid, -1 is used elsewhere */ 06885 AST_DECLARE_APP_ARGS(args, 06886 AST_APP_ARG(keyword); 06887 AST_APP_ARG(confno); 06888 ); 06889 06890 if (ast_strlen_zero(data)) { 06891 ast_log(LOG_ERROR, "Syntax: MEETME_INFO() requires two arguments\n"); 06892 return -1; 06893 } 06894 06895 parse = ast_strdupa(data); 06896 AST_STANDARD_APP_ARGS(args, parse); 06897 06898 if (ast_strlen_zero(args.keyword)) { 06899 ast_log(LOG_ERROR, "Syntax: MEETME_INFO() requires a keyword\n"); 06900 return -1; 06901 } 06902 06903 if (ast_strlen_zero(args.confno)) { 06904 ast_log(LOG_ERROR, "Syntax: MEETME_INFO() requires a conference number\n"); 06905 return -1; 06906 } 06907 06908 AST_LIST_LOCK(&confs); 06909 AST_LIST_TRAVERSE(&confs, conf, list) { 06910 if (!strcmp(args.confno, conf->confno)) { 06911 result = acf_meetme_info_eval(args.keyword, conf); 06912 break; 06913 } 06914 } 06915 AST_LIST_UNLOCK(&confs); 06916 06917 if (result > -1) { 06918 snprintf(buf, len, "%d", result); 06919 } else if (result == -1) { 06920 ast_log(LOG_NOTICE, "Error: invalid keyword: '%s'\n", args.keyword); 06921 snprintf(buf, len, "0"); 06922 } else if (result == -2) { 06923 ast_log(LOG_NOTICE, "Error: conference (%s) not found\n", args.confno); 06924 snprintf(buf, len, "0"); 06925 } 06926 06927 return 0; 06928 }
static int acf_meetme_info_eval | ( | const char * | keyword, | |
const struct ast_conference * | conf | |||
) | [static] |
Definition at line 6862 of file app_meetme.c.
References ast_conference::isdynamic, ast_conference::locked, ast_conference::start, and ast_conference::users.
Referenced by acf_meetme_info().
06863 { 06864 if (!strcasecmp("lock", keyword)) { 06865 return conf->locked; 06866 } else if (!strcasecmp("parties", keyword)) { 06867 return conf->users; 06868 } else if (!strcasecmp("activity", keyword)) { 06869 time_t now; 06870 now = time(NULL); 06871 return (now - conf->start); 06872 } else if (!strcasecmp("dynamic", keyword)) { 06873 return conf->isdynamic; 06874 } else { 06875 return -1; 06876 } 06877 06878 }
static int action_meetmelist | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 4798 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().
04799 { 04800 const char *actionid = astman_get_header(m, "ActionID"); 04801 const char *conference = astman_get_header(m, "Conference"); 04802 char idText[80] = ""; 04803 struct ast_conference *cnf; 04804 struct ast_conf_user *user; 04805 struct ao2_iterator user_iter; 04806 int total = 0; 04807 04808 if (!ast_strlen_zero(actionid)) 04809 snprintf(idText, sizeof(idText), "ActionID: %s\r\n", actionid); 04810 04811 if (AST_LIST_EMPTY(&confs)) { 04812 astman_send_error(s, m, "No active conferences."); 04813 return 0; 04814 } 04815 04816 astman_send_listack(s, m, "Meetme user list will follow", "start"); 04817 04818 /* Find the right conference */ 04819 AST_LIST_LOCK(&confs); 04820 AST_LIST_TRAVERSE(&confs, cnf, list) { 04821 /* If we ask for one particular, and this isn't it, skip it */ 04822 if (!ast_strlen_zero(conference) && strcmp(cnf->confno, conference)) 04823 continue; 04824 04825 /* Show all the users */ 04826 user_iter = ao2_iterator_init(cnf->usercontainer, 0); 04827 while ((user = ao2_iterator_next(&user_iter))) { 04828 total++; 04829 astman_append(s, 04830 "Event: MeetmeList\r\n" 04831 "%s" 04832 "Conference: %s\r\n" 04833 "UserNumber: %d\r\n" 04834 "CallerIDNum: %s\r\n" 04835 "CallerIDName: %s\r\n" 04836 "ConnectedLineNum: %s\r\n" 04837 "ConnectedLineName: %s\r\n" 04838 "Channel: %s\r\n" 04839 "Admin: %s\r\n" 04840 "Role: %s\r\n" 04841 "MarkedUser: %s\r\n" 04842 "Muted: %s\r\n" 04843 "Talking: %s\r\n" 04844 "\r\n", 04845 idText, 04846 cnf->confno, 04847 user->user_no, 04848 S_COR(user->chan->caller.id.number.valid, user->chan->caller.id.number.str, "<unknown>"), 04849 S_COR(user->chan->caller.id.name.valid, user->chan->caller.id.name.str, "<no name>"), 04850 S_COR(user->chan->connected.id.number.valid, user->chan->connected.id.number.str, "<unknown>"), 04851 S_COR(user->chan->connected.id.name.valid, user->chan->connected.id.name.str, "<no name>"), 04852 user->chan->name, 04853 ast_test_flag64(&user->userflags, CONFFLAG_ADMIN) ? "Yes" : "No", 04854 ast_test_flag64(&user->userflags, CONFFLAG_MONITOR) ? "Listen only" : ast_test_flag64(&user->userflags, CONFFLAG_TALKER) ? "Talk only" : "Talk and listen", 04855 ast_test_flag64(&user->userflags, CONFFLAG_MARKEDUSER) ? "Yes" : "No", 04856 user->adminflags & ADMINFLAG_MUTED ? "By admin" : user->adminflags & ADMINFLAG_SELFMUTED ? "By self" : "No", 04857 user->talking > 0 ? "Yes" : user->talking == 0 ? "No" : "Not monitored"); 04858 ao2_ref(user, -1); 04859 } 04860 ao2_iterator_destroy(&user_iter); 04861 } 04862 AST_LIST_UNLOCK(&confs); 04863 /* Send final confirmation */ 04864 astman_append(s, 04865 "Event: MeetmeListComplete\r\n" 04866 "EventList: Complete\r\n" 04867 "ListItems: %d\r\n" 04868 "%s" 04869 "\r\n", total, idText); 04870 return 0; 04871 }
static int action_meetmemute | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 4788 of file app_meetme.c.
References meetmemute().
Referenced by load_module().
04789 { 04790 return meetmemute(s, m, 1); 04791 }
static int action_meetmeunmute | ( | 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, 0); 04796 }
static int admin_exec | ( | struct ast_channel * | chan, | |
const char * | data | |||
) | [static] |
The MeetMeadmin application.
MeetMeAdmin(confno, command, caller)
Definition at line 4526 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().
04526 { 04527 char *params; 04528 struct ast_conference *cnf; 04529 struct ast_conf_user *user = NULL; 04530 AST_DECLARE_APP_ARGS(args, 04531 AST_APP_ARG(confno); 04532 AST_APP_ARG(command); 04533 AST_APP_ARG(user); 04534 ); 04535 int res = 0; 04536 04537 if (ast_strlen_zero(data)) { 04538 ast_log(LOG_WARNING, "MeetMeAdmin requires an argument!\n"); 04539 pbx_builtin_setvar_helper(chan, "MEETMEADMINSTATUS", "NOPARSE"); 04540 return -1; 04541 } 04542 04543 params = ast_strdupa(data); 04544 AST_STANDARD_APP_ARGS(args, params); 04545 04546 if (!args.command) { 04547 ast_log(LOG_WARNING, "MeetmeAdmin requires a command!\n"); 04548 pbx_builtin_setvar_helper(chan, "MEETMEADMINSTATUS", "NOPARSE"); 04549 return -1; 04550 } 04551 04552 AST_LIST_LOCK(&confs); 04553 AST_LIST_TRAVERSE(&confs, cnf, list) { 04554 if (!strcmp(cnf->confno, args.confno)) 04555 break; 04556 } 04557 04558 if (!cnf) { 04559 ast_log(LOG_WARNING, "Conference number '%s' not found!\n", args.confno); 04560 AST_LIST_UNLOCK(&confs); 04561 pbx_builtin_setvar_helper(chan, "MEETMEADMINSTATUS", "NOTFOUND"); 04562 return 0; 04563 } 04564 04565 ast_atomic_fetchadd_int(&cnf->refcount, 1); 04566 04567 if (args.user) { 04568 user = find_user(cnf, args.user); 04569 if (!user) { 04570 ast_log(LOG_NOTICE, "Specified User not found!\n"); 04571 res = -2; 04572 goto usernotfound; 04573 } 04574 } 04575 04576 switch (*args.command) { 04577 case 76: /* L: Lock */ 04578 cnf->locked = 1; 04579 break; 04580 case 108: /* l: Unlock */ 04581 cnf->locked = 0; 04582 break; 04583 case 75: /* K: kick all users */ 04584 ao2_callback(cnf->usercontainer, OBJ_NODATA, user_set_kickme_cb, NULL); 04585 break; 04586 case 101: /* e: Eject last user*/ 04587 { 04588 int max_no = 0; 04589 ao2_callback(cnf->usercontainer, OBJ_NODATA, user_max_cmp, &max_no); 04590 user = ao2_find(cnf->usercontainer, &max_no, 0); 04591 if (!ast_test_flag64(&user->userflags, CONFFLAG_ADMIN)) 04592 user->adminflags |= ADMINFLAG_KICKME; 04593 else { 04594 res = -1; 04595 ast_log(LOG_NOTICE, "Not kicking last user, is an Admin!\n"); 04596 } 04597 ao2_ref(user, -1); 04598 break; 04599 } 04600 case 77: /* M: Mute */ 04601 user->adminflags |= ADMINFLAG_MUTED; 04602 break; 04603 case 78: /* N: Mute all (non-admin) users */ 04604 ao2_callback(cnf->usercontainer, OBJ_NODATA, user_set_muted_cb, NULL); 04605 break; 04606 case 109: /* m: Unmute */ 04607 user->adminflags &= ~(ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED | ADMINFLAG_T_REQUEST); 04608 break; 04609 case 110: /* n: Unmute all users */ 04610 ao2_callback(cnf->usercontainer, OBJ_NODATA, user_set_unmuted_cb, NULL); 04611 break; 04612 case 107: /* k: Kick user */ 04613 user->adminflags |= ADMINFLAG_KICKME; 04614 break; 04615 case 118: /* v: Lower all users listen volume */ 04616 ao2_callback(cnf->usercontainer, OBJ_NODATA, user_listen_voldown_cb, NULL); 04617 break; 04618 case 86: /* V: Raise all users listen volume */ 04619 ao2_callback(cnf->usercontainer, OBJ_NODATA, user_listen_volup_cb, NULL); 04620 break; 04621 case 115: /* s: Lower all users speaking volume */ 04622 ao2_callback(cnf->usercontainer, OBJ_NODATA, user_talk_voldown_cb, NULL); 04623 break; 04624 case 83: /* S: Raise all users speaking volume */ 04625 ao2_callback(cnf->usercontainer, OBJ_NODATA, user_talk_volup_cb, NULL); 04626 break; 04627 case 82: /* R: Reset all volume levels */ 04628 ao2_callback(cnf->usercontainer, OBJ_NODATA, user_reset_vol_cb, NULL); 04629 break; 04630 case 114: /* r: Reset user's volume level */ 04631 reset_volumes(user); 04632 break; 04633 case 85: /* U: Raise user's listen volume */ 04634 tweak_listen_volume(user, VOL_UP); 04635 break; 04636 case 117: /* u: Lower user's listen volume */ 04637 tweak_listen_volume(user, VOL_DOWN); 04638 break; 04639 case 84: /* T: Raise user's talk volume */ 04640 tweak_talk_volume(user, VOL_UP); 04641 break; 04642 case 116: /* t: Lower user's talk volume */ 04643 tweak_talk_volume(user, VOL_DOWN); 04644 break; 04645 case 'E': /* E: Extend conference */ 04646 if (rt_extend_conf(args.confno)) { 04647 res = -1; 04648 } 04649 break; 04650 } 04651 04652 if (args.user) { 04653 /* decrement reference from find_user */ 04654 ao2_ref(user, -1); 04655 } 04656 usernotfound: 04657 AST_LIST_UNLOCK(&confs); 04658 04659 dispose_conf(cnf); 04660 pbx_builtin_setvar_helper(chan, "MEETMEADMINSTATUS", res == -2 ? "NOTFOUND" : res ? "FAILED" : "OK"); 04661 04662 return 0; 04663 }
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 5181 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().
05182 { 05183 ast_answer(chan); 05184 ast_indicate(chan, -1); 05185 }
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 4667 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().
04667 { 04668 char *params; 04669 struct ast_conference *conf = NULL; 04670 struct ast_conf_user *user = NULL; 04671 AST_DECLARE_APP_ARGS(args, 04672 AST_APP_ARG(channel); 04673 AST_APP_ARG(command); 04674 ); 04675 04676 if (ast_strlen_zero(data)) { 04677 ast_log(LOG_WARNING, "MeetMeChannelAdmin requires two arguments!\n"); 04678 return -1; 04679 } 04680 04681 params = ast_strdupa(data); 04682 AST_STANDARD_APP_ARGS(args, params); 04683 04684 if (!args.channel) { 04685 ast_log(LOG_WARNING, "MeetMeChannelAdmin requires a channel name!\n"); 04686 return -1; 04687 } 04688 04689 if (!args.command) { 04690 ast_log(LOG_WARNING, "MeetMeChannelAdmin requires a command!\n"); 04691 return -1; 04692 } 04693 04694 AST_LIST_LOCK(&confs); 04695 AST_LIST_TRAVERSE(&confs, conf, list) { 04696 if ((user = ao2_callback(conf->usercontainer, 0, user_chan_cb, args.channel))) { 04697 break; 04698 } 04699 } 04700 04701 if (!user) { 04702 ast_log(LOG_NOTICE, "Specified user (%s) not found\n", args.channel); 04703 AST_LIST_UNLOCK(&confs); 04704 return 0; 04705 } 04706 04707 /* perform the specified action */ 04708 switch (*args.command) { 04709 case 77: /* M: Mute */ 04710 user->adminflags |= ADMINFLAG_MUTED; 04711 break; 04712 case 109: /* m: Unmute */ 04713 user->adminflags &= ~ADMINFLAG_MUTED; 04714 break; 04715 case 107: /* k: Kick user */ 04716 user->adminflags |= ADMINFLAG_KICKME; 04717 break; 04718 default: /* unknown command */ 04719 ast_log(LOG_WARNING, "Unknown MeetMeChannelAdmin command '%s'\n", args.command); 04720 break; 04721 } 04722 ao2_ref(user, -1); 04723 AST_LIST_UNLOCK(&confs); 04724 04725 return 0; 04726 }
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_flags, 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_start(), ast_moh_stop(), ast_mutex_init, ast_mutex_lock, ast_mutex_unlock, ast_null_frame, AST_OPTION_TONE_VERIFY, ast_play_and_record(), ast_pthread_create_background, ast_pthread_create_detached_background, AST_PTHREADT_NULL, ast_read(), ast_read_noaudio(), ast_realtime_require_field(), ast_record_review(), ast_request(), ast_safe_sleep(), ast_samp2tv(), ast_say_digits(), ast_say_number(), ast_set_flag64, ast_set_read_format(), 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: %i\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: %i\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: %i\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: %i\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 ast_moh_start(chan, NULL, NULL); 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 ast_moh_start(chan, NULL, NULL); 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 6275 of file app_meetme.c.
References ast_calloc, and sla_trunk_ref::trunk.
Referenced by sla_add_trunk_to_station().
06276 { 06277 struct sla_trunk_ref *trunk_ref; 06278 06279 if (!(trunk_ref = ast_calloc(1, sizeof(*trunk_ref)))) 06280 return NULL; 06281 06282 trunk_ref->trunk = trunk; 06283 06284 return trunk_ref; 06285 }
static void destroy_station | ( | struct sla_station * | station | ) | [static] |
Definition at line 6483 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().
06484 { 06485 struct sla_trunk_ref *trunk_ref; 06486 06487 if (!ast_strlen_zero(station->autocontext)) { 06488 AST_RWLIST_RDLOCK(&sla_trunks); 06489 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) { 06490 char exten[AST_MAX_EXTENSION]; 06491 char hint[AST_MAX_APP]; 06492 snprintf(exten, sizeof(exten), "%s_%s", station->name, trunk_ref->trunk->name); 06493 snprintf(hint, sizeof(hint), "SLA:%s", exten); 06494 ast_context_remove_extension(station->autocontext, exten, 06495 1, sla_registrar); 06496 ast_context_remove_extension(station->autocontext, hint, 06497 PRIORITY_HINT, sla_registrar); 06498 } 06499 AST_RWLIST_UNLOCK(&sla_trunks); 06500 } 06501 06502 while ((trunk_ref = AST_LIST_REMOVE_HEAD(&station->trunks, entry))) 06503 ast_free(trunk_ref); 06504 06505 ast_string_field_free_memory(station); 06506 ast_free(station); 06507 }
static void destroy_trunk | ( | struct sla_trunk * | trunk | ) | [static] |
Definition at line 6469 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().
06470 { 06471 struct sla_station_ref *station_ref; 06472 06473 if (!ast_strlen_zero(trunk->autocontext)) 06474 ast_context_remove_extension(trunk->autocontext, "s", 1, sla_registrar); 06475 06476 while ((station_ref = AST_LIST_REMOVE_HEAD(&trunk->stations, entry))) 06477 ast_free(station_ref); 06478 06479 ast_string_field_free_memory(trunk); 06480 ast_free(trunk); 06481 }
static void* dial_trunk | ( | void * | data | ) | [static] |
Definition at line 5988 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().
05989 { 05990 struct dial_trunk_args *args = data; 05991 struct ast_dial *dial; 05992 char *tech, *tech_data; 05993 enum ast_dial_result dial_res; 05994 char conf_name[MAX_CONFNUM]; 05995 struct ast_conference *conf; 05996 struct ast_flags64 conf_flags = { 0 }; 05997 struct sla_trunk_ref *trunk_ref = args->trunk_ref; 05998 int caller_is_saved; 05999 struct ast_party_caller caller; 06000 06001 if (!(dial = ast_dial_create())) { 06002 ast_mutex_lock(args->cond_lock); 06003 ast_cond_signal(args->cond); 06004 ast_mutex_unlock(args->cond_lock); 06005 return NULL; 06006 } 06007 06008 tech_data = ast_strdupa(trunk_ref->trunk->device); 06009 tech = strsep(&tech_data, "/"); 06010 if (ast_dial_append(dial, tech, tech_data) == -1) { 06011 ast_mutex_lock(args->cond_lock); 06012 ast_cond_signal(args->cond); 06013 ast_mutex_unlock(args->cond_lock); 06014 ast_dial_destroy(dial); 06015 return NULL; 06016 } 06017 06018 /* Do we need to save of the caller ID data? */ 06019 caller_is_saved = 0; 06020 if (!sla.attempt_callerid) { 06021 caller_is_saved = 1; 06022 caller = trunk_ref->chan->caller; 06023 ast_party_caller_init(&trunk_ref->chan->caller); 06024 } 06025 06026 dial_res = ast_dial_run(dial, trunk_ref->chan, 1); 06027 06028 /* Restore saved caller ID */ 06029 if (caller_is_saved) { 06030 ast_party_caller_free(&trunk_ref->chan->caller); 06031 trunk_ref->chan->caller = caller; 06032 } 06033 06034 if (dial_res != AST_DIAL_RESULT_TRYING) { 06035 ast_mutex_lock(args->cond_lock); 06036 ast_cond_signal(args->cond); 06037 ast_mutex_unlock(args->cond_lock); 06038 ast_dial_destroy(dial); 06039 return NULL; 06040 } 06041 06042 for (;;) { 06043 unsigned int done = 0; 06044 switch ((dial_res = ast_dial_state(dial))) { 06045 case AST_DIAL_RESULT_ANSWERED: 06046 trunk_ref->trunk->chan = ast_dial_answered(dial); 06047 case AST_DIAL_RESULT_HANGUP: 06048 case AST_DIAL_RESULT_INVALID: 06049 case AST_DIAL_RESULT_FAILED: 06050 case AST_DIAL_RESULT_TIMEOUT: 06051 case AST_DIAL_RESULT_UNANSWERED: 06052 done = 1; 06053 case AST_DIAL_RESULT_TRYING: 06054 case AST_DIAL_RESULT_RINGING: 06055 case AST_DIAL_RESULT_PROGRESS: 06056 case AST_DIAL_RESULT_PROCEEDING: 06057 break; 06058 } 06059 if (done) 06060 break; 06061 } 06062 06063 if (!trunk_ref->trunk->chan) { 06064 ast_mutex_lock(args->cond_lock); 06065 ast_cond_signal(args->cond); 06066 ast_mutex_unlock(args->cond_lock); 06067 ast_dial_join(dial); 06068 ast_dial_destroy(dial); 06069 return NULL; 06070 } 06071 06072 snprintf(conf_name, sizeof(conf_name), "SLA_%s", trunk_ref->trunk->name); 06073 ast_set_flag64(&conf_flags, 06074 CONFFLAG_QUIET | CONFFLAG_MARKEDEXIT | CONFFLAG_MARKEDUSER | 06075 CONFFLAG_PASS_DTMF | CONFFLAG_SLA_TRUNK); 06076 conf = build_conf(conf_name, "", "", 1, 1, 1, trunk_ref->trunk->chan, NULL); 06077 06078 ast_mutex_lock(args->cond_lock); 06079 ast_cond_signal(args->cond); 06080 ast_mutex_unlock(args->cond_lock); 06081 06082 if (conf) { 06083 conf_run(trunk_ref->trunk->chan, conf, &conf_flags, NULL); 06084 dispose_conf(conf); 06085 conf = NULL; 06086 } 06087 06088 /* If the trunk is going away, it is definitely now IDLE. */ 06089 sla_change_trunk_state(trunk_ref->trunk, SLA_TRUNK_STATE_IDLE, ALL_TRUNK_REFS, NULL); 06090 06091 trunk_ref->trunk->chan = NULL; 06092 trunk_ref->trunk->on_hold = 0; 06093 06094 ast_dial_join(dial); 06095 ast_dial_destroy(dial); 06096 06097 return NULL; 06098 }
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 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_flags, 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 sscanf(callerident, "%30i", &cid); 04468 if (conf && callerident) { 04469 user = ao2_find(conf->usercontainer, &cid, 0); 04470 /* reference decremented later in admin_exec */ 04471 return user; 04472 } 04473 return NULL; 04474 }
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 6937 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().
06938 { 06939 load_config_meetme(); 06940 06941 if (reload && sla.thread != AST_PTHREADT_NULL) { 06942 sla_queue_event(SLA_EVENT_RELOAD); 06943 ast_log(LOG_NOTICE, "A reload of the SLA configuration has been requested " 06944 "and will be completed when the system is idle.\n"); 06945 return 0; 06946 } 06947 06948 return sla_load_config(0); 06949 }
static void load_config_meetme | ( | void | ) | [static] |
Definition at line 4960 of file app_meetme.c.
References ast_config_destroy(), ast_config_load, ast_log(), ast_true(), ast_variable_retrieve(), CONFIG_FILE_NAME, config_flags, CONFIG_STATUS_FILEINVALID, DEFAULT_AUDIO_BUFFERS, LOG_ERROR, LOG_NOTICE, and LOG_WARNING.
Referenced by load_config().
04961 { 04962 struct ast_config *cfg; 04963 struct ast_flags config_flags = { 0 }; 04964 const char *val; 04965 04966 if (!(cfg = ast_config_load(CONFIG_FILE_NAME, config_flags))) { 04967 return; 04968 } else if (cfg == CONFIG_STATUS_FILEINVALID) { 04969 ast_log(LOG_ERROR, "Config file " CONFIG_FILE_NAME " is in an invalid format. Aborting.\n"); 04970 return; 04971 } 04972 04973 audio_buffers = DEFAULT_AUDIO_BUFFERS; 04974 04975 /* Scheduling support is off by default */ 04976 rt_schedule = 0; 04977 fuzzystart = 0; 04978 earlyalert = 0; 04979 endalert = 0; 04980 extendby = 0; 04981 04982 /* Logging of participants defaults to ON for compatibility reasons */ 04983 rt_log_members = 1; 04984 04985 if ((val = ast_variable_retrieve(cfg, "general", "audiobuffers"))) { 04986 if ((sscanf(val, "%30d", &audio_buffers) != 1)) { 04987 ast_log(LOG_WARNING, "audiobuffers setting must be a number, not '%s'\n", val); 04988 audio_buffers = DEFAULT_AUDIO_BUFFERS; 04989 } else if ((audio_buffers < DAHDI_DEFAULT_NUM_BUFS) || (audio_buffers > DAHDI_MAX_NUM_BUFS)) { 04990 ast_log(LOG_WARNING, "audiobuffers setting must be between %d and %d\n", 04991 DAHDI_DEFAULT_NUM_BUFS, DAHDI_MAX_NUM_BUFS); 04992 audio_buffers = DEFAULT_AUDIO_BUFFERS; 04993 } 04994 if (audio_buffers != DEFAULT_AUDIO_BUFFERS) 04995 ast_log(LOG_NOTICE, "Audio buffers per channel set to %d\n", audio_buffers); 04996 } 04997 04998 if ((val = ast_variable_retrieve(cfg, "general", "schedule"))) 04999 rt_schedule = ast_true(val); 05000 if ((val = ast_variable_retrieve(cfg, "general", "logmembercount"))) 05001 rt_log_members = ast_true(val); 05002 if ((val = ast_variable_retrieve(cfg, "general", "fuzzystart"))) { 05003 if ((sscanf(val, "%30d", &fuzzystart) != 1)) { 05004 ast_log(LOG_WARNING, "fuzzystart must be a number, not '%s'\n", val); 05005 fuzzystart = 0; 05006 } 05007 } 05008 if ((val = ast_variable_retrieve(cfg, "general", "earlyalert"))) { 05009 if ((sscanf(val, "%30d", &earlyalert) != 1)) { 05010 ast_log(LOG_WARNING, "earlyalert must be a number, not '%s'\n", val); 05011 earlyalert = 0; 05012 } 05013 } 05014 if ((val = ast_variable_retrieve(cfg, "general", "endalert"))) { 05015 if ((sscanf(val, "%30d", &endalert) != 1)) { 05016 ast_log(LOG_WARNING, "endalert must be a number, not '%s'\n", val); 05017 endalert = 0; 05018 } 05019 } 05020 if ((val = ast_variable_retrieve(cfg, "general", "extendby"))) { 05021 if ((sscanf(val, "%30d", &extendby) != 1)) { 05022 ast_log(LOG_WARNING, "extendby must be a number, not '%s'\n", val); 05023 extendby = 0; 05024 } 05025 } 05026 05027 ast_config_destroy(cfg); 05028 }
static int load_module | ( | void | ) | [static] |
Definition at line 7162 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().
07163 { 07164 int res = 0; 07165 07166 res |= load_config(0); 07167 07168 ast_cli_register_multiple(cli_meetme, ARRAY_LEN(cli_meetme)); 07169 res |= ast_manager_register_xml("MeetmeMute", EVENT_FLAG_CALL, action_meetmemute); 07170 res |= ast_manager_register_xml("MeetmeUnmute", EVENT_FLAG_CALL, action_meetmeunmute); 07171 res |= ast_manager_register_xml("MeetmeList", EVENT_FLAG_REPORTING, action_meetmelist); 07172 res |= ast_register_application_xml(app4, channel_admin_exec); 07173 res |= ast_register_application_xml(app3, admin_exec); 07174 res |= ast_register_application_xml(app2, count_exec); 07175 res |= ast_register_application_xml(app, conf_exec); 07176 res |= ast_register_application_xml(slastation_app, sla_station_exec); 07177 res |= ast_register_application_xml(slatrunk_app, sla_trunk_exec); 07178 07179 #ifdef TEST_FRAMEWORK 07180 AST_TEST_REGISTER(test_meetme_data_provider); 07181 #endif 07182 ast_data_register_multiple(meetme_data_providers, ARRAY_LEN(meetme_data_providers)); 07183 07184 res |= ast_devstate_prov_add("Meetme", meetmestate); 07185 res |= ast_devstate_prov_add("SLA", sla_state); 07186 07187 res |= ast_custom_function_register(&meetme_info_acf); 07188 ast_realtime_require_field("meetme", "confno", RQ_UINTEGER2, 3, "members", RQ_UINTEGER1, 3, NULL); 07189 07190 return res; 07191 }
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 7026 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.
07028 { 07029 struct ast_conference *cnf; 07030 struct ast_data *data_meetme, *data_meetme_users; 07031 07032 AST_LIST_LOCK(&confs); 07033 AST_LIST_TRAVERSE(&confs, cnf, list) { 07034 data_meetme = ast_data_add_node(data_root, "meetme"); 07035 if (!data_meetme) { 07036 continue; 07037 } 07038 07039 ast_data_add_structure(ast_conference, data_meetme, cnf); 07040 07041 if (ao2_container_count(cnf->usercontainer)) { 07042 data_meetme_users = ast_data_add_node(data_meetme, "users"); 07043 if (!data_meetme_users) { 07044 ast_data_remove_node(data_root, data_meetme); 07045 continue; 07046 } 07047 07048 ao2_callback(cnf->usercontainer, OBJ_NODATA, user_add_provider_cb, data_meetme_users); 07049 } 07050 07051 if (!ast_data_search_match(search, data_meetme)) { 07052 ast_data_remove_node(data_root, data_meetme); 07053 } 07054 } 07055 AST_LIST_UNLOCK(&confs); 07056 07057 return 0; 07058 }
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 4728 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().
04729 { 04730 struct ast_conference *conf; 04731 struct ast_conf_user *user; 04732 const char *confid = astman_get_header(m, "Meetme"); 04733 char *userid = ast_strdupa(astman_get_header(m, "Usernum")); 04734 int userno; 04735 04736 if (ast_strlen_zero(confid)) { 04737 astman_send_error(s, m, "Meetme conference not specified"); 04738 return 0; 04739 } 04740 04741 if (ast_strlen_zero(userid)) { 04742 astman_send_error(s, m, "Meetme user number not specified"); 04743 return 0; 04744 } 04745 04746 userno = strtoul(userid, &userid, 10); 04747 04748 if (*userid) { 04749 astman_send_error(s, m, "Invalid user number"); 04750 return 0; 04751 } 04752 04753 /* Look in the conference list */ 04754 AST_LIST_LOCK(&confs); 04755 AST_LIST_TRAVERSE(&confs, conf, list) { 04756 if (!strcmp(confid, conf->confno)) 04757 break; 04758 } 04759 04760 if (!conf) { 04761 AST_LIST_UNLOCK(&confs); 04762 astman_send_error(s, m, "Meetme conference does not exist"); 04763 return 0; 04764 } 04765 04766 user = ao2_find(conf->usercontainer, &userno, 0); 04767 04768 if (!user) { 04769 AST_LIST_UNLOCK(&confs); 04770 astman_send_error(s, m, "User number not found"); 04771 return 0; 04772 } 04773 04774 if (mute) 04775 user->adminflags |= ADMINFLAG_MUTED; /* request user muting */ 04776 else 04777 user->adminflags &= ~(ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED | ADMINFLAG_T_REQUEST); /* request user unmuting */ 04778 04779 AST_LIST_UNLOCK(&confs); 04780 04781 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); 04782 04783 ao2_ref(user, -1); 04784 astman_send_ack(s, m, mute ? "User muted" : "User unmuted"); 04785 return 0; 04786 }
static enum ast_device_state meetmestate | ( | const char * | data | ) | [static] |
Callback for devicestate providers.
Definition at line 4938 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().
04939 { 04940 struct ast_conference *conf; 04941 04942 /* Find conference */ 04943 AST_LIST_LOCK(&confs); 04944 AST_LIST_TRAVERSE(&confs, conf, list) { 04945 if (!strcmp(data, conf->confno)) 04946 break; 04947 } 04948 AST_LIST_UNLOCK(&confs); 04949 if (!conf) 04950 return AST_DEVICE_INVALID; 04951 04952 04953 /* SKREP to fill */ 04954 if (!conf->users) 04955 return AST_DEVICE_NOT_INUSE; 04956 04957 return AST_DEVICE_INUSE; 04958 }
static struct sla_ringing_trunk* queue_ringing_trunk | ( | struct sla_trunk * | trunk | ) | [static] |
Definition at line 6287 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().
06288 { 06289 struct sla_ringing_trunk *ringing_trunk; 06290 06291 if (!(ringing_trunk = ast_calloc(1, sizeof(*ringing_trunk)))) 06292 return NULL; 06293 06294 ringing_trunk->trunk = trunk; 06295 ringing_trunk->ring_begin = ast_tvnow(); 06296 06297 sla_change_trunk_state(trunk, SLA_TRUNK_STATE_RINGING, ALL_TRUNK_REFS, NULL); 06298 06299 ast_mutex_lock(&sla.lock); 06300 AST_LIST_INSERT_HEAD(&sla.ringing_trunks, ringing_trunk, entry); 06301 ast_mutex_unlock(&sla.lock); 06302 06303 sla_queue_event(SLA_EVENT_RINGING_TRUNK); 06304 06305 return ringing_trunk; 06306 }
static void * recordthread | ( | void * | args | ) | [static] |
Definition at line 4873 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_waitfor(), ast_writefile(), ast_writestream(), f, 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.
04874 { 04875 struct ast_conference *cnf = args; 04876 struct ast_frame *f = NULL; 04877 int flags; 04878 struct ast_filestream *s = NULL; 04879 int res = 0; 04880 int x; 04881 const char *oldrecordingfilename = NULL; 04882 04883 if (!cnf || !cnf->lchan) { 04884 pthread_exit(0); 04885 } 04886 04887 ast_stopstream(cnf->lchan); 04888 flags = O_CREAT | O_TRUNC | O_WRONLY; 04889 04890 04891 cnf->recording = MEETME_RECORD_ACTIVE; 04892 while (ast_waitfor(cnf->lchan, -1) > -1) { 04893 if (cnf->recording == MEETME_RECORD_TERMINATE) { 04894 AST_LIST_LOCK(&confs); 04895 AST_LIST_UNLOCK(&confs); 04896 break; 04897 } 04898 if (!s && cnf->recordingfilename && (cnf->recordingfilename != oldrecordingfilename)) { 04899 s = ast_writefile(cnf->recordingfilename, cnf->recordingformat, NULL, flags, 0, AST_FILE_MODE); 04900 oldrecordingfilename = cnf->recordingfilename; 04901 } 04902 04903 f = ast_read(cnf->lchan); 04904 if (!f) { 04905 res = -1; 04906 break; 04907 } 04908 if (f->frametype == AST_FRAME_VOICE) { 04909 ast_mutex_lock(&cnf->listenlock); 04910 for (x = 0; x < AST_FRAME_BITS; x++) { 04911 /* Free any translations that have occured */ 04912 if (cnf->transframe[x]) { 04913 ast_frfree(cnf->transframe[x]); 04914 cnf->transframe[x] = NULL; 04915 } 04916 } 04917 if (cnf->origframe) 04918 ast_frfree(cnf->origframe); 04919 cnf->origframe = ast_frdup(f); 04920 ast_mutex_unlock(&cnf->listenlock); 04921 if (s) 04922 res = ast_writestream(s, f); 04923 if (res) { 04924 ast_frfree(f); 04925 break; 04926 } 04927 } 04928 ast_frfree(f); 04929 } 04930 cnf->recording = MEETME_RECORD_OFF; 04931 if (s) 04932 ast_closestream(s); 04933 04934 pthread_exit(0); 04935 }
static int reload | ( | void | ) | [static] |
Definition at line 7193 of file app_meetme.c.
References ast_unload_realtime(), and load_config().
07194 { 07195 ast_unload_realtime("meetme"); 07196 return load_config(1); 07197 }
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 5187 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().
05188 { 05189 struct sla_station *station; 05190 struct sla_trunk_ref *trunk_ref; 05191 struct ast_str *conf_name = ast_str_create(16); 05192 struct ast_flags64 conf_flags = { 0 }; 05193 struct ast_conference *conf; 05194 05195 { 05196 struct run_station_args *args = data; 05197 station = args->station; 05198 trunk_ref = args->trunk_ref; 05199 ast_mutex_lock(args->cond_lock); 05200 ast_cond_signal(args->cond); 05201 ast_mutex_unlock(args->cond_lock); 05202 /* args is no longer valid here. */ 05203 } 05204 05205 ast_atomic_fetchadd_int((int *) &trunk_ref->trunk->active_stations, 1); 05206 ast_str_set(&conf_name, 0, "SLA_%s", trunk_ref->trunk->name); 05207 ast_set_flag64(&conf_flags, 05208 CONFFLAG_QUIET | CONFFLAG_MARKEDEXIT | CONFFLAG_PASS_DTMF | CONFFLAG_SLA_STATION); 05209 answer_trunk_chan(trunk_ref->chan); 05210 conf = build_conf(ast_str_buffer(conf_name), "", "", 0, 0, 1, trunk_ref->chan, NULL); 05211 if (conf) { 05212 conf_run(trunk_ref->chan, conf, &conf_flags, NULL); 05213 dispose_conf(conf); 05214 conf = NULL; 05215 } 05216 trunk_ref->chan = NULL; 05217 if (ast_atomic_dec_and_test((int *) &trunk_ref->trunk->active_stations) && 05218 trunk_ref->state != SLA_TRUNK_STATE_ONHOLD_BYME) { 05219 ast_str_append(&conf_name, 0, ",K"); 05220 admin_exec(NULL, ast_str_buffer(conf_name)); 05221 trunk_ref->trunk->hold_stations = 0; 05222 sla_change_trunk_state(trunk_ref->trunk, SLA_TRUNK_STATE_IDLE, ALL_TRUNK_REFS, NULL); 05223 } 05224 05225 ast_dial_join(station->dial); 05226 ast_dial_destroy(station->dial); 05227 station->dial = NULL; 05228 ast_free(conf_name); 05229 05230 return NULL; 05231 }
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 6627 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().
06628 { 06629 struct sla_trunk *trunk; 06630 struct sla_trunk_ref *trunk_ref; 06631 struct sla_station_ref *station_ref; 06632 char *trunk_name, *options, *cur; 06633 06634 options = ast_strdupa(var->value); 06635 trunk_name = strsep(&options, ","); 06636 06637 AST_RWLIST_RDLOCK(&sla_trunks); 06638 AST_RWLIST_TRAVERSE(&sla_trunks, trunk, entry) { 06639 if (!strcasecmp(trunk->name, trunk_name)) 06640 break; 06641 } 06642 06643 AST_RWLIST_UNLOCK(&sla_trunks); 06644 if (!trunk) { 06645 ast_log(LOG_ERROR, "Trunk '%s' not found!\n", var->value); 06646 return; 06647 } 06648 if (!(trunk_ref = create_trunk_ref(trunk))) 06649 return; 06650 trunk_ref->state = SLA_TRUNK_STATE_IDLE; 06651 06652 while ((cur = strsep(&options, ","))) { 06653 char *name, *value = cur; 06654 name = strsep(&value, "="); 06655 if (!strcasecmp(name, "ringtimeout")) { 06656 if (sscanf(value, "%30u", &trunk_ref->ring_timeout) != 1) { 06657 ast_log(LOG_WARNING, "Invalid ringtimeout value '%s' for " 06658 "trunk '%s' on station '%s'\n", value, trunk->name, station->name); 06659 trunk_ref->ring_timeout = 0; 06660 } 06661 } else if (!strcasecmp(name, "ringdelay")) { 06662 if (sscanf(value, "%30u", &trunk_ref->ring_delay) != 1) { 06663 ast_log(LOG_WARNING, "Invalid ringdelay value '%s' for " 06664 "trunk '%s' on station '%s'\n", value, trunk->name, station->name); 06665 trunk_ref->ring_delay = 0; 06666 } 06667 } else { 06668 ast_log(LOG_WARNING, "Invalid option '%s' for " 06669 "trunk '%s' on station '%s'\n", name, trunk->name, station->name); 06670 } 06671 } 06672 06673 if (!(station_ref = sla_create_station_ref(station))) { 06674 ast_free(trunk_ref); 06675 return; 06676 } 06677 ast_atomic_fetchadd_int((int *) &trunk->num_stations, 1); 06678 AST_RWLIST_WRLOCK(&sla_trunks); 06679 AST_LIST_INSERT_TAIL(&trunk->stations, station_ref, entry); 06680 AST_RWLIST_UNLOCK(&sla_trunks); 06681 AST_LIST_INSERT_TAIL(&station->trunks, trunk_ref, entry); 06682 }
static int sla_build_station | ( | struct ast_config * | cfg, | |
const char * | cat | |||
) | [static] |
Definition at line 6684 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().
06685 { 06686 struct sla_station *station; 06687 struct ast_variable *var; 06688 const char *dev; 06689 06690 if (!(dev = ast_variable_retrieve(cfg, cat, "device"))) { 06691 ast_log(LOG_ERROR, "SLA Station '%s' defined with no device!\n", cat); 06692 return -1; 06693 } 06694 06695 if (!(station = ast_calloc_with_stringfields(1, struct sla_station, 32))) { 06696 return -1; 06697 } 06698 06699 ast_string_field_set(station, name, cat); 06700 ast_string_field_set(station, device, dev); 06701 06702 for (var = ast_variable_browse(cfg, cat); var; var = var->next) { 06703 if (!strcasecmp(var->name, "trunk")) 06704 sla_add_trunk_to_station(station, var); 06705 else if (!strcasecmp(var->name, "autocontext")) 06706 ast_string_field_set(station, autocontext, var->value); 06707 else if (!strcasecmp(var->name, "ringtimeout")) { 06708 if (sscanf(var->value, "%30u", &station->ring_timeout) != 1) { 06709 ast_log(LOG_WARNING, "Invalid ringtimeout '%s' specified for station '%s'\n", 06710 var->value, station->name); 06711 station->ring_timeout = 0; 06712 } 06713 } else if (!strcasecmp(var->name, "ringdelay")) { 06714 if (sscanf(var->value, "%30u", &station->ring_delay) != 1) { 06715 ast_log(LOG_WARNING, "Invalid ringdelay '%s' specified for station '%s'\n", 06716 var->value, station->name); 06717 station->ring_delay = 0; 06718 } 06719 } else if (!strcasecmp(var->name, "hold")) { 06720 if (!strcasecmp(var->value, "private")) 06721 station->hold_access = SLA_HOLD_PRIVATE; 06722 else if (!strcasecmp(var->value, "open")) 06723 station->hold_access = SLA_HOLD_OPEN; 06724 else { 06725 ast_log(LOG_WARNING, "Invalid value '%s' for hold on station %s\n", 06726 var->value, station->name); 06727 } 06728 06729 } else if (strcasecmp(var->name, "type") && strcasecmp(var->name, "device")) { 06730 ast_log(LOG_ERROR, "Invalid option '%s' specified at line %d of %s!\n", 06731 var->name, var->lineno, SLA_CONFIG_FILE); 06732 } 06733 } 06734 06735 if (!ast_strlen_zero(station->autocontext)) { 06736 struct ast_context *context; 06737 struct sla_trunk_ref *trunk_ref; 06738 context = ast_context_find_or_create(NULL, NULL, station->autocontext, sla_registrar); 06739 if (!context) { 06740 ast_log(LOG_ERROR, "Failed to automatically find or create " 06741 "context '%s' for SLA!\n", station->autocontext); 06742 destroy_station(station); 06743 return -1; 06744 } 06745 /* The extension for when the handset goes off-hook. 06746 * exten => station1,1,SLAStation(station1) */ 06747 if (ast_add_extension2(context, 0 /* don't replace */, station->name, 1, 06748 NULL, NULL, slastation_app, ast_strdup(station->name), ast_free_ptr, sla_registrar)) { 06749 ast_log(LOG_ERROR, "Failed to automatically create extension " 06750 "for trunk '%s'!\n", station->name); 06751 destroy_station(station); 06752 return -1; 06753 } 06754 AST_RWLIST_RDLOCK(&sla_trunks); 06755 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) { 06756 char exten[AST_MAX_EXTENSION]; 06757 char hint[AST_MAX_APP]; 06758 snprintf(exten, sizeof(exten), "%s_%s", station->name, trunk_ref->trunk->name); 06759 snprintf(hint, sizeof(hint), "SLA:%s", exten); 06760 /* Extension for this line button 06761 * exten => station1_line1,1,SLAStation(station1_line1) */ 06762 if (ast_add_extension2(context, 0 /* don't replace */, exten, 1, 06763 NULL, NULL, slastation_app, ast_strdup(exten), ast_free_ptr, sla_registrar)) { 06764 ast_log(LOG_ERROR, "Failed to automatically create extension " 06765 "for trunk '%s'!\n", station->name); 06766 destroy_station(station); 06767 return -1; 06768 } 06769 /* Hint for this line button 06770 * exten => station1_line1,hint,SLA:station1_line1 */ 06771 if (ast_add_extension2(context, 0 /* don't replace */, exten, PRIORITY_HINT, 06772 NULL, NULL, hint, NULL, NULL, sla_registrar)) { 06773 ast_log(LOG_ERROR, "Failed to automatically create hint " 06774 "for trunk '%s'!\n", station->name); 06775 destroy_station(station); 06776 return -1; 06777 } 06778 } 06779 AST_RWLIST_UNLOCK(&sla_trunks); 06780 } 06781 06782 AST_RWLIST_WRLOCK(&sla_stations); 06783 AST_RWLIST_INSERT_TAIL(&sla_stations, station, entry); 06784 AST_RWLIST_UNLOCK(&sla_stations); 06785 06786 return 0; 06787 }
static int sla_build_trunk | ( | struct ast_config * | cfg, | |
const char * | cat | |||
) | [static] |
Definition at line 6552 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().
06553 { 06554 struct sla_trunk *trunk; 06555 struct ast_variable *var; 06556 const char *dev; 06557 06558 if (!(dev = ast_variable_retrieve(cfg, cat, "device"))) { 06559 ast_log(LOG_ERROR, "SLA Trunk '%s' defined with no device!\n", cat); 06560 return -1; 06561 } 06562 06563 if (sla_check_device(dev)) { 06564 ast_log(LOG_ERROR, "SLA Trunk '%s' define with invalid device '%s'!\n", 06565 cat, dev); 06566 return -1; 06567 } 06568 06569 if (!(trunk = ast_calloc_with_stringfields(1, struct sla_trunk, 32))) { 06570 return -1; 06571 } 06572 06573 ast_string_field_set(trunk, name, cat); 06574 ast_string_field_set(trunk, device, dev); 06575 06576 for (var = ast_variable_browse(cfg, cat); var; var = var->next) { 06577 if (!strcasecmp(var->name, "autocontext")) 06578 ast_string_field_set(trunk, autocontext, var->value); 06579 else if (!strcasecmp(var->name, "ringtimeout")) { 06580 if (sscanf(var->value, "%30u", &trunk->ring_timeout) != 1) { 06581 ast_log(LOG_WARNING, "Invalid ringtimeout '%s' specified for trunk '%s'\n", 06582 var->value, trunk->name); 06583 trunk->ring_timeout = 0; 06584 } 06585 } else if (!strcasecmp(var->name, "barge")) 06586 trunk->barge_disabled = ast_false(var->value); 06587 else if (!strcasecmp(var->name, "hold")) { 06588 if (!strcasecmp(var->value, "private")) 06589 trunk->hold_access = SLA_HOLD_PRIVATE; 06590 else if (!strcasecmp(var->value, "open")) 06591 trunk->hold_access = SLA_HOLD_OPEN; 06592 else { 06593 ast_log(LOG_WARNING, "Invalid value '%s' for hold on trunk %s\n", 06594 var->value, trunk->name); 06595 } 06596 } else if (strcasecmp(var->name, "type") && strcasecmp(var->name, "device")) { 06597 ast_log(LOG_ERROR, "Invalid option '%s' specified at line %d of %s!\n", 06598 var->name, var->lineno, SLA_CONFIG_FILE); 06599 } 06600 } 06601 06602 if (!ast_strlen_zero(trunk->autocontext)) { 06603 struct ast_context *context; 06604 context = ast_context_find_or_create(NULL, NULL, trunk->autocontext, sla_registrar); 06605 if (!context) { 06606 ast_log(LOG_ERROR, "Failed to automatically find or create " 06607 "context '%s' for SLA!\n", trunk->autocontext); 06608 destroy_trunk(trunk); 06609 return -1; 06610 } 06611 if (ast_add_extension2(context, 0 /* don't replace */, "s", 1, 06612 NULL, NULL, slatrunk_app, ast_strdup(trunk->name), ast_free_ptr, sla_registrar)) { 06613 ast_log(LOG_ERROR, "Failed to automatically create extension " 06614 "for trunk '%s'!\n", trunk->name); 06615 destroy_trunk(trunk); 06616 return -1; 06617 } 06618 } 06619 06620 AST_RWLIST_WRLOCK(&sla_trunks); 06621 AST_RWLIST_INSERT_TAIL(&sla_trunks, trunk, entry); 06622 AST_RWLIST_UNLOCK(&sla_trunks); 06623 06624 return 0; 06625 }
static int sla_calc_station_delays | ( | unsigned int * | timeout | ) | [static] |
Calculate the ring delay for a station.
Definition at line 5799 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().
05800 { 05801 struct sla_station *station; 05802 int res = 0; 05803 05804 AST_LIST_TRAVERSE(&sla_stations, station, entry) { 05805 struct sla_ringing_trunk *ringing_trunk; 05806 int time_left; 05807 05808 /* Ignore stations already ringing */ 05809 if (sla_check_ringing_station(station)) 05810 continue; 05811 05812 /* Ignore stations already on a call */ 05813 if (sla_check_inuse_station(station)) 05814 continue; 05815 05816 /* Ignore stations that don't have one of their trunks ringing */ 05817 if (!(ringing_trunk = sla_choose_ringing_trunk(station, NULL, 0))) 05818 continue; 05819 05820 if ((time_left = sla_check_station_delay(station, ringing_trunk)) == INT_MAX) 05821 continue; 05822 05823 /* If there is no time left, then the station needs to start ringing. 05824 * Return non-zero so that an event will be queued up an event to 05825 * make that happen. */ 05826 if (time_left <= 0) { 05827 res = 1; 05828 continue; 05829 } 05830 05831 if (time_left < *timeout) 05832 *timeout = time_left; 05833 } 05834 05835 return res; 05836 }
static int sla_calc_station_timeouts | ( | unsigned int * | timeout | ) | [static] |
Process station ring timeouts.
Definition at line 5716 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().
05717 { 05718 struct sla_ringing_trunk *ringing_trunk; 05719 struct sla_ringing_station *ringing_station; 05720 int res = 0; 05721 05722 AST_LIST_TRAVERSE_SAFE_BEGIN(&sla.ringing_stations, ringing_station, entry) { 05723 unsigned int ring_timeout = 0; 05724 int time_elapsed, time_left = INT_MAX, final_trunk_time_left = INT_MIN; 05725 struct sla_trunk_ref *trunk_ref; 05726 05727 /* If there are any ring timeouts specified for a specific trunk 05728 * on the station, then use the highest per-trunk ring timeout. 05729 * Otherwise, use the ring timeout set for the entire station. */ 05730 AST_LIST_TRAVERSE(&ringing_station->station->trunks, trunk_ref, entry) { 05731 struct sla_station_ref *station_ref; 05732 int trunk_time_elapsed, trunk_time_left; 05733 05734 AST_LIST_TRAVERSE(&sla.ringing_trunks, ringing_trunk, entry) { 05735 if (ringing_trunk->trunk == trunk_ref->trunk) 05736 break; 05737 } 05738 if (!ringing_trunk) 05739 continue; 05740 05741 /* If there is a trunk that is ringing without a timeout, then the 05742 * only timeout that could matter is a global station ring timeout. */ 05743 if (!trunk_ref->ring_timeout) 05744 break; 05745 05746 /* This trunk on this station is ringing and has a timeout. 05747 * However, make sure this trunk isn't still ringing from a 05748 * previous timeout. If so, don't consider it. */ 05749 AST_LIST_TRAVERSE(&ringing_trunk->timed_out_stations, station_ref, entry) { 05750 if (station_ref->station == ringing_station->station) 05751 break; 05752 } 05753 if (station_ref) 05754 continue; 05755 05756 trunk_time_elapsed = ast_tvdiff_ms(ast_tvnow(), ringing_trunk->ring_begin); 05757 trunk_time_left = (trunk_ref->ring_timeout * 1000) - trunk_time_elapsed; 05758 if (trunk_time_left > final_trunk_time_left) 05759 final_trunk_time_left = trunk_time_left; 05760 } 05761 05762 /* No timeout was found for ringing trunks, and no timeout for the entire station */ 05763 if (final_trunk_time_left == INT_MIN && !ringing_station->station->ring_timeout) 05764 continue; 05765 05766 /* Compute how much time is left for a global station timeout */ 05767 if (ringing_station->station->ring_timeout) { 05768 ring_timeout = ringing_station->station->ring_timeout; 05769 time_elapsed = ast_tvdiff_ms(ast_tvnow(), ringing_station->ring_begin); 05770 time_left = (ring_timeout * 1000) - time_elapsed; 05771 } 05772 05773 /* If the time left based on the per-trunk timeouts is smaller than the 05774 * global station ring timeout, use that. */ 05775 if (final_trunk_time_left > INT_MIN && final_trunk_time_left < time_left) 05776 time_left = final_trunk_time_left; 05777 05778 /* If there is no time left, the station needs to stop ringing */ 05779 if (time_left <= 0) { 05780 AST_LIST_REMOVE_CURRENT(entry); 05781 sla_stop_ringing_station(ringing_station, SLA_STATION_HANGUP_TIMEOUT); 05782 res = 1; 05783 continue; 05784 } 05785 05786 /* There is still some time left for this station to ring, so save that 05787 * timeout if it is the first event scheduled to occur */ 05788 if (time_left < *timeout) 05789 *timeout = time_left; 05790 } 05791 AST_LIST_TRAVERSE_SAFE_END; 05792 05793 return res; 05794 }
static int sla_calc_trunk_timeouts | ( | unsigned int * | timeout | ) | [static] |
Process trunk ring timeouts.
Definition at line 5686 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().
05687 { 05688 struct sla_ringing_trunk *ringing_trunk; 05689 int res = 0; 05690 05691 AST_LIST_TRAVERSE_SAFE_BEGIN(&sla.ringing_trunks, ringing_trunk, entry) { 05692 int time_left, time_elapsed; 05693 if (!ringing_trunk->trunk->ring_timeout) 05694 continue; 05695 time_elapsed = ast_tvdiff_ms(ast_tvnow(), ringing_trunk->ring_begin); 05696 time_left = (ringing_trunk->trunk->ring_timeout * 1000) - time_elapsed; 05697 if (time_left <= 0) { 05698 pbx_builtin_setvar_helper(ringing_trunk->trunk->chan, "SLATRUNK_STATUS", "RINGTIMEOUT"); 05699 AST_LIST_REMOVE_CURRENT(entry); 05700 sla_stop_ringing_trunk(ringing_trunk); 05701 res = 1; 05702 continue; 05703 } 05704 if (time_left < *timeout) 05705 *timeout = time_left; 05706 } 05707 AST_LIST_TRAVERSE_SAFE_END; 05708 05709 return res; 05710 }
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 5155 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().
05157 { 05158 struct sla_station *station; 05159 struct sla_trunk_ref *trunk_ref; 05160 05161 AST_LIST_TRAVERSE(&sla_stations, station, entry) { 05162 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) { 05163 if (trunk_ref->trunk != trunk || (inactive_only ? trunk_ref->chan : 0) 05164 || trunk_ref == exclude) 05165 continue; 05166 trunk_ref->state = state; 05167 ast_devstate_changed(sla_state_to_devstate(state), 05168 "SLA:%s_%s", station->name, trunk->name); 05169 break; 05170 } 05171 } 05172 }
static int sla_check_device | ( | const char * | device | ) | [static] |
Definition at line 6539 of file app_meetme.c.
References ast_strdupa, ast_strlen_zero(), and strsep().
Referenced by sla_build_trunk().
06540 { 06541 char *tech, *tech_data; 06542 06543 tech_data = ast_strdupa(device); 06544 tech = strsep(&tech_data, "/"); 06545 06546 if (ast_strlen_zero(tech) || ast_strlen_zero(tech_data)) 06547 return -1; 06548 06549 return 0; 06550 }
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 5435 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().
05436 { 05437 struct sla_failed_station *failed_station; 05438 int res = 0; 05439 05440 AST_LIST_TRAVERSE_SAFE_BEGIN(&sla.failed_stations, failed_station, entry) { 05441 if (station != failed_station->station) 05442 continue; 05443 if (ast_tvdiff_ms(ast_tvnow(), failed_station->last_try) > 1000) { 05444 AST_LIST_REMOVE_CURRENT(entry); 05445 ast_free(failed_station); 05446 break; 05447 } 05448 res = 1; 05449 } 05450 AST_LIST_TRAVERSE_SAFE_END 05451 05452 return res; 05453 }
static int sla_check_inuse_station | ( | const struct sla_station * | station | ) | [static] |
Check to see if a station is in use.
Definition at line 5520 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().
05521 { 05522 struct sla_trunk_ref *trunk_ref; 05523 05524 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) { 05525 if (trunk_ref->chan) 05526 return 1; 05527 } 05528 05529 return 0; 05530 }
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 5878 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().
05879 { 05880 struct sla_station *station; 05881 struct sla_trunk *trunk; 05882 05883 ast_mutex_lock(&sla.lock); 05884 05885 if (!AST_LIST_EMPTY(&sla.event_q) || !AST_LIST_EMPTY(&sla.ringing_trunks) 05886 || !AST_LIST_EMPTY(&sla.ringing_stations)) { 05887 ast_mutex_unlock(&sla.lock); 05888 return; 05889 } 05890 05891 AST_RWLIST_RDLOCK(&sla_stations); 05892 AST_RWLIST_TRAVERSE(&sla_stations, station, entry) { 05893 if (station->ref_count) 05894 break; 05895 } 05896 AST_RWLIST_UNLOCK(&sla_stations); 05897 if (station) { 05898 ast_mutex_unlock(&sla.lock); 05899 return; 05900 } 05901 05902 AST_RWLIST_RDLOCK(&sla_trunks); 05903 AST_RWLIST_TRAVERSE(&sla_trunks, trunk, entry) { 05904 if (trunk->ref_count) 05905 break; 05906 } 05907 AST_RWLIST_UNLOCK(&sla_trunks); 05908 if (trunk) { 05909 ast_mutex_unlock(&sla.lock); 05910 return; 05911 } 05912 05913 /* yay */ 05914 sla_load_config(1); 05915 sla.reload = 0; 05916 05917 ast_mutex_unlock(&sla.lock); 05918 }
static int sla_check_ringing_station | ( | const struct sla_station * | station | ) | [static] |
Check to see if this station is already ringing.
Definition at line 5420 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().
05421 { 05422 struct sla_ringing_station *ringing_station; 05423 05424 AST_LIST_TRAVERSE(&sla.ringing_stations, ringing_station, entry) { 05425 if (station == ringing_station->station) 05426 return 1; 05427 } 05428 05429 return 0; 05430 }
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 5550 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().
05552 { 05553 struct sla_trunk_ref *trunk_ref; 05554 unsigned int delay = UINT_MAX; 05555 int time_left, time_elapsed; 05556 05557 if (!ringing_trunk) 05558 ringing_trunk = sla_choose_ringing_trunk(station, &trunk_ref, 0); 05559 else 05560 trunk_ref = sla_find_trunk_ref(station, ringing_trunk->trunk); 05561 05562 if (!ringing_trunk || !trunk_ref) 05563 return delay; 05564 05565 /* If this station has a ring delay specific to the highest priority 05566 * ringing trunk, use that. Otherwise, use the ring delay specified 05567 * globally for the station. */ 05568 delay = trunk_ref->ring_delay; 05569 if (!delay) 05570 delay = station->ring_delay; 05571 if (!delay) 05572 return INT_MAX; 05573 05574 time_elapsed = ast_tvdiff_ms(ast_tvnow(), ringing_trunk->ring_begin); 05575 time_left = (delay * 1000) - time_elapsed; 05576 05577 return time_left; 05578 }
static int sla_check_station_hold_access | ( | const struct sla_trunk * | trunk, | |
const struct sla_station * | station | |||
) | [static] |
Definition at line 5060 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().
05062 { 05063 struct sla_station_ref *station_ref; 05064 struct sla_trunk_ref *trunk_ref; 05065 05066 /* For each station that has this call on hold, check for private hold. */ 05067 AST_LIST_TRAVERSE(&trunk->stations, station_ref, entry) { 05068 AST_LIST_TRAVERSE(&station_ref->station->trunks, trunk_ref, entry) { 05069 if (trunk_ref->trunk != trunk || station_ref->station == station) 05070 continue; 05071 if (trunk_ref->state == SLA_TRUNK_STATE_ONHOLD_BYME && 05072 station_ref->station->hold_access == SLA_HOLD_PRIVATE) 05073 return 1; 05074 return 0; 05075 } 05076 } 05077 05078 return 0; 05079 }
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 5291 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().
05293 { 05294 struct sla_station_ref *timed_out_station; 05295 05296 AST_LIST_TRAVERSE(&ringing_trunk->timed_out_stations, timed_out_station, entry) { 05297 if (station == timed_out_station->station) 05298 return 1; 05299 } 05300 05301 return 0; 05302 }
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 6102 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().
06103 { 06104 struct sla_trunk_ref *trunk_ref = NULL; 06105 06106 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) { 06107 if (trunk_ref->state == SLA_TRUNK_STATE_IDLE) 06108 break; 06109 } 06110 06111 return trunk_ref; 06112 }
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 5312 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().
05314 { 05315 struct sla_trunk_ref *s_trunk_ref; 05316 struct sla_ringing_trunk *ringing_trunk = NULL; 05317 05318 AST_LIST_TRAVERSE(&station->trunks, s_trunk_ref, entry) { 05319 AST_LIST_TRAVERSE_SAFE_BEGIN(&sla.ringing_trunks, ringing_trunk, entry) { 05320 /* Make sure this is the trunk we're looking for */ 05321 if (s_trunk_ref->trunk != ringing_trunk->trunk) 05322 continue; 05323 05324 /* This trunk on the station is ringing. But, make sure this station 05325 * didn't already time out while this trunk was ringing. */ 05326 if (sla_check_timed_out_station(ringing_trunk, station)) 05327 continue; 05328 05329 if (rm) 05330 AST_LIST_REMOVE_CURRENT(entry); 05331 05332 if (trunk_ref) 05333 *trunk_ref = s_trunk_ref; 05334 05335 break; 05336 } 05337 AST_LIST_TRAVERSE_SAFE_END; 05338 05339 if (ringing_trunk) 05340 break; 05341 } 05342 05343 return ringing_trunk; 05344 }
static struct sla_ringing_station* sla_create_ringing_station | ( | struct sla_station * | station | ) | [static] |
Definition at line 5125 of file app_meetme.c.
References ast_calloc, ast_tvnow(), and sla_ringing_station::station.
Referenced by sla_ring_station().
05126 { 05127 struct sla_ringing_station *ringing_station; 05128 05129 if (!(ringing_station = ast_calloc(1, sizeof(*ringing_station)))) 05130 return NULL; 05131 05132 ringing_station->station = station; 05133 ringing_station->ring_begin = ast_tvnow(); 05134 05135 return ringing_station; 05136 }
static struct sla_station_ref* sla_create_station_ref | ( | struct sla_station * | station | ) | [static] |
Definition at line 5113 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().
05114 { 05115 struct sla_station_ref *station_ref; 05116 05117 if (!(station_ref = ast_calloc(1, sizeof(*station_ref)))) 05118 return NULL; 05119 05120 station_ref->station = station; 05121 05122 return station_ref; 05123 }
static void sla_destroy | ( | void | ) | [static] |
Definition at line 6509 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().
06510 { 06511 struct sla_trunk *trunk; 06512 struct sla_station *station; 06513 06514 AST_RWLIST_WRLOCK(&sla_trunks); 06515 while ((trunk = AST_RWLIST_REMOVE_HEAD(&sla_trunks, entry))) 06516 destroy_trunk(trunk); 06517 AST_RWLIST_UNLOCK(&sla_trunks); 06518 06519 AST_RWLIST_WRLOCK(&sla_stations); 06520 while ((station = AST_RWLIST_REMOVE_HEAD(&sla_stations, entry))) 06521 destroy_station(station); 06522 AST_RWLIST_UNLOCK(&sla_stations); 06523 06524 if (sla.thread != AST_PTHREADT_NULL) { 06525 ast_mutex_lock(&sla.lock); 06526 sla.stop = 1; 06527 ast_cond_signal(&sla.cond); 06528 ast_mutex_unlock(&sla.lock); 06529 pthread_join(sla.thread, NULL); 06530 } 06531 06532 /* Drop any created contexts from the dialplan */ 06533 ast_context_destroy(NULL, sla_registrar); 06534 06535 ast_mutex_destroy(&sla.lock); 06536 ast_cond_destroy(&sla.cond); 06537 }
static void sla_dial_state_callback | ( | struct ast_dial * | dial | ) | [static] |
Definition at line 5283 of file app_meetme.c.
References SLA_EVENT_DIAL_STATE, and sla_queue_event().
Referenced by sla_ring_station().
05284 { 05285 sla_queue_event(SLA_EVENT_DIAL_STATE); 05286 }
static struct sla_station* sla_find_station | ( | const char * | name | ) | [static] |
Find an SLA station by name.
Definition at line 5048 of file app_meetme.c.
References AST_RWLIST_TRAVERSE, sla_station::entry, and sla_station::name.
Referenced by sla_station_exec().
05049 { 05050 struct sla_station *station = NULL; 05051 05052 AST_RWLIST_TRAVERSE(&sla_stations, station, entry) { 05053 if (!strcasecmp(station->name, name)) 05054 break; 05055 } 05056 05057 return station; 05058 }
static struct sla_trunk* sla_find_trunk | ( | const char * | name | ) | [static] |
Find an SLA trunk by name.
Definition at line 5033 of file app_meetme.c.
References AST_RWLIST_TRAVERSE, sla_trunk::entry, and sla_trunk::name.
Referenced by sla_trunk_exec().
05034 { 05035 struct sla_trunk *trunk = NULL; 05036 05037 AST_RWLIST_TRAVERSE(&sla_trunks, trunk, entry) { 05038 if (!strcasecmp(trunk->name, name)) 05039 break; 05040 } 05041 05042 return trunk; 05043 }
static struct sla_trunk_ref* sla_find_trunk_ref | ( | const struct sla_station * | station, | |
const struct sla_trunk * | trunk | |||
) | [static] |
Definition at line 5532 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().
05534 { 05535 struct sla_trunk_ref *trunk_ref = NULL; 05536 05537 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) { 05538 if (trunk_ref->trunk == trunk) 05539 break; 05540 } 05541 05542 return trunk_ref; 05543 }
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 5088 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().
05090 { 05091 struct sla_trunk_ref *trunk_ref = NULL; 05092 05093 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) { 05094 if (strcasecmp(trunk_ref->trunk->name, name)) 05095 continue; 05096 05097 if ( (trunk_ref->trunk->barge_disabled 05098 && trunk_ref->state == SLA_TRUNK_STATE_UP) || 05099 (trunk_ref->trunk->hold_stations 05100 && trunk_ref->trunk->hold_access == SLA_HOLD_PRIVATE 05101 && trunk_ref->state != SLA_TRUNK_STATE_ONHOLD_BYME) || 05102 sla_check_station_hold_access(trunk_ref->trunk, station) ) 05103 { 05104 trunk_ref = NULL; 05105 } 05106 05107 break; 05108 } 05109 05110 return trunk_ref; 05111 }
static void sla_handle_dial_state_event | ( | void | ) | [static] |
Definition at line 5346 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().
05347 { 05348 struct sla_ringing_station *ringing_station; 05349 05350 AST_LIST_TRAVERSE_SAFE_BEGIN(&sla.ringing_stations, ringing_station, entry) { 05351 struct sla_trunk_ref *s_trunk_ref = NULL; 05352 struct sla_ringing_trunk *ringing_trunk = NULL; 05353 struct run_station_args args; 05354 enum ast_dial_result dial_res; 05355 pthread_t dont_care; 05356 ast_mutex_t cond_lock; 05357 ast_cond_t cond; 05358 05359 switch ((dial_res = ast_dial_state(ringing_station->station->dial))) { 05360 case AST_DIAL_RESULT_HANGUP: 05361 case AST_DIAL_RESULT_INVALID: 05362 case AST_DIAL_RESULT_FAILED: 05363 case AST_DIAL_RESULT_TIMEOUT: 05364 case AST_DIAL_RESULT_UNANSWERED: 05365 AST_LIST_REMOVE_CURRENT(entry); 05366 sla_stop_ringing_station(ringing_station, SLA_STATION_HANGUP_NORMAL); 05367 break; 05368 case AST_DIAL_RESULT_ANSWERED: 05369 AST_LIST_REMOVE_CURRENT(entry); 05370 /* Find the appropriate trunk to answer. */ 05371 ast_mutex_lock(&sla.lock); 05372 ringing_trunk = sla_choose_ringing_trunk(ringing_station->station, &s_trunk_ref, 1); 05373 ast_mutex_unlock(&sla.lock); 05374 if (!ringing_trunk) { 05375 ast_debug(1, "Found no ringing trunk for station '%s' to answer!\n", ringing_station->station->name); 05376 break; 05377 } 05378 /* Track the channel that answered this trunk */ 05379 s_trunk_ref->chan = ast_dial_answered(ringing_station->station->dial); 05380 /* Actually answer the trunk */ 05381 answer_trunk_chan(ringing_trunk->trunk->chan); 05382 sla_change_trunk_state(ringing_trunk->trunk, SLA_TRUNK_STATE_UP, ALL_TRUNK_REFS, NULL); 05383 /* Now, start a thread that will connect this station to the trunk. The rest of 05384 * the code here sets up the thread and ensures that it is able to save the arguments 05385 * before they are no longer valid since they are allocated on the stack. */ 05386 args.trunk_ref = s_trunk_ref; 05387 args.station = ringing_station->station; 05388 args.cond = &cond; 05389 args.cond_lock = &cond_lock; 05390 ast_free(ringing_trunk); 05391 ast_free(ringing_station); 05392 ast_mutex_init(&cond_lock); 05393 ast_cond_init(&cond, NULL); 05394 ast_mutex_lock(&cond_lock); 05395 ast_pthread_create_detached_background(&dont_care, NULL, run_station, &args); 05396 ast_cond_wait(&cond, &cond_lock); 05397 ast_mutex_unlock(&cond_lock); 05398 ast_mutex_destroy(&cond_lock); 05399 ast_cond_destroy(&cond); 05400 break; 05401 case AST_DIAL_RESULT_TRYING: 05402 case AST_DIAL_RESULT_RINGING: 05403 case AST_DIAL_RESULT_PROGRESS: 05404 case AST_DIAL_RESULT_PROCEEDING: 05405 break; 05406 } 05407 if (dial_res == AST_DIAL_RESULT_ANSWERED) { 05408 /* Queue up reprocessing ringing trunks, and then ringing stations again */ 05409 sla_queue_event(SLA_EVENT_RINGING_TRUNK); 05410 sla_queue_event(SLA_EVENT_DIAL_STATE); 05411 break; 05412 } 05413 } 05414 AST_LIST_TRAVERSE_SAFE_END; 05415 }
static void sla_handle_hold_event | ( | struct sla_event * | event | ) | [static] |
Definition at line 5662 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().
05663 { 05664 ast_atomic_fetchadd_int((int *) &event->trunk_ref->trunk->hold_stations, 1); 05665 event->trunk_ref->state = SLA_TRUNK_STATE_ONHOLD_BYME; 05666 ast_devstate_changed(AST_DEVICE_ONHOLD, "SLA:%s_%s", 05667 event->station->name, event->trunk_ref->trunk->name); 05668 sla_change_trunk_state(event->trunk_ref->trunk, SLA_TRUNK_STATE_ONHOLD, 05669 INACTIVE_TRUNK_REFS, event->trunk_ref); 05670 05671 if (event->trunk_ref->trunk->active_stations == 1) { 05672 /* The station putting it on hold is the only one on the call, so start 05673 * Music on hold to the trunk. */ 05674 event->trunk_ref->trunk->on_hold = 1; 05675 ast_indicate(event->trunk_ref->trunk->chan, AST_CONTROL_HOLD); 05676 } 05677 05678 ast_softhangup(event->trunk_ref->chan, AST_SOFTHANGUP_DEV); 05679 event->trunk_ref->chan = NULL; 05680 }
static void sla_handle_ringing_trunk_event | ( | void | ) | [static] |
Definition at line 5652 of file app_meetme.c.
References ast_mutex_lock, ast_mutex_unlock, sla, sla_hangup_stations(), and sla_ring_stations().
Referenced by sla_thread().
05653 { 05654 ast_mutex_lock(&sla.lock); 05655 sla_ring_stations(); 05656 ast_mutex_unlock(&sla.lock); 05657 05658 /* Find stations that shouldn't be ringing anymore. */ 05659 sla_hangup_stations(); 05660 }
static void sla_hangup_stations | ( | void | ) | [static] |
Definition at line 5624 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().
05625 { 05626 struct sla_trunk_ref *trunk_ref; 05627 struct sla_ringing_station *ringing_station; 05628 05629 AST_LIST_TRAVERSE_SAFE_BEGIN(&sla.ringing_stations, ringing_station, entry) { 05630 AST_LIST_TRAVERSE(&ringing_station->station->trunks, trunk_ref, entry) { 05631 struct sla_ringing_trunk *ringing_trunk; 05632 ast_mutex_lock(&sla.lock); 05633 AST_LIST_TRAVERSE(&sla.ringing_trunks, ringing_trunk, entry) { 05634 if (trunk_ref->trunk == ringing_trunk->trunk) 05635 break; 05636 } 05637 ast_mutex_unlock(&sla.lock); 05638 if (ringing_trunk) 05639 break; 05640 } 05641 if (!trunk_ref) { 05642 AST_LIST_REMOVE_CURRENT(entry); 05643 ast_dial_join(ringing_station->station->dial); 05644 ast_dial_destroy(ringing_station->station->dial); 05645 ringing_station->station->dial = NULL; 05646 ast_free(ringing_station); 05647 } 05648 } 05649 AST_LIST_TRAVERSE_SAFE_END 05650 }
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 6789 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_flags, 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().
06790 { 06791 struct ast_config *cfg; 06792 struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; 06793 const char *cat = NULL; 06794 int res = 0; 06795 const char *val; 06796 06797 if (!reload) { 06798 ast_mutex_init(&sla.lock); 06799 ast_cond_init(&sla.cond, NULL); 06800 } 06801 06802 if (!(cfg = ast_config_load(SLA_CONFIG_FILE, config_flags))) { 06803 return 0; /* Treat no config as normal */ 06804 } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) { 06805 return 0; 06806 } else if (cfg == CONFIG_STATUS_FILEINVALID) { 06807 ast_log(LOG_ERROR, "Config file " SLA_CONFIG_FILE " is in an invalid format. Aborting.\n"); 06808 return 0; 06809 } 06810 06811 if (reload) { 06812 struct sla_station *station; 06813 struct sla_trunk *trunk; 06814 06815 /* We need to actually delete the previous versions of trunks and stations now */ 06816 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&sla_stations, station, entry) { 06817 AST_RWLIST_REMOVE_CURRENT(entry); 06818 ast_free(station); 06819 } 06820 AST_RWLIST_TRAVERSE_SAFE_END; 06821 06822 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&sla_trunks, trunk, entry) { 06823 AST_RWLIST_REMOVE_CURRENT(entry); 06824 ast_free(trunk); 06825 } 06826 AST_RWLIST_TRAVERSE_SAFE_END; 06827 } 06828 06829 if ((val = ast_variable_retrieve(cfg, "general", "attemptcallerid"))) 06830 sla.attempt_callerid = ast_true(val); 06831 06832 while ((cat = ast_category_browse(cfg, cat)) && !res) { 06833 const char *type; 06834 if (!strcasecmp(cat, "general")) 06835 continue; 06836 if (!(type = ast_variable_retrieve(cfg, cat, "type"))) { 06837 ast_log(LOG_WARNING, "Invalid entry in %s defined with no type!\n", 06838 SLA_CONFIG_FILE); 06839 continue; 06840 } 06841 if (!strcasecmp(type, "trunk")) 06842 res = sla_build_trunk(cfg, cat); 06843 else if (!strcasecmp(type, "station")) 06844 res = sla_build_station(cfg, cat); 06845 else { 06846 ast_log(LOG_WARNING, "Entry in %s defined with invalid type '%s'!\n", 06847 SLA_CONFIG_FILE, type); 06848 } 06849 } 06850 06851 ast_config_destroy(cfg); 06852 06853 /* Even if we don't have any stations, we may after a reload and we need to 06854 * be able to process the SLA_EVENT_RELOAD event in that case */ 06855 if (sla.thread == AST_PTHREADT_NULL && (!AST_LIST_EMPTY(&sla_stations) || !AST_LIST_EMPTY(&sla_trunks))) { 06856 ast_pthread_create(&sla.thread, NULL, sla_thread, NULL); 06857 } 06858 06859 return res; 06860 }
static int sla_process_timers | ( | struct timespec * | ts | ) | [static] |
Calculate the time until the next known event.
Definition at line 5840 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().
05841 { 05842 unsigned int timeout = UINT_MAX; 05843 struct timeval wait; 05844 unsigned int change_made = 0; 05845 05846 /* Check for ring timeouts on ringing trunks */ 05847 if (sla_calc_trunk_timeouts(&timeout)) 05848 change_made = 1; 05849 05850 /* Check for ring timeouts on ringing stations */ 05851 if (sla_calc_station_timeouts(&timeout)) 05852 change_made = 1; 05853 05854 /* Check for station ring delays */ 05855 if (sla_calc_station_delays(&timeout)) 05856 change_made = 1; 05857 05858 /* queue reprocessing of ringing trunks */ 05859 if (change_made) 05860 sla_queue_event_nolock(SLA_EVENT_RINGING_TRUNK); 05861 05862 /* No timeout */ 05863 if (timeout == UINT_MAX) 05864 return 0; 05865 05866 if (ts) { 05867 wait = ast_tvadd(ast_tvnow(), ast_samp2tv(timeout, 1000)); 05868 ts->tv_sec = wait.tv_sec; 05869 ts->tv_nsec = wait.tv_usec * 1000; 05870 } 05871 05872 return 1; 05873 }
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 5458 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().
05459 { 05460 char *tech, *tech_data; 05461 struct ast_dial *dial; 05462 struct sla_ringing_station *ringing_station; 05463 enum ast_dial_result res; 05464 int caller_is_saved; 05465 struct ast_party_caller caller; 05466 05467 if (!(dial = ast_dial_create())) 05468 return -1; 05469 05470 ast_dial_set_state_callback(dial, sla_dial_state_callback); 05471 tech_data = ast_strdupa(station->device); 05472 tech = strsep(&tech_data, "/"); 05473 05474 if (ast_dial_append(dial, tech, tech_data) == -1) { 05475 ast_dial_destroy(dial); 05476 return -1; 05477 } 05478 05479 /* Do we need to save off the caller ID data? */ 05480 caller_is_saved = 0; 05481 if (!sla.attempt_callerid) { 05482 caller_is_saved = 1; 05483 caller = ringing_trunk->trunk->chan->caller; 05484 ast_party_caller_init(&ringing_trunk->trunk->chan->caller); 05485 } 05486 05487 res = ast_dial_run(dial, ringing_trunk->trunk->chan, 1); 05488 05489 /* Restore saved caller ID */ 05490 if (caller_is_saved) { 05491 ast_party_caller_free(&ringing_trunk->trunk->chan->caller); 05492 ringing_trunk->trunk->chan->caller = caller; 05493 } 05494 05495 if (res != AST_DIAL_RESULT_TRYING) { 05496 struct sla_failed_station *failed_station; 05497 ast_dial_destroy(dial); 05498 if (!(failed_station = ast_calloc(1, sizeof(*failed_station)))) 05499 return -1; 05500 failed_station->station = station; 05501 failed_station->last_try = ast_tvnow(); 05502 AST_LIST_INSERT_HEAD(&sla.failed_stations, failed_station, entry); 05503 return -1; 05504 } 05505 if (!(ringing_station = sla_create_ringing_station(station))) { 05506 ast_dial_join(dial); 05507 ast_dial_destroy(dial); 05508 return -1; 05509 } 05510 05511 station->dial = dial; 05512 05513 AST_LIST_INSERT_HEAD(&sla.ringing_stations, ringing_station, entry); 05514 05515 return 0; 05516 }
static void sla_ring_stations | ( | void | ) | [static] |
Ring stations based on current set of ringing trunks.
Definition at line 5583 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().
05584 { 05585 struct sla_station_ref *station_ref; 05586 struct sla_ringing_trunk *ringing_trunk; 05587 05588 /* Make sure that every station that uses at least one of the ringing 05589 * trunks, is ringing. */ 05590 AST_LIST_TRAVERSE(&sla.ringing_trunks, ringing_trunk, entry) { 05591 AST_LIST_TRAVERSE(&ringing_trunk->trunk->stations, station_ref, entry) { 05592 int time_left; 05593 05594 /* Is this station already ringing? */ 05595 if (sla_check_ringing_station(station_ref->station)) 05596 continue; 05597 05598 /* Is this station already in a call? */ 05599 if (sla_check_inuse_station(station_ref->station)) 05600 continue; 05601 05602 /* Did we fail to dial this station earlier? If so, has it been 05603 * a minute since we tried? */ 05604 if (sla_check_failed_station(station_ref->station)) 05605 continue; 05606 05607 /* If this station already timed out while this trunk was ringing, 05608 * do not dial it again for this ringing trunk. */ 05609 if (sla_check_timed_out_station(ringing_trunk, station_ref->station)) 05610 continue; 05611 05612 /* Check for a ring delay in progress */ 05613 time_left = sla_check_station_delay(station_ref->station, ringing_trunk); 05614 if (time_left != INT_MAX && time_left > 0) 05615 continue; 05616 05617 /* It is time to make this station begin to ring. Do it! */ 05618 sla_ring_station(ringing_trunk, station_ref->station); 05619 } 05620 } 05621 /* Now, all of the stations that should be ringing, are ringing. */ 05622 }
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 6433 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().
06434 { 06435 char *buf, *station_name, *trunk_name; 06436 struct sla_station *station; 06437 struct sla_trunk_ref *trunk_ref; 06438 enum ast_device_state res = AST_DEVICE_INVALID; 06439 06440 trunk_name = buf = ast_strdupa(data); 06441 station_name = strsep(&trunk_name, "_"); 06442 06443 AST_RWLIST_RDLOCK(&sla_stations); 06444 AST_LIST_TRAVERSE(&sla_stations, station, entry) { 06445 if (strcasecmp(station_name, station->name)) 06446 continue; 06447 AST_RWLIST_RDLOCK(&sla_trunks); 06448 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) { 06449 if (!strcasecmp(trunk_name, trunk_ref->trunk->name)) 06450 break; 06451 } 06452 if (!trunk_ref) { 06453 AST_RWLIST_UNLOCK(&sla_trunks); 06454 break; 06455 } 06456 res = sla_state_to_devstate(trunk_ref->state); 06457 AST_RWLIST_UNLOCK(&sla_trunks); 06458 } 06459 AST_RWLIST_UNLOCK(&sla_stations); 06460 06461 if (res == AST_DEVICE_INVALID) { 06462 ast_log(LOG_ERROR, "Could not determine state for trunk %s on station %s!\n", 06463 trunk_name, station_name); 06464 } 06465 06466 return res; 06467 }
static enum ast_device_state sla_state_to_devstate | ( | enum sla_trunk_state | state | ) | [static] |
Definition at line 5138 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().
05139 { 05140 switch (state) { 05141 case SLA_TRUNK_STATE_IDLE: 05142 return AST_DEVICE_NOT_INUSE; 05143 case SLA_TRUNK_STATE_RINGING: 05144 return AST_DEVICE_RINGING; 05145 case SLA_TRUNK_STATE_UP: 05146 return AST_DEVICE_INUSE; 05147 case SLA_TRUNK_STATE_ONHOLD: 05148 case SLA_TRUNK_STATE_ONHOLD_BYME: 05149 return AST_DEVICE_ONHOLD; 05150 } 05151 05152 return AST_DEVICE_UNKNOWN; 05153 }
static int sla_station_exec | ( | struct ast_channel * | chan, | |
const char * | data | |||
) | [static] |
Definition at line 6114 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().
06115 { 06116 char *station_name, *trunk_name; 06117 struct sla_station *station; 06118 struct sla_trunk_ref *trunk_ref = NULL; 06119 char conf_name[MAX_CONFNUM]; 06120 struct ast_flags64 conf_flags = { 0 }; 06121 struct ast_conference *conf; 06122 06123 if (ast_strlen_zero(data)) { 06124 ast_log(LOG_WARNING, "Invalid Arguments to SLAStation!\n"); 06125 pbx_builtin_setvar_helper(chan, "SLASTATION_STATUS", "FAILURE"); 06126 return 0; 06127 } 06128 06129 trunk_name = ast_strdupa(data); 06130 station_name = strsep(&trunk_name, "_"); 06131 06132 if (ast_strlen_zero(station_name)) { 06133 ast_log(LOG_WARNING, "Invalid Arguments to SLAStation!\n"); 06134 pbx_builtin_setvar_helper(chan, "SLASTATION_STATUS", "FAILURE"); 06135 return 0; 06136 } 06137 06138 AST_RWLIST_RDLOCK(&sla_stations); 06139 station = sla_find_station(station_name); 06140 if (station) 06141 ast_atomic_fetchadd_int((int *) &station->ref_count, 1); 06142 AST_RWLIST_UNLOCK(&sla_stations); 06143 06144 if (!station) { 06145 ast_log(LOG_WARNING, "Station '%s' not found!\n", station_name); 06146 pbx_builtin_setvar_helper(chan, "SLASTATION_STATUS", "FAILURE"); 06147 sla_queue_event(SLA_EVENT_CHECK_RELOAD); 06148 return 0; 06149 } 06150 06151 AST_RWLIST_RDLOCK(&sla_trunks); 06152 if (!ast_strlen_zero(trunk_name)) { 06153 trunk_ref = sla_find_trunk_ref_byname(station, trunk_name); 06154 } else 06155 trunk_ref = sla_choose_idle_trunk(station); 06156 AST_RWLIST_UNLOCK(&sla_trunks); 06157 06158 if (!trunk_ref) { 06159 if (ast_strlen_zero(trunk_name)) 06160 ast_log(LOG_NOTICE, "No trunks available for call.\n"); 06161 else { 06162 ast_log(LOG_NOTICE, "Can't join existing call on trunk " 06163 "'%s' due to access controls.\n", trunk_name); 06164 } 06165 pbx_builtin_setvar_helper(chan, "SLASTATION_STATUS", "CONGESTION"); 06166 ast_atomic_fetchadd_int((int *) &station->ref_count, -1); 06167 sla_queue_event(SLA_EVENT_CHECK_RELOAD); 06168 return 0; 06169 } 06170 06171 if (trunk_ref->state == SLA_TRUNK_STATE_ONHOLD_BYME) { 06172 if (ast_atomic_dec_and_test((int *) &trunk_ref->trunk->hold_stations) == 1) 06173 sla_change_trunk_state(trunk_ref->trunk, SLA_TRUNK_STATE_UP, ALL_TRUNK_REFS, NULL); 06174 else { 06175 trunk_ref->state = SLA_TRUNK_STATE_UP; 06176 ast_devstate_changed(AST_DEVICE_INUSE, 06177 "SLA:%s_%s", station->name, trunk_ref->trunk->name); 06178 } 06179 } else if (trunk_ref->state == SLA_TRUNK_STATE_RINGING) { 06180 struct sla_ringing_trunk *ringing_trunk; 06181 06182 ast_mutex_lock(&sla.lock); 06183 AST_LIST_TRAVERSE_SAFE_BEGIN(&sla.ringing_trunks, ringing_trunk, entry) { 06184 if (ringing_trunk->trunk == trunk_ref->trunk) { 06185 AST_LIST_REMOVE_CURRENT(entry); 06186 break; 06187 } 06188 } 06189 AST_LIST_TRAVERSE_SAFE_END 06190 ast_mutex_unlock(&sla.lock); 06191 06192 if (ringing_trunk) { 06193 answer_trunk_chan(ringing_trunk->trunk->chan); 06194 sla_change_trunk_state(ringing_trunk->trunk, SLA_TRUNK_STATE_UP, ALL_TRUNK_REFS, NULL); 06195 06196 free(ringing_trunk); 06197 06198 /* Queue up reprocessing ringing trunks, and then ringing stations again */ 06199 sla_queue_event(SLA_EVENT_RINGING_TRUNK); 06200 sla_queue_event(SLA_EVENT_DIAL_STATE); 06201 } 06202 } 06203 06204 trunk_ref->chan = chan; 06205 06206 if (!trunk_ref->trunk->chan) { 06207 ast_mutex_t cond_lock; 06208 ast_cond_t cond; 06209 pthread_t dont_care; 06210 struct dial_trunk_args args = { 06211 .trunk_ref = trunk_ref, 06212 .station = station, 06213 .cond_lock = &cond_lock, 06214 .cond = &cond, 06215 }; 06216 sla_change_trunk_state(trunk_ref->trunk, SLA_TRUNK_STATE_UP, ALL_TRUNK_REFS, NULL); 06217 /* Create a thread to dial the trunk and dump it into the conference. 06218 * However, we want to wait until the trunk has been dialed and the 06219 * conference is created before continuing on here. */ 06220 ast_autoservice_start(chan); 06221 ast_mutex_init(&cond_lock); 06222 ast_cond_init(&cond, NULL); 06223 ast_mutex_lock(&cond_lock); 06224 ast_pthread_create_detached_background(&dont_care, NULL, dial_trunk, &args); 06225 ast_cond_wait(&cond, &cond_lock); 06226 ast_mutex_unlock(&cond_lock); 06227 ast_mutex_destroy(&cond_lock); 06228 ast_cond_destroy(&cond); 06229 ast_autoservice_stop(chan); 06230 if (!trunk_ref->trunk->chan) { 06231 ast_debug(1, "Trunk didn't get created. chan: %lx\n", (long) trunk_ref->trunk->chan); 06232 pbx_builtin_setvar_helper(chan, "SLASTATION_STATUS", "CONGESTION"); 06233 sla_change_trunk_state(trunk_ref->trunk, SLA_TRUNK_STATE_IDLE, ALL_TRUNK_REFS, NULL); 06234 trunk_ref->chan = NULL; 06235 ast_atomic_fetchadd_int((int *) &station->ref_count, -1); 06236 sla_queue_event(SLA_EVENT_CHECK_RELOAD); 06237 return 0; 06238 } 06239 } 06240 06241 if (ast_atomic_fetchadd_int((int *) &trunk_ref->trunk->active_stations, 1) == 0 && 06242 trunk_ref->trunk->on_hold) { 06243 trunk_ref->trunk->on_hold = 0; 06244 ast_indicate(trunk_ref->trunk->chan, AST_CONTROL_UNHOLD); 06245 sla_change_trunk_state(trunk_ref->trunk, SLA_TRUNK_STATE_UP, ALL_TRUNK_REFS, NULL); 06246 } 06247 06248 snprintf(conf_name, sizeof(conf_name), "SLA_%s", trunk_ref->trunk->name); 06249 ast_set_flag64(&conf_flags, 06250 CONFFLAG_QUIET | CONFFLAG_MARKEDEXIT | CONFFLAG_PASS_DTMF | CONFFLAG_SLA_STATION); 06251 ast_answer(chan); 06252 conf = build_conf(conf_name, "", "", 0, 0, 1, chan, NULL); 06253 if (conf) { 06254 conf_run(chan, conf, &conf_flags, NULL); 06255 dispose_conf(conf); 06256 conf = NULL; 06257 } 06258 trunk_ref->chan = NULL; 06259 if (ast_atomic_dec_and_test((int *) &trunk_ref->trunk->active_stations) && 06260 trunk_ref->state != SLA_TRUNK_STATE_ONHOLD_BYME) { 06261 strncat(conf_name, ",K", sizeof(conf_name) - strlen(conf_name) - 1); 06262 admin_exec(NULL, conf_name); 06263 trunk_ref->trunk->hold_stations = 0; 06264 sla_change_trunk_state(trunk_ref->trunk, SLA_TRUNK_STATE_IDLE, ALL_TRUNK_REFS, NULL); 06265 } 06266 06267 pbx_builtin_setvar_helper(chan, "SLASTATION_STATUS", "SUCCESS"); 06268 06269 ast_atomic_fetchadd_int((int *) &station->ref_count, -1); 06270 sla_queue_event(SLA_EVENT_CHECK_RELOAD); 06271 06272 return 0; 06273 }
static void sla_stop_ringing_station | ( | struct sla_ringing_station * | ringing_station, | |
enum sla_station_hangup | hangup | |||
) | [static] |
Definition at line 5248 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().
05250 { 05251 struct sla_ringing_trunk *ringing_trunk; 05252 struct sla_trunk_ref *trunk_ref; 05253 struct sla_station_ref *station_ref; 05254 05255 ast_dial_join(ringing_station->station->dial); 05256 ast_dial_destroy(ringing_station->station->dial); 05257 ringing_station->station->dial = NULL; 05258 05259 if (hangup == SLA_STATION_HANGUP_NORMAL) 05260 goto done; 05261 05262 /* If the station is being hung up because of a timeout, then add it to the 05263 * list of timed out stations on each of the ringing trunks. This is so 05264 * that when doing further processing to figure out which stations should be 05265 * ringing, which trunk to answer, determining timeouts, etc., we know which 05266 * ringing trunks we should ignore. */ 05267 AST_LIST_TRAVERSE(&sla.ringing_trunks, ringing_trunk, entry) { 05268 AST_LIST_TRAVERSE(&ringing_station->station->trunks, trunk_ref, entry) { 05269 if (ringing_trunk->trunk == trunk_ref->trunk) 05270 break; 05271 } 05272 if (!trunk_ref) 05273 continue; 05274 if (!(station_ref = sla_create_station_ref(ringing_station->station))) 05275 continue; 05276 AST_LIST_INSERT_TAIL(&ringing_trunk->timed_out_stations, station_ref, entry); 05277 } 05278 05279 done: 05280 ast_free(ringing_station); 05281 }
static void sla_stop_ringing_trunk | ( | struct sla_ringing_trunk * | ringing_trunk | ) | [static] |
Definition at line 5233 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().
05234 { 05235 char buf[80]; 05236 struct sla_station_ref *station_ref; 05237 05238 snprintf(buf, sizeof(buf), "SLA_%s,K", ringing_trunk->trunk->name); 05239 admin_exec(NULL, buf); 05240 sla_change_trunk_state(ringing_trunk->trunk, SLA_TRUNK_STATE_IDLE, ALL_TRUNK_REFS, NULL); 05241 05242 while ((station_ref = AST_LIST_REMOVE_HEAD(&ringing_trunk->timed_out_stations, entry))) 05243 ast_free(station_ref); 05244 05245 ast_free(ringing_trunk); 05246 }
static void* sla_thread | ( | void * | data | ) | [static] |
Definition at line 5920 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().
05921 { 05922 struct sla_failed_station *failed_station; 05923 struct sla_ringing_station *ringing_station; 05924 05925 ast_mutex_lock(&sla.lock); 05926 05927 while (!sla.stop) { 05928 struct sla_event *event; 05929 struct timespec ts = { 0, }; 05930 unsigned int have_timeout = 0; 05931 05932 if (AST_LIST_EMPTY(&sla.event_q)) { 05933 if ((have_timeout = sla_process_timers(&ts))) 05934 ast_cond_timedwait(&sla.cond, &sla.lock, &ts); 05935 else 05936 ast_cond_wait(&sla.cond, &sla.lock); 05937 if (sla.stop) 05938 break; 05939 } 05940 05941 if (have_timeout) 05942 sla_process_timers(NULL); 05943 05944 while ((event = AST_LIST_REMOVE_HEAD(&sla.event_q, entry))) { 05945 ast_mutex_unlock(&sla.lock); 05946 switch (event->type) { 05947 case SLA_EVENT_HOLD: 05948 sla_handle_hold_event(event); 05949 break; 05950 case SLA_EVENT_DIAL_STATE: 05951 sla_handle_dial_state_event(); 05952 break; 05953 case SLA_EVENT_RINGING_TRUNK: 05954 sla_handle_ringing_trunk_event(); 05955 break; 05956 case SLA_EVENT_RELOAD: 05957 sla.reload = 1; 05958 case SLA_EVENT_CHECK_RELOAD: 05959 break; 05960 } 05961 ast_free(event); 05962 ast_mutex_lock(&sla.lock); 05963 } 05964 05965 if (sla.reload) { 05966 sla_check_reload(); 05967 } 05968 } 05969 05970 ast_mutex_unlock(&sla.lock); 05971 05972 while ((ringing_station = AST_LIST_REMOVE_HEAD(&sla.ringing_stations, entry))) 05973 ast_free(ringing_station); 05974 05975 while ((failed_station = AST_LIST_REMOVE_HEAD(&sla.failed_stations, entry))) 05976 ast_free(failed_station); 05977 05978 return NULL; 05979 }
static int sla_trunk_exec | ( | struct ast_channel * | chan, | |
const char * | data | |||
) | [static] |
Definition at line 6321 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().
06322 { 06323 char conf_name[MAX_CONFNUM]; 06324 struct ast_conference *conf; 06325 struct ast_flags64 conf_flags = { 0 }; 06326 struct sla_trunk *trunk; 06327 struct sla_ringing_trunk *ringing_trunk; 06328 AST_DECLARE_APP_ARGS(args, 06329 AST_APP_ARG(trunk_name); 06330 AST_APP_ARG(options); 06331 ); 06332 char *opts[SLA_TRUNK_OPT_ARG_ARRAY_SIZE] = { NULL, }; 06333 struct ast_flags opt_flags = { 0 }; 06334 char *parse; 06335 06336 if (ast_strlen_zero(data)) { 06337 ast_log(LOG_ERROR, "The SLATrunk application requires an argument, the trunk name\n"); 06338 return -1; 06339 } 06340 06341 parse = ast_strdupa(data); 06342 AST_STANDARD_APP_ARGS(args, parse); 06343 if (args.argc == 2) { 06344 if (ast_app_parse_options(sla_trunk_opts, &opt_flags, opts, args.options)) { 06345 ast_log(LOG_ERROR, "Error parsing options for SLATrunk\n"); 06346 return -1; 06347 } 06348 } 06349 06350 AST_RWLIST_RDLOCK(&sla_trunks); 06351 trunk = sla_find_trunk(args.trunk_name); 06352 if (trunk) 06353 ast_atomic_fetchadd_int((int *) &trunk->ref_count, 1); 06354 AST_RWLIST_UNLOCK(&sla_trunks); 06355 06356 if (!trunk) { 06357 ast_log(LOG_ERROR, "SLA Trunk '%s' not found!\n", args.trunk_name); 06358 pbx_builtin_setvar_helper(chan, "SLATRUNK_STATUS", "FAILURE"); 06359 sla_queue_event(SLA_EVENT_CHECK_RELOAD); 06360 return 0; 06361 } 06362 06363 if (trunk->chan) { 06364 ast_log(LOG_ERROR, "Call came in on %s, but the trunk is already in use!\n", 06365 args.trunk_name); 06366 pbx_builtin_setvar_helper(chan, "SLATRUNK_STATUS", "FAILURE"); 06367 ast_atomic_fetchadd_int((int *) &trunk->ref_count, -1); 06368 sla_queue_event(SLA_EVENT_CHECK_RELOAD); 06369 return 0; 06370 } 06371 06372 trunk->chan = chan; 06373 06374 if (!(ringing_trunk = queue_ringing_trunk(trunk))) { 06375 pbx_builtin_setvar_helper(chan, "SLATRUNK_STATUS", "FAILURE"); 06376 ast_atomic_fetchadd_int((int *) &trunk->ref_count, -1); 06377 sla_queue_event(SLA_EVENT_CHECK_RELOAD); 06378 return 0; 06379 } 06380 06381 snprintf(conf_name, sizeof(conf_name), "SLA_%s", args.trunk_name); 06382 conf = build_conf(conf_name, "", "", 1, 1, 1, chan, NULL); 06383 if (!conf) { 06384 pbx_builtin_setvar_helper(chan, "SLATRUNK_STATUS", "FAILURE"); 06385 ast_atomic_fetchadd_int((int *) &trunk->ref_count, -1); 06386 sla_queue_event(SLA_EVENT_CHECK_RELOAD); 06387 return 0; 06388 } 06389 ast_set_flag64(&conf_flags, 06390 CONFFLAG_QUIET | CONFFLAG_MARKEDEXIT | CONFFLAG_MARKEDUSER | CONFFLAG_PASS_DTMF | CONFFLAG_NO_AUDIO_UNTIL_UP); 06391 06392 if (ast_test_flag(&opt_flags, SLA_TRUNK_OPT_MOH)) { 06393 ast_indicate(chan, -1); 06394 ast_set_flag64(&conf_flags, CONFFLAG_MOH); 06395 } else 06396 ast_indicate(chan, AST_CONTROL_RINGING); 06397 06398 conf_run(chan, conf, &conf_flags, opts); 06399 dispose_conf(conf); 06400 conf = NULL; 06401 trunk->chan = NULL; 06402 trunk->on_hold = 0; 06403 06404 sla_change_trunk_state(trunk, SLA_TRUNK_STATE_IDLE, ALL_TRUNK_REFS, NULL); 06405 06406 if (!pbx_builtin_getvar_helper(chan, "SLATRUNK_STATUS")) 06407 pbx_builtin_setvar_helper(chan, "SLATRUNK_STATUS", "SUCCESS"); 06408 06409 /* Remove the entry from the list of ringing trunks if it is still there. */ 06410 ast_mutex_lock(&sla.lock); 06411 AST_LIST_TRAVERSE_SAFE_BEGIN(&sla.ringing_trunks, ringing_trunk, entry) { 06412 if (ringing_trunk->trunk == trunk) { 06413 AST_LIST_REMOVE_CURRENT(entry); 06414 break; 06415 } 06416 } 06417 AST_LIST_TRAVERSE_SAFE_END; 06418 ast_mutex_unlock(&sla.lock); 06419 if (ringing_trunk) { 06420 ast_free(ringing_trunk); 06421 pbx_builtin_setvar_helper(chan, "SLATRUNK_STATUS", "UNANSWERED"); 06422 /* Queue reprocessing of ringing trunks to make stations stop ringing 06423 * that shouldn't be ringing after this trunk stopped. */ 06424 sla_queue_event(SLA_EVENT_RINGING_TRUNK); 06425 } 06426 06427 ast_atomic_fetchadd_int((int *) &trunk->ref_count, -1); 06428 sla_queue_event(SLA_EVENT_CHECK_RELOAD); 06429 06430 return 0; 06431 }
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 7129 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().
07130 { 07131 int res = 0; 07132 07133 ast_cli_unregister_multiple(cli_meetme, ARRAY_LEN(cli_meetme)); 07134 res = ast_manager_unregister("MeetmeMute"); 07135 res |= ast_manager_unregister("MeetmeUnmute"); 07136 res |= ast_manager_unregister("MeetmeList"); 07137 res |= ast_unregister_application(app4); 07138 res |= ast_unregister_application(app3); 07139 res |= ast_unregister_application(app2); 07140 res |= ast_unregister_application(app); 07141 res |= ast_unregister_application(slastation_app); 07142 res |= ast_unregister_application(slatrunk_app); 07143 07144 #ifdef TEST_FRAMEWORK 07145 AST_TEST_UNREGISTER(test_meetme_data_provider); 07146 #endif 07147 ast_data_unregister(NULL); 07148 07149 ast_devstate_prov_del("Meetme"); 07150 ast_devstate_prov_del("SLA"); 07151 07152 sla_destroy(); 07153 07154 res |= ast_custom_function_unregister(&meetme_info_acf); 07155 ast_unload_realtime("meetme"); 07156 07157 return res; 07158 }
static int user_add_provider_cb | ( | void * | obj, | |
void * | arg, | |||
int | flags | |||
) | [static] |
Definition at line 6980 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().
06981 { 06982 struct ast_data *data_meetme_user; 06983 struct ast_data *data_meetme_user_channel; 06984 struct ast_data *data_meetme_user_volume; 06985 06986 struct ast_conf_user *user = obj; 06987 struct ast_data *data_meetme_users = arg; 06988 06989 data_meetme_user = ast_data_add_node(data_meetme_users, "user"); 06990 if (!data_meetme_user) { 06991 return 0; 06992 } 06993 /* user structure */ 06994 ast_data_add_structure(ast_conf_user, data_meetme_user, user); 06995 06996 /* user's channel */ 06997 data_meetme_user_channel = ast_data_add_node(data_meetme_user, "channel"); 06998 if (!data_meetme_user_channel) { 06999 return 0; 07000 } 07001 07002 ast_channel_data_add_structure(data_meetme_user_channel, user->chan, 1); 07003 07004 /* volume structure */ 07005 data_meetme_user_volume = ast_data_add_node(data_meetme_user, "listen-volume"); 07006 if (!data_meetme_user_volume) { 07007 return 0; 07008 } 07009 ast_data_add_int(data_meetme_user_volume, "desired", user->listen.desired); 07010 ast_data_add_int(data_meetme_user_volume, "actual", user->listen.actual); 07011 07012 data_meetme_user_volume = ast_data_add_node(data_meetme_user, "talk-volume"); 07013 if (!data_meetme_user_volume) { 07014 return 0; 07015 } 07016 ast_data_add_int(data_meetme_user_volume, "desired", user->talk.desired); 07017 ast_data_add_int(data_meetme_user_volume, "actual", user->talk.actual); 07018 07019 return 0; 07020 }
static int user_chan_cb | ( | void * | obj, | |
void * | args, | |||
int | flags | |||
) | [static] |
Definition at line 4511 of file app_meetme.c.
References CMP_MATCH, CMP_STOP, and user.
Referenced by channel_admin_exec().
04512 { 04513 struct ast_conf_user *user = obj; 04514 const char *channel = args; 04515 04516 if (!strcmp(user->chan->name, channel)) { 04517 return (CMP_MATCH | CMP_STOP); 04518 } 04519 04520 return 0; 04521 }
static int user_listen_voldown_cb | ( | void * | obj, | |
void * | unused, | |||
int | flags | |||
) | [static] |
Definition at line 4483 of file app_meetme.c.
References tweak_listen_volume(), and user.
Referenced by admin_exec().
04484 { 04485 struct ast_conf_user *user = obj; 04486 tweak_listen_volume(user, VOL_DOWN); 04487 return 0; 04488 }
static int user_listen_volup_cb | ( | void * | obj, | |
void * | unused, | |||
int | flags | |||
) | [static] |
Definition at line 4476 of file app_meetme.c.
References tweak_listen_volume(), user, and VOL_UP.
Referenced by admin_exec().
04477 { 04478 struct ast_conf_user *user = obj; 04479 tweak_listen_volume(user, VOL_UP); 04480 return 0; 04481 }
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 4504 of file app_meetme.c.
References reset_volumes(), and user.
Referenced by admin_exec().
04505 { 04506 struct ast_conf_user *user = obj; 04507 reset_volumes(user); 04508 return 0; 04509 }
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 4497 of file app_meetme.c.
References tweak_talk_volume(), and user.
Referenced by admin_exec().
04498 { 04499 struct ast_conf_user *user = obj; 04500 tweak_talk_volume(user, VOL_DOWN); 04501 return 0; 04502 }
static int user_talk_volup_cb | ( | void * | obj, | |
void * | unused, | |||
int | flags | |||
) | [static] |
Definition at line 4490 of file app_meetme.c.
References tweak_talk_volume(), user, and VOL_UP.
Referenced by admin_exec().
04491 { 04492 struct ast_conf_user *user = obj; 04493 tweak_talk_volume(user, VOL_UP); 04494 return 0; 04495 }
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 = "88eaa8f5c1bd988bedd71113385e0886" , .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_DEVSTATE_PROVIDER, } [static] |
Definition at line 7204 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 7204 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(), node_lookup(), 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(), load_rpt_vars(), reload(), rpt_master(), smdi_message_wait(), unload_module(), and write_cdr().
struct ast_data_handler meetme_data_provider [static] |
Initial value:
{ .version = AST_DATA_HANDLER_VERSION, .get = meetme_data_provider_get }
Definition at line 7060 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 7065 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 6931 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(), handle_minivm_reload(), reload(), and rpt_do_reload().
struct { ... } ringing_stations |
struct { ... } ringing_trunks |
int rt_log_members [static] |
Log participant count to the RealTime backend
Definition at line 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(), 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().