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