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