#include "asterisk.h"
#include <sys/ioctl.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/astobj.h"
#include "asterisk/astobj2.h"
#include "asterisk/devicestate.h"
#include "asterisk/dial.h"
#include "asterisk/causes.h"
#include "asterisk/paths.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 | 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 | 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_DELAYDETECTENDTALK 1000 |
#define | MEETME_DELAYDETECTTALK 300 |
#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_ARRAY_SIZE = 5 } |
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 | 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, void *data) |
The MeetMeadmin application. | |
static void * | announce_thread (void *data) |
static void | answer_trunk_chan (struct ast_channel *chan) |
static struct ast_conference * | build_conf (char *confno, char *pin, char *pinadmin, int make, int dynamic, int refcount, const struct ast_channel *chan) |
Find or create a conference. | |
static int | can_write (struct ast_channel *chan, int confflags) |
static int | careful_write (int fd, unsigned char *data, int len, int block) |
static int | channel_admin_exec (struct ast_channel *chan, void *data) |
static char * | complete_meetmecmd (const char *line, const char *word, int pos, int state) |
static int | conf_exec (struct ast_channel *chan, void *data) |
The meetme() application. | |
static void | conf_flush (int fd, struct ast_channel *chan) |
static int | conf_free (struct ast_conference *conf) |
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, int confflags, char *optargs[]) |
static void | conf_start_moh (struct ast_channel *chan, const char *musicclass) |
static int | count_exec (struct ast_channel *chan, void *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) |
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_flags *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_flags *confflags, char *optargs[], int *too_early) |
static struct ast_conf_user * | find_user (struct ast_conference *conf, char *callerident) |
static const char * | get_announce_filename (enum announcetypes type) |
static 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 | 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 void * | run_station (void *data) |
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 | 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 remove) |
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, void *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, void *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) |
Variables | |
static struct ast_module_info | __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .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 = "068e67f60f50dd9ee86464c05884a49d" , .load = load_module, .unload = unload_module, .reload = reload, } |
static const char * | app = "MeetMe" |
static const char * | app2 = "MeetMeCount" |
static const char * | app3 = "MeetMeAdmin" |
static const char * | app4 = "MeetMeChannelAdmin" |
static const struct ast_module_info * | ast_module_info = &__mod_info |
static int | audio_buffers |
static struct ast_cli_entry | cli_meetme [] |
static unsigned int | conf_map [1024] = {0, } |
static const char * | descrip |
static const char * | descrip2 |
static const char * | descrip3 |
static const char * | descrip4 |
static int | earlyalert |
static int | endalert |
static int | fuzzystart |
static char const | gain_map [] |
static char | mandescr_meetmelist [] |
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 }, [ '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 * | slastation_app = "SLAStation" |
static const char * | slastation_desc |
static const char * | slastation_synopsis = "Shared Line Appearance Station" |
static const char * | slatrunk_app = "SLATrunk" |
static const char * | slatrunk_desc |
static const char * | slatrunk_synopsis = "Shared Line Appearance Trunk" |
static const char * | synopsis = "MeetMe conference bridge" |
static const char * | synopsis2 = "MeetMe participant count" |
static const char * | synopsis3 = "MeetMe conference Administration" |
static const char * | synopsis4 = "MeetMe conference Administration (channel specific)" |
(SLA) Russell Bryant <russell@digium.com>
Definition in file app_meetme.c.
#define AST_FRAME_BITS 32 |
Definition at line 88 of file app_meetme.c.
Referenced by conf_free(), conf_run(), and recordthread().
#define CONF_SIZE 320 |
Definition at line 107 of file app_meetme.c.
#define CONFIG_FILE_NAME "meetme.conf" |
Definition at line 68 of file app_meetme.c.
Referenced by 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 75 of file app_meetme.c.
Referenced by append_date(), build_radius_record(), find_conf_realtime(), get_date(), manager_log(), pgsql_log(), prepare_cb(), and sqlite_log().
#define DEFAULT_AUDIO_BUFFERS 32 |
each buffer is 20ms, so this is 640ms total
Definition at line 72 of file app_meetme.c.
Referenced by load_config_meetme().
#define MAX_CONFNUM 80 |
Definition at line 361 of file app_meetme.c.
Referenced by conf_exec(), dial_trunk(), run_station(), sla_station_exec(), and sla_trunk_exec().
#define MAX_PIN 80 |
#define MC_DATA_FORMAT "%-12.12s %4.4d %4.4s %02d:%02d:%02d %-8s %-6s\n" |
Referenced by meetme_cmd().
#define MC_HEADER_FORMAT "%-14s %-14s %-10s %-8s %-8s %-6s\n" |
Referenced by meetme_cmd().
#define MEETME_DELAYDETECTENDTALK 1000 |
#define MEETME_DELAYDETECTTALK 300 |
#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 77 of file app_meetme.c.
00077 { 00078 ADMINFLAG_MUTED = (1 << 1), /*!< User is muted */ 00079 ADMINFLAG_SELFMUTED = (1 << 2), /*!< User muted self */ 00080 ADMINFLAG_KICKME = (1 << 3), /*!< User has been kicked */ 00081 /*! User has requested to speak */ 00082 ADMINFLAG_T_REQUEST = (1 << 4), 00083 };
anonymous enum |
Definition at line 109 of file app_meetme.c.
00109 { 00110 /*! user has admin access on the conference */ 00111 CONFFLAG_ADMIN = (1 << 0), 00112 /*! If set the user can only receive audio from the conference */ 00113 CONFFLAG_MONITOR = (1 << 1), 00114 /*! If set asterisk will exit conference when key defined in p() option is pressed */ 00115 CONFFLAG_KEYEXIT = (1 << 2), 00116 /*! If set asterisk will provide a menu to the user when '*' is pressed */ 00117 CONFFLAG_STARMENU = (1 << 3), 00118 /*! If set the use can only send audio to the conference */ 00119 CONFFLAG_TALKER = (1 << 4), 00120 /*! If set there will be no enter or leave sounds */ 00121 CONFFLAG_QUIET = (1 << 5), 00122 /*! If set, when user joins the conference, they will be told the number 00123 * of users that are already in */ 00124 CONFFLAG_ANNOUNCEUSERCOUNT = (1 << 6), 00125 /*! Set to run AGI Script in Background */ 00126 CONFFLAG_AGI = (1 << 7), 00127 /*! Set to have music on hold when user is alone in conference */ 00128 CONFFLAG_MOH = (1 << 8), 00129 /*! If set the MeetMe will return if all marked with this flag left */ 00130 CONFFLAG_MARKEDEXIT = (1 << 9), 00131 /*! If set, the MeetMe will wait until a marked user enters */ 00132 CONFFLAG_WAITMARKED = (1 << 10), 00133 /*! If set, the MeetMe will exit to the specified context */ 00134 CONFFLAG_EXIT_CONTEXT = (1 << 11), 00135 /*! If set, the user will be marked */ 00136 CONFFLAG_MARKEDUSER = (1 << 12), 00137 /*! If set, user will be ask record name on entry of conference */ 00138 CONFFLAG_INTROUSER = (1 << 13), 00139 /*! If set, the MeetMe will be recorded */ 00140 CONFFLAG_RECORDCONF = (1<< 14), 00141 /*! If set, the user will be monitored if the user is talking or not */ 00142 CONFFLAG_MONITORTALKER = (1 << 15), 00143 CONFFLAG_DYNAMIC = (1 << 16), 00144 CONFFLAG_DYNAMICPIN = (1 << 17), 00145 CONFFLAG_EMPTY = (1 << 18), 00146 CONFFLAG_EMPTYNOPIN = (1 << 19), 00147 CONFFLAG_ALWAYSPROMPT = (1 << 20), 00148 /*! If set, treat talking users as muted users */ 00149 CONFFLAG_OPTIMIZETALKER = (1 << 21), 00150 /*! If set, won't speak the extra prompt when the first person 00151 * enters the conference */ 00152 CONFFLAG_NOONLYPERSON = (1 << 22), 00153 /*! If set, user will be asked to record name on entry of conference 00154 * without review */ 00155 CONFFLAG_INTROUSERNOREVIEW = (1 << 23), 00156 /*! If set, the user will be initially self-muted */ 00157 CONFFLAG_STARTMUTED = (1 << 24), 00158 /*! Pass DTMF through the conference */ 00159 CONFFLAG_PASS_DTMF = (1 << 25), 00160 CONFFLAG_SLA_STATION = (1 << 26), 00161 CONFFLAG_SLA_TRUNK = (1 << 27), 00162 /*! If set, the user should continue in the dialplan if kicked out */ 00163 CONFFLAG_KICK_CONTINUE = (1 << 28), 00164 CONFFLAG_DURATION_STOP = (1 << 29), 00165 CONFFLAG_DURATION_LIMIT = (1 << 30), 00166 /*! Do not write any audio to this channel until the state is up. */ 00167 CONFFLAG_NO_AUDIO_UNTIL_UP = (1 << 31), 00168 };
anonymous enum |
OPT_ARG_WAITMARKED | |
OPT_ARG_EXITKEYS | |
OPT_ARG_DURATION_STOP | |
OPT_ARG_DURATION_LIMIT | |
OPT_ARG_MOH_CLASS | |
OPT_ARG_ARRAY_SIZE |
Definition at line 170 of file app_meetme.c.
00170 { 00171 OPT_ARG_WAITMARKED = 0, 00172 OPT_ARG_EXITKEYS = 1, 00173 OPT_ARG_DURATION_STOP = 2, 00174 OPT_ARG_DURATION_LIMIT = 3, 00175 OPT_ARG_MOH_CLASS = 4, 00176 OPT_ARG_ARRAY_SIZE = 5, 00177 };
anonymous enum |
anonymous enum |
Definition at line 5158 of file app_meetme.c.
05158 { 05159 SLA_TRUNK_OPT_ARG_MOH_CLASS = 0, 05160 SLA_TRUNK_OPT_ARG_ARRAY_SIZE = 1, 05161 };
enum announcetypes |
enum entrance_sound |
enum recording_state |
Definition at line 100 of file app_meetme.c.
00100 { 00101 MEETME_RECORD_OFF, 00102 MEETME_RECORD_STARTED, 00103 MEETME_RECORD_ACTIVE, 00104 MEETME_RECORD_TERMINATE 00105 };
enum sla_event_type |
Event types that can be queued up for the SLA thread.
Definition at line 554 of file app_meetme.c.
00554 { 00555 /*! A station has put the call on hold */ 00556 SLA_EVENT_HOLD, 00557 /*! The state of a dial has changed */ 00558 SLA_EVENT_DIAL_STATE, 00559 /*! The state of a ringing trunk has changed */ 00560 SLA_EVENT_RINGING_TRUNK, 00561 /*! A reload of configuration has been requested */ 00562 SLA_EVENT_RELOAD, 00563 /*! Poke the SLA thread so it can check if it can perform a reload */ 00564 SLA_EVENT_CHECK_RELOAD, 00565 };
enum sla_hold_access |
Definition at line 464 of file app_meetme.c.
00464 { 00465 /*! This means that any station can put it on hold, and any station 00466 * can retrieve the call from hold. */ 00467 SLA_HOLD_OPEN, 00468 /*! This means that only the station that put the call on hold may 00469 * retrieve it from hold. */ 00470 SLA_HOLD_PRIVATE, 00471 };
enum sla_station_hangup |
Definition at line 591 of file app_meetme.c.
00591 { 00592 SLA_STATION_HANGUP_NORMAL, 00593 SLA_STATION_HANGUP_TIMEOUT, 00594 };
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 456 of file app_meetme.c.
00456 { 00457 SLA_TRUNK_STATE_IDLE, 00458 SLA_TRUNK_STATE_RINGING, 00459 SLA_TRUNK_STATE_UP, 00460 SLA_TRUNK_STATE_ONHOLD, 00461 SLA_TRUNK_STATE_ONHOLD_BYME, 00462 };
enum sla_which_trunk_refs |
Definition at line 451 of file app_meetme.c.
00451 { 00452 ALL_TRUNK_REFS, 00453 INACTIVE_TRUNK_REFS, 00454 };
enum volume_action |
static void __reg_module | ( | void | ) | [static] |
Definition at line 5766 of file app_meetme.c.
static void __unreg_module | ( | void | ) | [static] |
Definition at line 5766 of file app_meetme.c.
static int action_meetmelist | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 3663 of file app_meetme.c.
References ADMINFLAG_MUTED, ADMINFLAG_SELFMUTED, AST_LIST_EMPTY, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_strlen_zero(), astman_append(), astman_get_header(), astman_send_error(), astman_send_listack(), CONFFLAG_ADMIN, CONFFLAG_MARKEDUSER, CONFFLAG_MONITOR, CONFFLAG_TALKER, ast_conference::confno, ast_conf_user::list, s, S_OR, total, user, and ast_conference::userlist.
Referenced by load_module().
03664 { 03665 const char *actionid = astman_get_header(m, "ActionID"); 03666 const char *conference = astman_get_header(m, "Conference"); 03667 char idText[80] = ""; 03668 struct ast_conference *cnf; 03669 struct ast_conf_user *user; 03670 int total = 0; 03671 03672 if (!ast_strlen_zero(actionid)) 03673 snprintf(idText, sizeof(idText), "ActionID: %s\r\n", actionid); 03674 03675 if (AST_LIST_EMPTY(&confs)) { 03676 astman_send_error(s, m, "No active conferences."); 03677 return 0; 03678 } 03679 03680 astman_send_listack(s, m, "Meetme user list will follow", "start"); 03681 03682 /* Find the right conference */ 03683 AST_LIST_LOCK(&confs); 03684 AST_LIST_TRAVERSE(&confs, cnf, list) { 03685 /* If we ask for one particular, and this isn't it, skip it */ 03686 if (!ast_strlen_zero(conference) && strcmp(cnf->confno, conference)) 03687 continue; 03688 03689 /* Show all the users */ 03690 AST_LIST_TRAVERSE(&cnf->userlist, user, list) { 03691 total++; 03692 astman_append(s, 03693 "Event: MeetmeList\r\n" 03694 "%s" 03695 "Conference: %s\r\n" 03696 "UserNumber: %d\r\n" 03697 "CallerIDNum: %s\r\n" 03698 "CallerIDName: %s\r\n" 03699 "Channel: %s\r\n" 03700 "Admin: %s\r\n" 03701 "Role: %s\r\n" 03702 "MarkedUser: %s\r\n" 03703 "Muted: %s\r\n" 03704 "Talking: %s\r\n" 03705 "\r\n", 03706 idText, 03707 cnf->confno, 03708 user->user_no, 03709 S_OR(user->chan->cid.cid_num, "<unknown>"), 03710 S_OR(user->chan->cid.cid_name, "<no name>"), 03711 user->chan->name, 03712 user->userflags & CONFFLAG_ADMIN ? "Yes" : "No", 03713 user->userflags & CONFFLAG_MONITOR ? "Listen only" : user->userflags & CONFFLAG_TALKER ? "Talk only" : "Talk and listen", 03714 user->userflags & CONFFLAG_MARKEDUSER ? "Yes" : "No", 03715 user->adminflags & ADMINFLAG_MUTED ? "By admin" : user->adminflags & ADMINFLAG_SELFMUTED ? "By self" : "No", 03716 user->talking > 0 ? "Yes" : user->talking == 0 ? "No" : "Not monitored"); 03717 } 03718 } 03719 AST_LIST_UNLOCK(&confs); 03720 /* Send final confirmation */ 03721 astman_append(s, 03722 "Event: MeetmeListComplete\r\n" 03723 "EventList: Complete\r\n" 03724 "ListItems: %d\r\n" 03725 "%s" 03726 "\r\n", total, idText); 03727 return 0; 03728 }
static int action_meetmemute | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 3645 of file app_meetme.c.
References meetmemute(), and s.
Referenced by load_module().
03646 { 03647 return meetmemute(s, m, 1); 03648 }
static int action_meetmeunmute | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 3650 of file app_meetme.c.
References meetmemute(), and s.
Referenced by load_module().
03651 { 03652 return meetmemute(s, m, 0); 03653 }
static int admin_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
The MeetMeadmin application.
Definition at line 3375 of file app_meetme.c.
References ADMINFLAG_KICKME, ADMINFLAG_MUTED, ADMINFLAG_SELFMUTED, ADMINFLAG_T_REQUEST, AST_APP_ARG, ast_atomic_fetchadd_int(), AST_DECLARE_APP_ARGS, AST_LIST_LAST, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), CONFFLAG_ADMIN, ast_conference::confno, dispose_conf(), find_user(), ast_conf_user::list, ast_conference::locked, LOG_NOTICE, LOG_WARNING, ast_conference::refcount, reset_volumes(), tweak_listen_volume(), tweak_talk_volume(), user, ast_conference::userlist, and VOL_UP.
Referenced by load_module(), run_station(), sla_station_exec(), and sla_stop_ringing_trunk().
03375 { 03376 char *params; 03377 struct ast_conference *cnf; 03378 struct ast_conf_user *user = NULL; 03379 AST_DECLARE_APP_ARGS(args, 03380 AST_APP_ARG(confno); 03381 AST_APP_ARG(command); 03382 AST_APP_ARG(user); 03383 ); 03384 03385 if (ast_strlen_zero(data)) { 03386 ast_log(LOG_WARNING, "MeetMeAdmin requires an argument!\n"); 03387 return -1; 03388 } 03389 03390 params = ast_strdupa(data); 03391 AST_STANDARD_APP_ARGS(args, params); 03392 03393 if (!args.command) { 03394 ast_log(LOG_WARNING, "MeetmeAdmin requires a command!\n"); 03395 return -1; 03396 } 03397 03398 AST_LIST_LOCK(&confs); 03399 AST_LIST_TRAVERSE(&confs, cnf, list) { 03400 if (!strcmp(cnf->confno, args.confno)) 03401 break; 03402 } 03403 03404 if (!cnf) { 03405 ast_log(LOG_WARNING, "Conference number '%s' not found!\n", args.confno); 03406 AST_LIST_UNLOCK(&confs); 03407 return 0; 03408 } 03409 03410 ast_atomic_fetchadd_int(&cnf->refcount, 1); 03411 03412 if (args.user) 03413 user = find_user(cnf, args.user); 03414 03415 switch (*args.command) { 03416 case 76: /* L: Lock */ 03417 cnf->locked = 1; 03418 break; 03419 case 108: /* l: Unlock */ 03420 cnf->locked = 0; 03421 break; 03422 case 75: /* K: kick all users */ 03423 AST_LIST_TRAVERSE(&cnf->userlist, user, list) 03424 user->adminflags |= ADMINFLAG_KICKME; 03425 break; 03426 case 101: /* e: Eject last user*/ 03427 user = AST_LIST_LAST(&cnf->userlist); 03428 if (!(user->userflags & CONFFLAG_ADMIN)) 03429 user->adminflags |= ADMINFLAG_KICKME; 03430 else 03431 ast_log(LOG_NOTICE, "Not kicking last user, is an Admin!\n"); 03432 break; 03433 case 77: /* M: Mute */ 03434 if (user) { 03435 user->adminflags |= ADMINFLAG_MUTED; 03436 } else 03437 ast_log(LOG_NOTICE, "Specified User not found!\n"); 03438 break; 03439 case 78: /* N: Mute all (non-admin) users */ 03440 AST_LIST_TRAVERSE(&cnf->userlist, user, list) { 03441 if (!(user->userflags & CONFFLAG_ADMIN)) 03442 user->adminflags |= ADMINFLAG_MUTED; 03443 } 03444 break; 03445 case 109: /* m: Unmute */ 03446 if (user) { 03447 user->adminflags &= ~(ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED | ADMINFLAG_T_REQUEST); 03448 } else 03449 ast_log(LOG_NOTICE, "Specified User not found!\n"); 03450 break; 03451 case 110: /* n: Unmute all users */ 03452 AST_LIST_TRAVERSE(&cnf->userlist, user, list) 03453 user->adminflags &= ~(ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED | ADMINFLAG_T_REQUEST); 03454 break; 03455 case 107: /* k: Kick user */ 03456 if (user) 03457 user->adminflags |= ADMINFLAG_KICKME; 03458 else 03459 ast_log(LOG_NOTICE, "Specified User not found!\n"); 03460 break; 03461 case 118: /* v: Lower all users listen volume */ 03462 AST_LIST_TRAVERSE(&cnf->userlist, user, list) 03463 tweak_listen_volume(user, VOL_DOWN); 03464 break; 03465 case 86: /* V: Raise all users listen volume */ 03466 AST_LIST_TRAVERSE(&cnf->userlist, user, list) 03467 tweak_listen_volume(user, VOL_UP); 03468 break; 03469 case 115: /* s: Lower all users speaking volume */ 03470 AST_LIST_TRAVERSE(&cnf->userlist, user, list) 03471 tweak_talk_volume(user, VOL_DOWN); 03472 break; 03473 case 83: /* S: Raise all users speaking volume */ 03474 AST_LIST_TRAVERSE(&cnf->userlist, user, list) 03475 tweak_talk_volume(user, VOL_UP); 03476 break; 03477 case 82: /* R: Reset all volume levels */ 03478 AST_LIST_TRAVERSE(&cnf->userlist, user, list) 03479 reset_volumes(user); 03480 break; 03481 case 114: /* r: Reset user's volume level */ 03482 if (user) 03483 reset_volumes(user); 03484 else 03485 ast_log(LOG_NOTICE, "Specified User not found!\n"); 03486 break; 03487 case 85: /* U: Raise user's listen volume */ 03488 if (user) 03489 tweak_listen_volume(user, VOL_UP); 03490 else 03491 ast_log(LOG_NOTICE, "Specified User not found!\n"); 03492 break; 03493 case 117: /* u: Lower user's listen volume */ 03494 if (user) 03495 tweak_listen_volume(user, VOL_DOWN); 03496 else 03497 ast_log(LOG_NOTICE, "Specified User not found!\n"); 03498 break; 03499 case 84: /* T: Raise user's talk volume */ 03500 if (user) 03501 tweak_talk_volume(user, VOL_UP); 03502 else 03503 ast_log(LOG_NOTICE, "Specified User not found!\n"); 03504 break; 03505 case 116: /* t: Lower user's talk volume */ 03506 if (user) 03507 tweak_talk_volume(user, VOL_DOWN); 03508 else 03509 ast_log(LOG_NOTICE, "Specified User not found!\n"); 03510 break; 03511 } 03512 03513 AST_LIST_UNLOCK(&confs); 03514 03515 dispose_conf(cnf); 03516 03517 return 0; 03518 }
static void* announce_thread | ( | void * | data | ) | [static] |
Definition at line 1542 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().
01543 { 01544 struct announce_listitem *current; 01545 struct ast_conference *conf = data; 01546 int res = 0; 01547 char filename[PATH_MAX] = ""; 01548 AST_LIST_HEAD_NOLOCK(, announce_listitem) local_list; 01549 AST_LIST_HEAD_INIT_NOLOCK(&local_list); 01550 01551 while (!conf->announcethread_stop) { 01552 ast_mutex_lock(&conf->announcelistlock); 01553 if (conf->announcethread_stop) { 01554 ast_mutex_unlock(&conf->announcelistlock); 01555 break; 01556 } 01557 if (AST_LIST_EMPTY(&conf->announcelist)) 01558 ast_cond_wait(&conf->announcelist_addition, &conf->announcelistlock); 01559 01560 AST_LIST_APPEND_LIST(&local_list, &conf->announcelist, entry); 01561 AST_LIST_HEAD_INIT_NOLOCK(&conf->announcelist); 01562 01563 ast_mutex_unlock(&conf->announcelistlock); 01564 if (conf->announcethread_stop) { 01565 break; 01566 } 01567 01568 for (res = 1; !conf->announcethread_stop && (current = AST_LIST_REMOVE_HEAD(&local_list, entry)); ao2_ref(current, -1)) { 01569 ast_log(LOG_DEBUG, "About to play %s\n", current->namerecloc); 01570 if (!ast_fileexists(current->namerecloc, NULL, NULL)) 01571 continue; 01572 if ((current->confchan) && (current->confusers > 1) && !ast_check_hangup(current->confchan)) { 01573 if (!ast_streamfile(current->confchan, current->namerecloc, current->language)) 01574 res = ast_waitstream(current->confchan, ""); 01575 if (!res) { 01576 ast_copy_string(filename, get_announce_filename(current->announcetype), sizeof(filename)); 01577 if (!ast_streamfile(current->confchan, filename, current->language)) 01578 ast_waitstream(current->confchan, ""); 01579 } 01580 } 01581 if (current->announcetype == CONF_HASLEFT) { 01582 ast_filedelete(current->namerecloc, NULL); 01583 } 01584 } 01585 } 01586 01587 /* thread marked to stop, clean up */ 01588 while ((current = AST_LIST_REMOVE_HEAD(&local_list, entry))) { 01589 ast_filedelete(current->namerecloc, NULL); 01590 ao2_ref(current, -1); 01591 } 01592 return NULL; 01593 }
static void answer_trunk_chan | ( | struct ast_channel * | chan | ) | [static] |
Definition at line 4027 of file app_meetme.c.
References ast_answer(), ast_indicate(), and chan.
Referenced by run_station(), sla_handle_dial_state_event(), and sla_station_exec().
04028 { 04029 ast_answer(chan); 04030 ast_indicate(chan, -1); 04031 }
static struct ast_conference* build_conf | ( | char * | confno, | |
char * | pin, | |||
char * | pinadmin, | |||
int | make, | |||
int | dynamic, | |||
int | refcount, | |||
const struct ast_channel * | chan | |||
) | [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 830 of file app_meetme.c.
References ast_atomic_fetchadd_int(), ast_calloc, ast_copy_string(), AST_FORMAT_SLINEAR, ast_free, ast_hangup(), AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_mutex_init(), AST_PTHREADT_NULL, ast_request(), ast_set_read_format(), ast_set_write_format(), ast_verb, chan, conf_map, ast_conference::confno, LOG_WARNING, and ast_channel::uniqueid.
Referenced by find_conf(), find_conf_realtime(), run_station(), sla_station_exec(), and sla_trunk_exec().
00831 { 00832 struct ast_conference *cnf; 00833 struct dahdi_confinfo dahdic = { 0, }; 00834 int confno_int = 0; 00835 00836 AST_LIST_LOCK(&confs); 00837 00838 AST_LIST_TRAVERSE(&confs, cnf, list) { 00839 if (!strcmp(confno, cnf->confno)) 00840 break; 00841 } 00842 00843 if (cnf || (!make && !dynamic)) 00844 goto cnfout; 00845 00846 /* Make a new one */ 00847 if (!(cnf = ast_calloc(1, sizeof(*cnf)))) 00848 goto cnfout; 00849 00850 ast_mutex_init(&cnf->playlock); 00851 ast_mutex_init(&cnf->listenlock); 00852 cnf->recordthread = AST_PTHREADT_NULL; 00853 ast_mutex_init(&cnf->recordthreadlock); 00854 cnf->announcethread = AST_PTHREADT_NULL; 00855 ast_mutex_init(&cnf->announcethreadlock); 00856 ast_copy_string(cnf->confno, confno, sizeof(cnf->confno)); 00857 ast_copy_string(cnf->pin, pin, sizeof(cnf->pin)); 00858 ast_copy_string(cnf->pinadmin, pinadmin, sizeof(cnf->pinadmin)); 00859 ast_copy_string(cnf->uniqueid, chan->uniqueid, sizeof(cnf->uniqueid)); 00860 00861 /* Setup a new dahdi conference */ 00862 dahdic.confno = -1; 00863 dahdic.confmode = DAHDI_CONF_CONFANN | DAHDI_CONF_CONFANNMON; 00864 cnf->fd = open("/dev/dahdi/pseudo", O_RDWR); 00865 if (cnf->fd < 0 || ioctl(cnf->fd, DAHDI_SETCONF, &dahdic)) { 00866 ast_log(LOG_WARNING, "Unable to open pseudo device\n"); 00867 if (cnf->fd >= 0) 00868 close(cnf->fd); 00869 ast_free(cnf); 00870 cnf = NULL; 00871 goto cnfout; 00872 } 00873 00874 cnf->dahdiconf = dahdic.confno; 00875 00876 /* Setup a new channel for playback of audio files */ 00877 cnf->chan = ast_request("DAHDI", AST_FORMAT_SLINEAR, "pseudo", NULL); 00878 if (cnf->chan) { 00879 ast_set_read_format(cnf->chan, AST_FORMAT_SLINEAR); 00880 ast_set_write_format(cnf->chan, AST_FORMAT_SLINEAR); 00881 dahdic.chan = 0; 00882 dahdic.confno = cnf->dahdiconf; 00883 dahdic.confmode = DAHDI_CONF_CONFANN | DAHDI_CONF_CONFANNMON; 00884 if (ioctl(cnf->chan->fds[0], DAHDI_SETCONF, &dahdic)) { 00885 ast_log(LOG_WARNING, "Error setting conference\n"); 00886 if (cnf->chan) 00887 ast_hangup(cnf->chan); 00888 else 00889 close(cnf->fd); 00890 00891 ast_free(cnf); 00892 cnf = NULL; 00893 goto cnfout; 00894 } 00895 } 00896 00897 /* Fill the conference struct */ 00898 cnf->start = time(NULL); 00899 cnf->maxusers = 0x7fffffff; 00900 cnf->isdynamic = dynamic ? 1 : 0; 00901 ast_verb(3, "Created MeetMe conference %d for conference '%s'\n", cnf->dahdiconf, cnf->confno); 00902 AST_LIST_INSERT_HEAD(&confs, cnf, list); 00903 00904 /* Reserve conference number in map */ 00905 if ((sscanf(cnf->confno, "%d", &confno_int) == 1) && (confno_int >= 0 && confno_int < 1024)) 00906 conf_map[confno_int] = 1; 00907 00908 cnfout: 00909 if (cnf) 00910 ast_atomic_fetchadd_int(&cnf->refcount, refcount); 00911 00912 AST_LIST_UNLOCK(&confs); 00913 00914 return cnf; 00915 }
static int can_write | ( | struct ast_channel * | chan, | |
int | confflags | |||
) | [static] |
Definition at line 1595 of file app_meetme.c.
References ast_channel::_state, AST_STATE_UP, chan, and CONFFLAG_NO_AUDIO_UNTIL_UP.
Referenced by conf_run().
01596 { 01597 if (!(confflags & CONFFLAG_NO_AUDIO_UNTIL_UP)) { 01598 return 1; 01599 } 01600 01601 return (chan->_state == AST_STATE_UP); 01602 }
static int careful_write | ( | int | fd, | |
unsigned char * | data, | |||
int | len, | |||
int | block | |||
) | [static] |
Definition at line 664 of file app_meetme.c.
References ast_log(), errno, and LOG_WARNING.
00665 { 00666 int res; 00667 int x; 00668 00669 while (len) { 00670 if (block) { 00671 x = DAHDI_IOMUX_WRITE | DAHDI_IOMUX_SIGEVENT; 00672 res = ioctl(fd, DAHDI_IOMUX, &x); 00673 } else 00674 res = 0; 00675 if (res >= 0) 00676 res = write(fd, data, len); 00677 if (res < 1) { 00678 if (errno != EAGAIN) { 00679 ast_log(LOG_WARNING, "Failed to write audio data to conference: %s\n", strerror(errno)); 00680 return -1; 00681 } else 00682 return 0; 00683 } 00684 len -= res; 00685 data += res; 00686 } 00687 00688 return 0; 00689 }
static int channel_admin_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Definition at line 3522 of file app_meetme.c.
References ADMINFLAG_KICKME, ADMINFLAG_MUTED, 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, and ast_conference::userlist.
Referenced by load_module().
03522 { 03523 char *params; 03524 struct ast_conference *conf = NULL; 03525 struct ast_conf_user *user = NULL; 03526 AST_DECLARE_APP_ARGS(args, 03527 AST_APP_ARG(channel); 03528 AST_APP_ARG(command); 03529 ); 03530 03531 if (ast_strlen_zero(data)) { 03532 ast_log(LOG_WARNING, "MeetMeChannelAdmin requires two arguments!\n"); 03533 return -1; 03534 } 03535 03536 params = ast_strdupa(data); 03537 AST_STANDARD_APP_ARGS(args, params); 03538 03539 if (!args.channel) { 03540 ast_log(LOG_WARNING, "MeetMeChannelAdmin requires a channel name!\n"); 03541 return -1; 03542 } 03543 03544 if (!args.command) { 03545 ast_log(LOG_WARNING, "MeetMeChannelAdmin requires a command!\n"); 03546 return -1; 03547 } 03548 03549 AST_LIST_LOCK(&confs); 03550 AST_LIST_TRAVERSE(&confs, conf, list) { 03551 AST_LIST_TRAVERSE(&conf->userlist, user, list) { 03552 if (!strcmp(user->chan->name, args.channel)) 03553 break; 03554 } 03555 } 03556 03557 if (!user) { 03558 ast_log(LOG_NOTICE, "Specified user (%s) not found\n", args.channel); 03559 AST_LIST_UNLOCK(&confs); 03560 return 0; 03561 } 03562 03563 /* perform the specified action */ 03564 switch (*args.command) { 03565 case 77: /* M: Mute */ 03566 user->adminflags |= ADMINFLAG_MUTED; 03567 break; 03568 case 109: /* m: Unmute */ 03569 user->adminflags &= ~ADMINFLAG_MUTED; 03570 break; 03571 case 107: /* k: Kick user */ 03572 user->adminflags |= ADMINFLAG_KICKME; 03573 break; 03574 default: /* unknown command */ 03575 ast_log(LOG_WARNING, "Unknown MeetMeChannelAdmin command '%s'\n", args.command); 03576 break; 03577 } 03578 03579 AST_LIST_UNLOCK(&confs); 03580 03581 return 0; 03582 }
static char* complete_meetmecmd | ( | const char * | line, | |
const char * | word, | |||
int | pos, | |||
int | state | |||
) | [static] |
Definition at line 918 of file app_meetme.c.
References 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::userlist.
Referenced by meetme_cmd().
00919 { 00920 static char *cmds[] = {"concise", "lock", "unlock", "mute", "unmute", "kick", "list", NULL}; 00921 00922 int len = strlen(word); 00923 int which = 0; 00924 struct ast_conference *cnf = NULL; 00925 struct ast_conf_user *usr = NULL; 00926 char *confno = NULL; 00927 char usrno[50] = ""; 00928 char *myline, *ret = NULL; 00929 00930 if (pos == 1) { /* Command */ 00931 return ast_cli_complete(word, cmds, state); 00932 } else if (pos == 2) { /* Conference Number */ 00933 AST_LIST_LOCK(&confs); 00934 AST_LIST_TRAVERSE(&confs, cnf, list) { 00935 if (!strncasecmp(word, cnf->confno, len) && ++which > state) { 00936 ret = cnf->confno; 00937 break; 00938 } 00939 } 00940 ret = ast_strdup(ret); /* dup before releasing the lock */ 00941 AST_LIST_UNLOCK(&confs); 00942 return ret; 00943 } else if (pos == 3) { 00944 /* User Number || Conf Command option*/ 00945 if (strstr(line, "mute") || strstr(line, "kick")) { 00946 if (state == 0 && (strstr(line, "kick") || strstr(line, "mute")) && !strncasecmp(word, "all", len)) 00947 return ast_strdup("all"); 00948 which++; 00949 AST_LIST_LOCK(&confs); 00950 00951 /* TODO: Find the conf number from the cmdline (ignore spaces) <- test this and make it fail-safe! */ 00952 myline = ast_strdupa(line); 00953 if (strsep(&myline, " ") && strsep(&myline, " ") && !confno) { 00954 while((confno = strsep(&myline, " ")) && (strcmp(confno, " ") == 0)) 00955 ; 00956 } 00957 00958 AST_LIST_TRAVERSE(&confs, cnf, list) { 00959 if (!strcmp(confno, cnf->confno)) 00960 break; 00961 } 00962 00963 if (cnf) { 00964 /* Search for the user */ 00965 AST_LIST_TRAVERSE(&cnf->userlist, usr, list) { 00966 snprintf(usrno, sizeof(usrno), "%d", usr->user_no); 00967 if (!strncasecmp(word, usrno, len) && ++which > state) 00968 break; 00969 } 00970 } 00971 AST_LIST_UNLOCK(&confs); 00972 return usr ? ast_strdup(usrno) : NULL; 00973 } else if (strstr(line, "list") && (state == 0)) 00974 return ast_strdup("concise"); 00975 } 00976 00977 return NULL; 00978 }
static int conf_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
The meetme() application.
Definition at line 3111 of file app_meetme.c.
References ast_channel::_state, ARRAY_LEN, ast_answer(), AST_APP_ARG, ast_app_getdata(), ast_app_parse_options(), 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_log(), ast_say_digits(), ast_set_flag, AST_STANDARD_APP_ARGS, AST_STATE_UP, ast_stopstream(), ast_strdupa, ast_streamfile(), ast_strlen_zero(), ast_test_flag, ast_variable_browse(), ast_waitstream(), chan, conf_map, conf_run(), CONFFLAG_ADMIN, CONFFLAG_ALWAYSPROMPT, CONFFLAG_DYNAMIC, CONFFLAG_DYNAMICPIN, CONFFLAG_EMPTY, CONFFLAG_EMPTYNOPIN, CONFFLAG_QUIET, CONFIG_FILE_NAME, ast_conference::confno, dispose_conf(), find_conf(), find_conf_realtime(), ast_flags::flags, LOG_ERROR, LOG_WARNING, MAX_CONFNUM, MAX_PIN, meetme_opts, OPT_ARG_ARRAY_SIZE, ast_conference::pin, ast_conference::pinadmin, strsep(), and var.
03112 { 03113 int res = -1; 03114 char confno[MAX_CONFNUM] = ""; 03115 int allowretry = 0; 03116 int retrycnt = 0; 03117 struct ast_conference *cnf = NULL; 03118 struct ast_flags confflags = {0}, config_flags = { 0 }; 03119 int dynamic = 0; 03120 int empty = 0, empty_no_pin = 0; 03121 int always_prompt = 0; 03122 char *notdata, *info, the_pin[MAX_PIN] = ""; 03123 AST_DECLARE_APP_ARGS(args, 03124 AST_APP_ARG(confno); 03125 AST_APP_ARG(options); 03126 AST_APP_ARG(pin); 03127 ); 03128 char *optargs[OPT_ARG_ARRAY_SIZE] = { NULL, }; 03129 03130 if (ast_strlen_zero(data)) { 03131 allowretry = 1; 03132 notdata = ""; 03133 } else { 03134 notdata = data; 03135 } 03136 03137 if (chan->_state != AST_STATE_UP) 03138 ast_answer(chan); 03139 03140 info = ast_strdupa(notdata); 03141 03142 AST_STANDARD_APP_ARGS(args, info); 03143 03144 if (args.confno) { 03145 ast_copy_string(confno, args.confno, sizeof(confno)); 03146 if (ast_strlen_zero(confno)) { 03147 allowretry = 1; 03148 } 03149 } 03150 03151 if (args.pin) 03152 ast_copy_string(the_pin, args.pin, sizeof(the_pin)); 03153 03154 if (args.options) { 03155 ast_app_parse_options(meetme_opts, &confflags, optargs, args.options); 03156 dynamic = ast_test_flag(&confflags, CONFFLAG_DYNAMIC | CONFFLAG_DYNAMICPIN); 03157 if (ast_test_flag(&confflags, CONFFLAG_DYNAMICPIN) && !args.pin) 03158 strcpy(the_pin, "q"); 03159 03160 empty = ast_test_flag(&confflags, CONFFLAG_EMPTY | CONFFLAG_EMPTYNOPIN); 03161 empty_no_pin = ast_test_flag(&confflags, CONFFLAG_EMPTYNOPIN); 03162 always_prompt = ast_test_flag(&confflags, CONFFLAG_ALWAYSPROMPT | CONFFLAG_DYNAMICPIN); 03163 } 03164 03165 do { 03166 if (retrycnt > 3) 03167 allowretry = 0; 03168 if (empty) { 03169 int i; 03170 struct ast_config *cfg; 03171 struct ast_variable *var; 03172 int confno_int; 03173 03174 /* We only need to load the config file for static and empty_no_pin (otherwise we don't care) */ 03175 if ((empty_no_pin) || (!dynamic)) { 03176 cfg = ast_config_load(CONFIG_FILE_NAME, config_flags); 03177 if (cfg) { 03178 var = ast_variable_browse(cfg, "rooms"); 03179 while (var) { 03180 if (!strcasecmp(var->name, "conf")) { 03181 char *stringp = ast_strdupa(var->value); 03182 if (stringp) { 03183 char *confno_tmp = strsep(&stringp, "|,"); 03184 int found = 0; 03185 if (!dynamic) { 03186 /* For static: run through the list and see if this conference is empty */ 03187 AST_LIST_LOCK(&confs); 03188 AST_LIST_TRAVERSE(&confs, cnf, list) { 03189 if (!strcmp(confno_tmp, cnf->confno)) { 03190 /* The conference exists, therefore it's not empty */ 03191 found = 1; 03192 break; 03193 } 03194 } 03195 AST_LIST_UNLOCK(&confs); 03196 if (!found) { 03197 /* At this point, we have a confno_tmp (static conference) that is empty */ 03198 if ((empty_no_pin && ast_strlen_zero(stringp)) || (!empty_no_pin)) { 03199 /* Case 1: empty_no_pin and pin is nonexistent (NULL) 03200 * Case 2: empty_no_pin and pin is blank (but not NULL) 03201 * Case 3: not empty_no_pin 03202 */ 03203 ast_copy_string(confno, confno_tmp, sizeof(confno)); 03204 break; 03205 /* XXX the map is not complete (but we do have a confno) */ 03206 } 03207 } 03208 } 03209 } 03210 } 03211 var = var->next; 03212 } 03213 ast_config_destroy(cfg); 03214 } 03215 } 03216 03217 /* Select first conference number not in use */ 03218 if (ast_strlen_zero(confno) && dynamic) { 03219 AST_LIST_LOCK(&confs); 03220 for (i = 0; i < ARRAY_LEN(conf_map); i++) { 03221 if (!conf_map[i]) { 03222 snprintf(confno, sizeof(confno), "%d", i); 03223 conf_map[i] = 1; 03224 break; 03225 } 03226 } 03227 AST_LIST_UNLOCK(&confs); 03228 } 03229 03230 /* Not found? */ 03231 if (ast_strlen_zero(confno)) { 03232 res = ast_streamfile(chan, "conf-noempty", chan->language); 03233 if (!res) 03234 ast_waitstream(chan, ""); 03235 } else { 03236 if (sscanf(confno, "%d", &confno_int) == 1) { 03237 if (!ast_test_flag(&confflags, CONFFLAG_QUIET)) { 03238 res = ast_streamfile(chan, "conf-enteringno", chan->language); 03239 if (!res) { 03240 ast_waitstream(chan, ""); 03241 res = ast_say_digits(chan, confno_int, "", chan->language); 03242 } 03243 } 03244 } else { 03245 ast_log(LOG_ERROR, "Could not scan confno '%s'\n", confno); 03246 } 03247 } 03248 } 03249 03250 while (allowretry && (ast_strlen_zero(confno)) && (++retrycnt < 4)) { 03251 /* Prompt user for conference number */ 03252 res = ast_app_getdata(chan, "conf-getconfno", confno, sizeof(confno) - 1, 0); 03253 if (res < 0) { 03254 /* Don't try to validate when we catch an error */ 03255 confno[0] = '\0'; 03256 allowretry = 0; 03257 break; 03258 } 03259 } 03260 if (!ast_strlen_zero(confno)) { 03261 /* Check the validity of the conference */ 03262 cnf = find_conf(chan, confno, 1, dynamic, the_pin, 03263 sizeof(the_pin), 1, &confflags); 03264 if (!cnf) { 03265 int too_early = 0; 03266 cnf = find_conf_realtime(chan, confno, 1, dynamic, 03267 the_pin, sizeof(the_pin), 1, &confflags, optargs, &too_early); 03268 if (rt_schedule && too_early) 03269 allowretry = 0; 03270 } 03271 03272 if (!cnf) { 03273 if (allowretry) { 03274 confno[0] = '\0'; 03275 res = ast_streamfile(chan, "conf-invalid", chan->language); 03276 if (!res) 03277 ast_waitstream(chan, ""); 03278 res = -1; 03279 } 03280 } else { 03281 if ((!ast_strlen_zero(cnf->pin) && 03282 !ast_test_flag(&confflags, CONFFLAG_ADMIN)) || 03283 (!ast_strlen_zero(cnf->pinadmin) && 03284 ast_test_flag(&confflags, CONFFLAG_ADMIN))) { 03285 char pin[MAX_PIN] = ""; 03286 int j; 03287 03288 /* Allow the pin to be retried up to 3 times */ 03289 for (j = 0; j < 3; j++) { 03290 if (*the_pin && (always_prompt == 0)) { 03291 ast_copy_string(pin, the_pin, sizeof(pin)); 03292 res = 0; 03293 } else { 03294 /* Prompt user for pin if pin is required */ 03295 res = ast_app_getdata(chan, "conf-getpin", pin + strlen(pin), sizeof(pin) - 1 - strlen(pin), 0); 03296 } 03297 if (res >= 0) { 03298 if (!strcasecmp(pin, cnf->pin) || 03299 (!ast_strlen_zero(cnf->pinadmin) && 03300 !strcasecmp(pin, cnf->pinadmin))) { 03301 /* Pin correct */ 03302 allowretry = 0; 03303 if (!ast_strlen_zero(cnf->pinadmin) && !strcasecmp(pin, cnf->pinadmin)) 03304 ast_set_flag(&confflags, CONFFLAG_ADMIN); 03305 /* Run the conference */ 03306 res = conf_run(chan, cnf, confflags.flags, optargs); 03307 break; 03308 } else { 03309 /* Pin invalid */ 03310 if (!ast_streamfile(chan, "conf-invalidpin", chan->language)) { 03311 res = ast_waitstream(chan, AST_DIGIT_ANY); 03312 ast_stopstream(chan); 03313 } 03314 else { 03315 ast_log(LOG_WARNING, "Couldn't play invalid pin msg!\n"); 03316 break; 03317 } 03318 if (res < 0) 03319 break; 03320 pin[0] = res; 03321 pin[1] = '\0'; 03322 res = -1; 03323 if (allowretry) 03324 confno[0] = '\0'; 03325 } 03326 } else { 03327 /* failed when getting the pin */ 03328 res = -1; 03329 allowretry = 0; 03330 /* see if we need to get rid of the conference */ 03331 break; 03332 } 03333 03334 /* Don't retry pin with a static pin */ 03335 if (*the_pin && (always_prompt == 0)) { 03336 break; 03337 } 03338 } 03339 } else { 03340 /* No pin required */ 03341 allowretry = 0; 03342 03343 /* Run the conference */ 03344 res = conf_run(chan, cnf, confflags.flags, optargs); 03345 } 03346 dispose_conf(cnf); 03347 cnf = NULL; 03348 } 03349 } 03350 } while (allowretry); 03351 03352 if (cnf) 03353 dispose_conf(cnf); 03354 03355 return res; 03356 }
static void conf_flush | ( | int | fd, | |
struct ast_channel * | chan | |||
) | [static] |
Definition at line 1320 of file app_meetme.c.
References ast_frfree, ast_log(), ast_read(), ast_waitfor(), chan, f, and LOG_WARNING.
Referenced by conf_run().
01321 { 01322 int x; 01323 01324 /* read any frames that may be waiting on the channel 01325 and throw them away 01326 */ 01327 if (chan) { 01328 struct ast_frame *f; 01329 01330 /* when no frames are available, this will wait 01331 for 1 millisecond maximum 01332 */ 01333 while (ast_waitfor(chan, 1)) { 01334 f = ast_read(chan); 01335 if (f) 01336 ast_frfree(f); 01337 else /* channel was hung up or something else happened */ 01338 break; 01339 } 01340 } 01341 01342 /* flush any data sitting in the pseudo channel */ 01343 x = DAHDI_FLUSH_ALL; 01344 if (ioctl(fd, DAHDI_FLUSH, &x)) 01345 ast_log(LOG_WARNING, "Error flushing channel\n"); 01346 01347 }
static int conf_free | ( | struct ast_conference * | conf | ) | [static] |
Definition at line 1351 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().
01352 { 01353 int x; 01354 struct announce_listitem *item; 01355 01356 AST_LIST_REMOVE(&confs, conf, list); 01357 manager_event(EVENT_FLAG_CALL, "MeetmeEnd", "Meetme: %s\r\n", conf->confno); 01358 01359 if (conf->recording == MEETME_RECORD_ACTIVE) { 01360 conf->recording = MEETME_RECORD_TERMINATE; 01361 AST_LIST_UNLOCK(&confs); 01362 while (1) { 01363 usleep(1); 01364 AST_LIST_LOCK(&confs); 01365 if (conf->recording == MEETME_RECORD_OFF) 01366 break; 01367 AST_LIST_UNLOCK(&confs); 01368 } 01369 } 01370 01371 for (x = 0; x < AST_FRAME_BITS; x++) { 01372 if (conf->transframe[x]) 01373 ast_frfree(conf->transframe[x]); 01374 if (conf->transpath[x]) 01375 ast_translator_free_path(conf->transpath[x]); 01376 } 01377 if (conf->announcethread != AST_PTHREADT_NULL) { 01378 ast_mutex_lock(&conf->announcelistlock); 01379 conf->announcethread_stop = 1; 01380 ast_softhangup(conf->chan, AST_SOFTHANGUP_EXPLICIT); 01381 ast_cond_signal(&conf->announcelist_addition); 01382 ast_mutex_unlock(&conf->announcelistlock); 01383 pthread_join(conf->announcethread, NULL); 01384 01385 while ((item = AST_LIST_REMOVE_HEAD(&conf->announcelist, entry))) { 01386 ast_filedelete(item->namerecloc, NULL); 01387 ao2_ref(item, -1); 01388 } 01389 ast_mutex_destroy(&conf->announcelistlock); 01390 } 01391 if (conf->origframe) 01392 ast_frfree(conf->origframe); 01393 if (conf->lchan) 01394 ast_hangup(conf->lchan); 01395 if (conf->chan) 01396 ast_hangup(conf->chan); 01397 if (conf->fd >= 0) 01398 close(conf->fd); 01399 01400 ast_mutex_destroy(&conf->playlock); 01401 ast_mutex_destroy(&conf->listenlock); 01402 ast_mutex_destroy(&conf->recordthreadlock); 01403 ast_mutex_destroy(&conf->announcethreadlock); 01404 ast_free(conf); 01405 01406 return 0; 01407 }
static void conf_play | ( | struct ast_channel * | chan, | |
struct ast_conference * | conf, | |||
enum entrance_sound | sound | |||
) | [static] |
Definition at line 782 of file app_meetme.c.
References ast_autoservice_start(), ast_autoservice_stop(), ast_check_hangup(), AST_LIST_LOCK, AST_LIST_UNLOCK, careful_write(), chan, enter, ENTER, ast_conference::fd, leave, and len().
Referenced by conf_run().
00783 { 00784 unsigned char *data; 00785 int len; 00786 int res = -1; 00787 00788 if (!ast_check_hangup(chan)) 00789 res = ast_autoservice_start(chan); 00790 00791 AST_LIST_LOCK(&confs); 00792 00793 switch(sound) { 00794 case ENTER: 00795 data = enter; 00796 len = sizeof(enter); 00797 break; 00798 case LEAVE: 00799 data = leave; 00800 len = sizeof(leave); 00801 break; 00802 default: 00803 data = NULL; 00804 len = 0; 00805 } 00806 if (data) { 00807 careful_write(conf->fd, data, len, 1); 00808 } 00809 00810 AST_LIST_UNLOCK(&confs); 00811 00812 if (!res) 00813 ast_autoservice_stop(chan); 00814 }
static void conf_queue_dtmf | ( | const struct ast_conference * | conf, | |
const struct ast_conf_user * | sender, | |||
struct ast_frame * | f | |||
) | [static] |
Definition at line 1409 of file app_meetme.c.
References AST_LIST_TRAVERSE, ast_log(), ast_write(), f, ast_conf_user::list, LOG_WARNING, user, and ast_conference::userlist.
Referenced by conf_run().
01411 { 01412 struct ast_conf_user *user; 01413 01414 AST_LIST_TRAVERSE(&conf->userlist, user, list) { 01415 if (user == sender) 01416 continue; 01417 if (ast_write(user->chan, f) < 0) 01418 ast_log(LOG_WARNING, "Error writing frame to channel %s\n", user->chan->name); 01419 } 01420 }
static int conf_run | ( | struct ast_channel * | chan, | |
struct ast_conference * | conf, | |||
int | confflags, | |||
char * | optargs[] | |||
) | [static] |
Definition at line 1604 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_ref(), app, ast_calloc, ast_channel_setoption(), ast_check_hangup(), ast_cond_signal(), ast_config_AST_SPOOL_DIR, AST_CONTROL_HOLD, ast_copy_string(), ast_debug, AST_DEVICE_INUSE, AST_DEVICE_NOT_INUSE, ast_devstate_changed(), AST_DIGIT_ANY, ast_dsp_free(), ast_dsp_new(), ast_dsp_silence(), ast_exists_extension(), ast_filedelete(), 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_goto_if_exists(), ast_hangup(), ast_indicate(), AST_LIST_EMPTY, AST_LIST_HEAD_INIT_NOLOCK, AST_LIST_INSERT_TAIL, AST_LIST_LAST, AST_LIST_LOCK, AST_LIST_NEXT, AST_LIST_REMOVE, AST_LIST_UNLOCK, ast_log(), AST_MAX_CONTEXT, AST_MAX_EXTENSION, ast_mkdir(), 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_record_review(), ast_request(), ast_safe_sleep(), ast_samp2tv(), ast_say_digits(), ast_say_number(), ast_set_read_format(), ast_set_write_format(), ast_stopstream(), ast_strdupa, ast_streamfile(), ast_strlen_zero(), ast_translate(), ast_translator_build_path(), ast_tvadd(), ast_tvdiff_ms(), ast_tvnow(), ast_tvsub(), ast_tvzero(), ast_update_realtime(), ast_verb, ast_verbose(), ast_waitfor_nandfds(), ast_waitstream(), ast_write(), ast_channel::audiohooks, buf, can_write(), careful_write(), ast_conf_user::chan, ast_conference::chan, 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_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_channel::context, ast_conference::dahdiconf, dtmfstr, ast_conference::endalert, ast_conference::endtime, ENTER, announce_listitem::entry, errno, EVENT_FLAG_CALL, exitcontext, f, ast_channel::fds, ast_frame::frame_list, ast_frame::frametype, ast_channel::language, ast_conference::lchan, ast_conference::listenlock, ast_conference::locked, LOG_WARNING, ast_channel::macrocontext, manager_event, ast_conference::markedusers, ast_conference::maxusers, MEETME_DELAYDETECTENDTALK, MEETME_DELAYDETECTTALK, ast_channel::monitor, ast_channel::name, OPT_ARG_DURATION_LIMIT, OPT_ARG_DURATION_STOP, OPT_ARG_EXITKEYS, 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, reset_volumes(), s, S_OR, sec, set_talk_volume(), SLA_EVENT_HOLD, sla_queue_event_conf(), strsep(), ast_channel::tech, ast_conference::transframe, ast_conference::transpath, tweak_listen_volume(), tweak_talk_volume(), ast_channel_tech::type, ast_conference::uniqueid, ast_channel::uniqueid, user, ast_conf_user::userflags, ast_conference::userlist, ast_conference::users, var, and VOL_UP.
01605 { 01606 struct ast_conf_user *user = NULL; 01607 struct ast_conf_user *usr = NULL; 01608 int fd; 01609 struct dahdi_confinfo dahdic, dahdic_empty; 01610 struct ast_frame *f; 01611 struct ast_channel *c; 01612 struct ast_frame fr; 01613 int outfd; 01614 int ms; 01615 int nfds; 01616 int res; 01617 int retrydahdi; 01618 int origfd; 01619 int musiconhold = 0; 01620 int firstpass = 0; 01621 int lastmarked = 0; 01622 int currentmarked = 0; 01623 int ret = -1; 01624 int x; 01625 int menu_active = 0; 01626 int talkreq_manager = 0; 01627 int using_pseudo = 0; 01628 int duration = 20; 01629 int hr, min, sec; 01630 int sent_event = 0; 01631 int checked = 0; 01632 int announcement_played = 0; 01633 struct timeval now; 01634 struct ast_dsp *dsp = NULL; 01635 struct ast_app *app; 01636 const char *agifile; 01637 const char *agifiledefault = "conf-background.agi"; 01638 char meetmesecs[30] = ""; 01639 char exitcontext[AST_MAX_CONTEXT] = ""; 01640 char recordingtmp[AST_MAX_EXTENSION] = ""; 01641 char members[10] = ""; 01642 int dtmf, opt_waitmarked_timeout = 0; 01643 time_t timeout = 0; 01644 struct dahdi_bufferinfo bi; 01645 char __buf[CONF_SIZE + AST_FRIENDLY_OFFSET]; 01646 char *buf = __buf + AST_FRIENDLY_OFFSET; 01647 char *exitkeys = NULL; 01648 unsigned int calldurationlimit = 0; 01649 long timelimit = 0; 01650 long play_warning = 0; 01651 long warning_freq = 0; 01652 const char *warning_sound = NULL; 01653 const char *end_sound = NULL; 01654 char *parse; 01655 long time_left_ms = 0; 01656 struct timeval nexteventts = { 0, }; 01657 int to; 01658 int setusercount = 0; 01659 01660 if (!(user = ast_calloc(1, sizeof(*user)))) 01661 return ret; 01662 01663 /* Possible timeout waiting for marked user */ 01664 if ((confflags & CONFFLAG_WAITMARKED) && 01665 !ast_strlen_zero(optargs[OPT_ARG_WAITMARKED]) && 01666 (sscanf(optargs[OPT_ARG_WAITMARKED], "%d", &opt_waitmarked_timeout) == 1) && 01667 (opt_waitmarked_timeout > 0)) { 01668 timeout = time(NULL) + opt_waitmarked_timeout; 01669 } 01670 01671 if ((confflags & CONFFLAG_DURATION_STOP) && !ast_strlen_zero(optargs[OPT_ARG_DURATION_STOP])) { 01672 calldurationlimit = atoi(optargs[OPT_ARG_DURATION_STOP]); 01673 ast_verb(3, "Setting call duration limit to %d seconds.\n", calldurationlimit); 01674 } 01675 01676 if ((confflags & CONFFLAG_DURATION_LIMIT) && !ast_strlen_zero(optargs[OPT_ARG_DURATION_LIMIT])) { 01677 char *limit_str, *warning_str, *warnfreq_str; 01678 const char *var; 01679 01680 parse = optargs[OPT_ARG_DURATION_LIMIT]; 01681 limit_str = strsep(&parse, ":"); 01682 warning_str = strsep(&parse, ":"); 01683 warnfreq_str = parse; 01684 01685 timelimit = atol(limit_str); 01686 if (warning_str) 01687 play_warning = atol(warning_str); 01688 if (warnfreq_str) 01689 warning_freq = atol(warnfreq_str); 01690 01691 if (!timelimit) { 01692 timelimit = play_warning = warning_freq = 0; 01693 warning_sound = NULL; 01694 } else if (play_warning > timelimit) { 01695 if (!warning_freq) { 01696 play_warning = 0; 01697 } else { 01698 while (play_warning > timelimit) 01699 play_warning -= warning_freq; 01700 if (play_warning < 1) 01701 play_warning = warning_freq = 0; 01702 } 01703 } 01704 01705 var = pbx_builtin_getvar_helper(chan, "CONF_LIMIT_WARNING_FILE"); 01706 warning_sound = var ? var : "timeleft"; 01707 01708 var = pbx_builtin_getvar_helper(chan, "CONF_LIMIT_TIMEOUT_FILE"); 01709 end_sound = var ? var : NULL; 01710 01711 /* undo effect of S(x) in case they are both used */ 01712 calldurationlimit = 0; 01713 /* more efficient do it like S(x) does since no advanced opts */ 01714 if (!play_warning && !end_sound && timelimit) { 01715 calldurationlimit = timelimit / 1000; 01716 timelimit = play_warning = warning_freq = 0; 01717 } else { 01718 ast_debug(2, "Limit Data for this call:\n"); 01719 ast_debug(2, "- timelimit = %ld\n", timelimit); 01720 ast_debug(2, "- play_warning = %ld\n", play_warning); 01721 ast_debug(2, "- warning_freq = %ld\n", warning_freq); 01722 ast_debug(2, "- warning_sound = %s\n", warning_sound ? warning_sound : "UNDEF"); 01723 ast_debug(2, "- end_sound = %s\n", end_sound ? end_sound : "UNDEF"); 01724 } 01725 } 01726 01727 /* Get exit keys */ 01728 if ((confflags & CONFFLAG_KEYEXIT)) { 01729 if (!ast_strlen_zero(optargs[OPT_ARG_EXITKEYS])) 01730 exitkeys = ast_strdupa(optargs[OPT_ARG_EXITKEYS]); 01731 else 01732 exitkeys = ast_strdupa("#"); /* Default */ 01733 } 01734 01735 if (confflags & CONFFLAG_RECORDCONF) { 01736 if (!conf->recordingfilename) { 01737 conf->recordingfilename = pbx_builtin_getvar_helper(chan, "MEETME_RECORDINGFILE"); 01738 if (!conf->recordingfilename) { 01739 snprintf(recordingtmp, sizeof(recordingtmp), "meetme-conf-rec-%s-%s", conf->confno, chan->uniqueid); 01740 conf->recordingfilename = ast_strdupa(recordingtmp); 01741 } 01742 conf->recordingformat = pbx_builtin_getvar_helper(chan, "MEETME_RECORDINGFORMAT"); 01743 if (!conf->recordingformat) { 01744 ast_copy_string(recordingtmp, "wav", sizeof(recordingtmp)); 01745 conf->recordingformat = ast_strdupa(recordingtmp); 01746 } 01747 ast_verb(4, "Starting recording of MeetMe Conference %s into file %s.%s.\n", 01748 conf->confno, conf->recordingfilename, conf->recordingformat); 01749 } 01750 } 01751 01752 ast_mutex_lock(&conf->recordthreadlock); 01753 if ((conf->recordthread == AST_PTHREADT_NULL) && (confflags & CONFFLAG_RECORDCONF) && ((conf->lchan = ast_request("DAHDI", AST_FORMAT_SLINEAR, "pseudo", NULL)))) { 01754 ast_set_read_format(conf->lchan, AST_FORMAT_SLINEAR); 01755 ast_set_write_format(conf->lchan, AST_FORMAT_SLINEAR); 01756 dahdic.chan = 0; 01757 dahdic.confno = conf->dahdiconf; 01758 dahdic.confmode = DAHDI_CONF_CONFANN | DAHDI_CONF_CONFANNMON; 01759 if (ioctl(conf->lchan->fds[0], DAHDI_SETCONF, &dahdic)) { 01760 ast_log(LOG_WARNING, "Error starting listen channel\n"); 01761 ast_hangup(conf->lchan); 01762 conf->lchan = NULL; 01763 } else { 01764 ast_pthread_create_detached_background(&conf->recordthread, NULL, recordthread, conf); 01765 } 01766 } 01767 ast_mutex_unlock(&conf->recordthreadlock); 01768 01769 ast_mutex_lock(&conf->announcethreadlock); 01770 if ((conf->announcethread == AST_PTHREADT_NULL) && !(confflags & CONFFLAG_QUIET) && ((confflags & CONFFLAG_INTROUSER) || (confflags & CONFFLAG_INTROUSERNOREVIEW))) { 01771 ast_mutex_init(&conf->announcelistlock); 01772 AST_LIST_HEAD_INIT_NOLOCK(&conf->announcelist); 01773 ast_pthread_create_background(&conf->announcethread, NULL, announce_thread, conf); 01774 } 01775 ast_mutex_unlock(&conf->announcethreadlock); 01776 01777 time(&user->jointime); 01778 01779 user->timelimit = timelimit; 01780 user->play_warning = play_warning; 01781 user->warning_freq = warning_freq; 01782 user->warning_sound = warning_sound; 01783 user->end_sound = end_sound; 01784 01785 if (calldurationlimit > 0) { 01786 time(&user->kicktime); 01787 user->kicktime = user->kicktime + calldurationlimit; 01788 } 01789 01790 if (ast_tvzero(user->start_time)) 01791 user->start_time = ast_tvnow(); 01792 time_left_ms = user->timelimit; 01793 01794 if (user->timelimit) { 01795 nexteventts = ast_tvadd(user->start_time, ast_samp2tv(user->timelimit, 1000)); 01796 nexteventts = ast_tvsub(nexteventts, ast_samp2tv(user->play_warning, 1000)); 01797 } 01798 01799 if (conf->locked && (!(confflags & CONFFLAG_ADMIN))) { 01800 /* Sorry, but this conference is locked! */ 01801 if (!ast_streamfile(chan, "conf-locked", chan->language)) 01802 ast_waitstream(chan, ""); 01803 goto outrun; 01804 } 01805 01806 ast_mutex_lock(&conf->playlock); 01807 01808 if (AST_LIST_EMPTY(&conf->userlist)) 01809 user->user_no = 1; 01810 else 01811 user->user_no = AST_LIST_LAST(&conf->userlist)->user_no + 1; 01812 01813 if (rt_schedule && conf->maxusers) 01814 if (conf->users >= conf->maxusers) { 01815 /* Sorry, but this confernce has reached the participant limit! */ 01816 if (!ast_streamfile(chan, "conf-full", chan->language)) 01817 ast_waitstream(chan, ""); 01818 ast_mutex_unlock(&conf->playlock); 01819 user->user_no = 0; 01820 goto outrun; 01821 } 01822 01823 AST_LIST_INSERT_TAIL(&conf->userlist, user, list); 01824 01825 user->chan = chan; 01826 user->userflags = confflags; 01827 user->adminflags = (confflags & CONFFLAG_STARTMUTED) ? ADMINFLAG_SELFMUTED : 0; 01828 user->talking = -1; 01829 01830 ast_mutex_unlock(&conf->playlock); 01831 01832 if (!(confflags & CONFFLAG_QUIET) && ((confflags & CONFFLAG_INTROUSER) || (confflags & CONFFLAG_INTROUSERNOREVIEW))) { 01833 char destdir[PATH_MAX]; 01834 01835 snprintf(destdir, sizeof(destdir), "%s/meetme", ast_config_AST_SPOOL_DIR); 01836 01837 if (ast_mkdir(destdir, 0777) != 0) { 01838 ast_log(LOG_WARNING, "mkdir '%s' failed: %s\n", destdir, strerror(errno)); 01839 goto outrun; 01840 } 01841 01842 snprintf(user->namerecloc, sizeof(user->namerecloc), 01843 "%s/meetme-username-%s-%d", destdir, 01844 conf->confno, user->user_no); 01845 if (confflags & CONFFLAG_INTROUSERNOREVIEW) 01846 res = ast_play_and_record(chan, "vm-rec-name", user->namerecloc, 10, "sln", &duration, 128, 0, NULL); 01847 else 01848 res = ast_record_review(chan, "vm-rec-name", user->namerecloc, 10, "sln", &duration, NULL); 01849 if (res == -1) 01850 goto outrun; 01851 } 01852 01853 ast_mutex_lock(&conf->playlock); 01854 01855 if (confflags & CONFFLAG_MARKEDUSER) 01856 conf->markedusers++; 01857 conf->users++; 01858 if (rt_log_members) { 01859 /* Update table */ 01860 snprintf(members, sizeof(members), "%d", conf->users); 01861 ast_update_realtime("meetme", "confno", conf->confno, "members", members, NULL); 01862 } 01863 setusercount = 1; 01864 01865 /* This device changed state now - if this is the first user */ 01866 if (conf->users == 1) 01867 ast_devstate_changed(AST_DEVICE_INUSE, "meetme:%s", conf->confno); 01868 01869 ast_mutex_unlock(&conf->playlock); 01870 01871 /* return the unique ID of the conference */ 01872 pbx_builtin_setvar_helper(chan, "MEETMEUNIQUEID", conf->uniqueid); 01873 01874 if (confflags & CONFFLAG_EXIT_CONTEXT) { 01875 if ((agifile = pbx_builtin_getvar_helper(chan, "MEETME_EXIT_CONTEXT"))) 01876 ast_copy_string(exitcontext, agifile, sizeof(exitcontext)); 01877 else if (!ast_strlen_zero(chan->macrocontext)) 01878 ast_copy_string(exitcontext, chan->macrocontext, sizeof(exitcontext)); 01879 else 01880 ast_copy_string(exitcontext, chan->context, sizeof(exitcontext)); 01881 } 01882 01883 if (!(confflags & (CONFFLAG_QUIET | CONFFLAG_NOONLYPERSON))) { 01884 if (conf->users == 1 && !(confflags & CONFFLAG_WAITMARKED)) 01885 if (!ast_streamfile(chan, "conf-onlyperson", chan->language)) 01886 ast_waitstream(chan, ""); 01887 if ((confflags & CONFFLAG_WAITMARKED) && conf->markedusers == 0) 01888 if (!ast_streamfile(chan, "conf-waitforleader", chan->language)) 01889 ast_waitstream(chan, ""); 01890 } 01891 01892 if (!(confflags & CONFFLAG_QUIET) && (confflags & CONFFLAG_ANNOUNCEUSERCOUNT) && conf->users > 1) { 01893 int keepplaying = 1; 01894 01895 if (conf->users == 2) { 01896 if (!ast_streamfile(chan, "conf-onlyone", chan->language)) { 01897 res = ast_waitstream(chan, AST_DIGIT_ANY); 01898 ast_stopstream(chan); 01899 if (res > 0) 01900 keepplaying = 0; 01901 else if (res == -1) 01902 goto outrun; 01903 } 01904 } else { 01905 if (!ast_streamfile(chan, "conf-thereare", chan->language)) { 01906 res = ast_waitstream(chan, AST_DIGIT_ANY); 01907 ast_stopstream(chan); 01908 if (res > 0) 01909 keepplaying = 0; 01910 else if (res == -1) 01911 goto outrun; 01912 } 01913 if (keepplaying) { 01914 res = ast_say_number(chan, conf->users - 1, AST_DIGIT_ANY, chan->language, (char *) NULL); 01915 if (res > 0) 01916 keepplaying = 0; 01917 else if (res == -1) 01918 goto outrun; 01919 } 01920 if (keepplaying && !ast_streamfile(chan, "conf-otherinparty", chan->language)) { 01921 res = ast_waitstream(chan, AST_DIGIT_ANY); 01922 ast_stopstream(chan); 01923 if (res > 0) 01924 keepplaying = 0; 01925 else if (res == -1) 01926 goto outrun; 01927 } 01928 } 01929 } 01930 01931 if (!(confflags & CONFFLAG_NO_AUDIO_UNTIL_UP)) { 01932 /* We're leaving this alone until the state gets changed to up */ 01933 ast_indicate(chan, -1); 01934 } 01935 01936 if (ast_set_write_format(chan, AST_FORMAT_SLINEAR) < 0) { 01937 ast_log(LOG_WARNING, "Unable to set '%s' to write linear mode\n", chan->name); 01938 goto outrun; 01939 } 01940 01941 if (ast_set_read_format(chan, AST_FORMAT_SLINEAR) < 0) { 01942 ast_log(LOG_WARNING, "Unable to set '%s' to read linear mode\n", chan->name); 01943 goto outrun; 01944 } 01945 01946 retrydahdi = (strcasecmp(chan->tech->type, "DAHDI") || (chan->audiohooks || chan->monitor) ? 1 : 0); 01947 user->dahdichannel = !retrydahdi; 01948 01949 dahdiretry: 01950 origfd = chan->fds[0]; 01951 if (retrydahdi) { 01952 /* open pseudo in non-blocking mode */ 01953 fd = open("/dev/dahdi/pseudo", O_RDWR | O_NONBLOCK); 01954 if (fd < 0) { 01955 ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno)); 01956 goto outrun; 01957 } 01958 using_pseudo = 1; 01959 /* Setup buffering information */ 01960 memset(&bi, 0, sizeof(bi)); 01961 bi.bufsize = CONF_SIZE / 2; 01962 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE; 01963 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE; 01964 bi.numbufs = audio_buffers; 01965 if (ioctl(fd, DAHDI_SET_BUFINFO, &bi)) { 01966 ast_log(LOG_WARNING, "Unable to set buffering information: %s\n", strerror(errno)); 01967 close(fd); 01968 goto outrun; 01969 } 01970 x = 1; 01971 if (ioctl(fd, DAHDI_SETLINEAR, &x)) { 01972 ast_log(LOG_WARNING, "Unable to set linear mode: %s\n", strerror(errno)); 01973 close(fd); 01974 goto outrun; 01975 } 01976 nfds = 1; 01977 } else { 01978 /* XXX Make sure we're not running on a pseudo channel XXX */ 01979 fd = chan->fds[0]; 01980 nfds = 0; 01981 } 01982 memset(&dahdic, 0, sizeof(dahdic)); 01983 memset(&dahdic_empty, 0, sizeof(dahdic_empty)); 01984 /* Check to see if we're in a conference... */ 01985 dahdic.chan = 0; 01986 if (ioctl(fd, DAHDI_GETCONF, &dahdic)) { 01987 ast_log(LOG_WARNING, "Error getting conference\n"); 01988 close(fd); 01989 goto outrun; 01990 } 01991 if (dahdic.confmode) { 01992 /* Whoa, already in a conference... Retry... */ 01993 if (!retrydahdi) { 01994 ast_debug(1, "DAHDI channel is in a conference already, retrying with pseudo\n"); 01995 retrydahdi = 1; 01996 goto dahdiretry; 01997 } 01998 } 01999 memset(&dahdic, 0, sizeof(dahdic)); 02000 /* Add us to the conference */ 02001 dahdic.chan = 0; 02002 dahdic.confno = conf->dahdiconf; 02003 02004 if (!(confflags & CONFFLAG_QUIET) && ((confflags & CONFFLAG_INTROUSER) || (confflags & CONFFLAG_INTROUSERNOREVIEW)) && conf->users > 1) { 02005 struct announce_listitem *item; 02006 if (!(item = ao2_alloc(sizeof(*item), NULL))) 02007 return -1; 02008 ast_copy_string(item->namerecloc, user->namerecloc, sizeof(item->namerecloc)); 02009 ast_copy_string(item->language, chan->language, sizeof(item->language)); 02010 item->confchan = conf->chan; 02011 item->confusers = conf->users; 02012 item->announcetype = CONF_HASJOIN; 02013 ast_mutex_lock(&conf->announcelistlock); 02014 ao2_ref(item, +1); /* add one more so we can determine when announce_thread is done playing it */ 02015 AST_LIST_INSERT_TAIL(&conf->announcelist, item, entry); 02016 ast_cond_signal(&conf->announcelist_addition); 02017 ast_mutex_unlock(&conf->announcelistlock); 02018 02019 while (!ast_check_hangup(conf->chan) && ao2_ref(item, 0) == 2 && !ast_safe_sleep(chan, 1000)) { 02020 ; 02021 } 02022 ao2_ref(item, -1); 02023 } 02024 02025 if (confflags & CONFFLAG_WAITMARKED && !conf->markedusers) 02026 dahdic.confmode = DAHDI_CONF_CONF; 02027 else if (confflags & CONFFLAG_MONITOR) 02028 dahdic.confmode = DAHDI_CONF_CONFMON | DAHDI_CONF_LISTENER; 02029 else if (confflags & CONFFLAG_TALKER) 02030 dahdic.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER; 02031 else 02032 dahdic.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER; 02033 02034 if (ioctl(fd, DAHDI_SETCONF, &dahdic)) { 02035 ast_log(LOG_WARNING, "Error setting conference\n"); 02036 close(fd); 02037 goto outrun; 02038 } 02039 ast_debug(1, "Placed channel %s in DAHDI conf %d\n", chan->name, conf->dahdiconf); 02040 02041 if (!sent_event) { 02042 manager_event(EVENT_FLAG_CALL, "MeetmeJoin", 02043 "Channel: %s\r\n" 02044 "Uniqueid: %s\r\n" 02045 "Meetme: %s\r\n" 02046 "Usernum: %d\r\n" 02047 "CallerIDnum: %s\r\n" 02048 "CallerIDname: %s\r\n", 02049 chan->name, chan->uniqueid, conf->confno, 02050 user->user_no, 02051 S_OR(user->chan->cid.cid_num, "<unknown>"), 02052 S_OR(user->chan->cid.cid_name, "<unknown>") 02053 ); 02054 sent_event = 1; 02055 } 02056 02057 if (!firstpass && !(confflags & CONFFLAG_MONITOR) && !(confflags & CONFFLAG_ADMIN)) { 02058 firstpass = 1; 02059 if (!(confflags & CONFFLAG_QUIET)) 02060 if (!(confflags & CONFFLAG_WAITMARKED) || ((confflags & CONFFLAG_MARKEDUSER) && (conf->markedusers >= 1))) 02061 conf_play(chan, conf, ENTER); 02062 } 02063 02064 conf_flush(fd, chan); 02065 02066 if (confflags & CONFFLAG_AGI) { 02067 /* Get name of AGI file to run from $(MEETME_AGI_BACKGROUND) 02068 or use default filename of conf-background.agi */ 02069 02070 agifile = pbx_builtin_getvar_helper(chan, "MEETME_AGI_BACKGROUND"); 02071 if (!agifile) 02072 agifile = agifiledefault; 02073 02074 if (user->dahdichannel) { 02075 /* Set CONFMUTE mode on DAHDI channel to mute DTMF tones */ 02076 x = 1; 02077 ast_channel_setoption(chan, AST_OPTION_TONE_VERIFY, &x, sizeof(char), 0); 02078 } 02079 /* Find a pointer to the agi app and execute the script */ 02080 app = pbx_findapp("agi"); 02081 if (app) { 02082 char *s = ast_strdupa(agifile); 02083 ret = pbx_exec(chan, app, s); 02084 } else { 02085 ast_log(LOG_WARNING, "Could not find application (agi)\n"); 02086 ret = -2; 02087 } 02088 if (user->dahdichannel) { 02089 /* Remove CONFMUTE mode on DAHDI channel */ 02090 x = 0; 02091 ast_channel_setoption(chan, AST_OPTION_TONE_VERIFY, &x, sizeof(char), 0); 02092 } 02093 } else { 02094 if (user->dahdichannel && (confflags & CONFFLAG_STARMENU)) { 02095 /* Set CONFMUTE mode on DAHDI channel to mute DTMF tones when the menu is enabled */ 02096 x = 1; 02097 ast_channel_setoption(chan, AST_OPTION_TONE_VERIFY, &x, sizeof(char), 0); 02098 } 02099 if (confflags & (CONFFLAG_OPTIMIZETALKER | CONFFLAG_MONITORTALKER) && !(dsp = ast_dsp_new())) { 02100 ast_log(LOG_WARNING, "Unable to allocate DSP!\n"); 02101 res = -1; 02102 } 02103 for (;;) { 02104 int menu_was_active = 0; 02105 02106 outfd = -1; 02107 ms = -1; 02108 now = ast_tvnow(); 02109 02110 if (rt_schedule) { 02111 if (now.tv_sec % 60 == 0) { 02112 if (!checked) { 02113 if (now.tv_sec > conf->endtime) { 02114 ast_verbose("Quitting time...\n"); 02115 goto outrun; 02116 } 02117 02118 if (!announcement_played && conf->endalert) { 02119 if (now.tv_sec + conf->endalert > conf->endtime) { 02120 if (!ast_streamfile(chan, "conf-will-end-in", chan->language)) 02121 ast_waitstream(chan, ""); 02122 ast_say_digits(chan, (now.tv_sec + conf->endalert - conf->endtime) / 60, "", chan->language); 02123 if (!ast_streamfile(chan, "minutes", chan->language)) 02124 ast_waitstream(chan, ""); 02125 announcement_played = 1; 02126 } 02127 } 02128 checked = 1; 02129 02130 } 02131 } else { 02132 checked = 0; 02133 } 02134 } 02135 02136 if (user->kicktime && (user->kicktime <= now.tv_sec)) 02137 break; 02138 02139 to = -1; 02140 if (user->timelimit) { 02141 int minutes = 0, seconds = 0, remain = 0; 02142 02143 to = ast_tvdiff_ms(nexteventts, now); 02144 if (to < 0) 02145 to = 0; 02146 time_left_ms = user->timelimit - ast_tvdiff_ms(now, user->start_time); 02147 if (time_left_ms < to) 02148 to = time_left_ms; 02149 02150 if (time_left_ms <= 0) { 02151 if (user->end_sound) { 02152 res = ast_streamfile(chan, user->end_sound, chan->language); 02153 res = ast_waitstream(chan, ""); 02154 } 02155 break; 02156 } 02157 02158 if (!to) { 02159 if (time_left_ms >= 5000) { 02160 02161 remain = (time_left_ms + 500) / 1000; 02162 if (remain / 60 >= 1) { 02163 minutes = remain / 60; 02164 seconds = remain % 60; 02165 } else { 02166 seconds = remain; 02167 } 02168 02169 /* force the time left to round up if appropriate */ 02170 if (user->warning_sound && user->play_warning) { 02171 if (!strcmp(user->warning_sound, "timeleft")) { 02172 02173 res = ast_streamfile(chan, "vm-youhave", chan->language); 02174 res = ast_waitstream(chan, ""); 02175 if (minutes) { 02176 res = ast_say_number(chan, minutes, AST_DIGIT_ANY, chan->language, (char *) NULL); 02177 res = ast_streamfile(chan, "queue-minutes", chan->language); 02178 res = ast_waitstream(chan, ""); 02179 } 02180 if (seconds) { 02181 res = ast_say_number(chan, seconds, AST_DIGIT_ANY, chan->language, (char *) NULL); 02182 res = ast_streamfile(chan, "queue-seconds", chan->language); 02183 res = ast_waitstream(chan, ""); 02184 } 02185 } else { 02186 res = ast_streamfile(chan, user->warning_sound, chan->language); 02187 res = ast_waitstream(chan, ""); 02188 } 02189 } 02190 } 02191 if (user->warning_freq) 02192 nexteventts = ast_tvadd(nexteventts, ast_samp2tv(user->warning_freq, 1000)); 02193 else 02194 nexteventts = ast_tvadd(user->start_time, ast_samp2tv(user->timelimit, 1000)); 02195 } 02196 } 02197 02198 now = ast_tvnow(); 02199 if (timeout && now.tv_sec >= timeout) 02200 break; 02201 02202 /* if we have just exited from the menu, and the user had a channel-driver 02203 volume adjustment, restore it 02204 */ 02205 if (!menu_active && menu_was_active && user->listen.desired && !user->listen.actual) 02206 set_talk_volume(user, user->listen.desired); 02207 02208 menu_was_active = menu_active; 02209 02210 currentmarked = conf->markedusers; 02211 if (!(confflags & CONFFLAG_QUIET) && 02212 (confflags & CONFFLAG_MARKEDUSER) && 02213 (confflags & CONFFLAG_WAITMARKED) && 02214 lastmarked == 0) { 02215 if (currentmarked == 1 && conf->users > 1) { 02216 ast_say_number(chan, conf->users - 1, AST_DIGIT_ANY, chan->language, (char *) NULL); 02217 if (conf->users - 1 == 1) { 02218 if (!ast_streamfile(chan, "conf-userwilljoin", chan->language)) 02219 ast_waitstream(chan, ""); 02220 } else { 02221 if (!ast_streamfile(chan, "conf-userswilljoin", chan->language)) 02222 ast_waitstream(chan, ""); 02223 } 02224 } 02225 if (conf->users == 1 && ! (confflags & CONFFLAG_MARKEDUSER)) 02226 if (!ast_streamfile(chan, "conf-onlyperson", chan->language)) 02227 ast_waitstream(chan, ""); 02228 } 02229 02230 /* Update the struct with the actual confflags */ 02231 user->userflags = confflags; 02232 02233 if (confflags & CONFFLAG_WAITMARKED) { 02234 if (currentmarked == 0) { 02235 if (lastmarked != 0) { 02236 if (!(confflags & CONFFLAG_QUIET)) 02237 if (!ast_streamfile(chan, "conf-leaderhasleft", chan->language)) 02238 ast_waitstream(chan, ""); 02239 if (confflags & CONFFLAG_MARKEDEXIT) { 02240 if (confflags & CONFFLAG_KICK_CONTINUE) 02241 ret = 0; 02242 break; 02243 } else { 02244 dahdic.confmode = DAHDI_CONF_CONF; 02245 if (ioctl(fd, DAHDI_SETCONF, &dahdic)) { 02246 ast_log(LOG_WARNING, "Error setting conference\n"); 02247 close(fd); 02248 goto outrun; 02249 } 02250 } 02251 } 02252 if (!musiconhold && (confflags & CONFFLAG_MOH)) { 02253 conf_start_moh(chan, optargs[OPT_ARG_MOH_CLASS]); 02254 musiconhold = 1; 02255 } 02256 } else if (currentmarked >= 1 && lastmarked == 0) { 02257 /* Marked user entered, so cancel timeout */ 02258 timeout = 0; 02259 if (confflags & CONFFLAG_MONITOR) 02260 dahdic.confmode = DAHDI_CONF_CONFMON | DAHDI_CONF_LISTENER; 02261 else if (confflags & CONFFLAG_TALKER) 02262 dahdic.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER; 02263 else 02264 dahdic.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER; 02265 if (ioctl(fd, DAHDI_SETCONF, &dahdic)) { 02266 ast_log(LOG_WARNING, "Error setting conference\n"); 02267 close(fd); 02268 goto outrun; 02269 } 02270 if (musiconhold && (confflags & CONFFLAG_MOH)) { 02271 ast_moh_stop(chan); 02272 musiconhold = 0; 02273 } 02274 if (!(confflags & CONFFLAG_QUIET) && !(confflags & CONFFLAG_MARKEDUSER)) { 02275 if (!ast_streamfile(chan, "conf-placeintoconf", chan->language)) 02276 ast_waitstream(chan, ""); 02277 conf_play(chan, conf, ENTER); 02278 } 02279 } 02280 } 02281 02282 /* trying to add moh for single person conf */ 02283 if ((confflags & CONFFLAG_MOH) && !(confflags & CONFFLAG_WAITMARKED)) { 02284 if (conf->users == 1) { 02285 if (!musiconhold) { 02286 conf_start_moh(chan, optargs[OPT_ARG_MOH_CLASS]); 02287 musiconhold = 1; 02288 } 02289 } else { 02290 if (musiconhold) { 02291 ast_moh_stop(chan); 02292 musiconhold = 0; 02293 } 02294 } 02295 } 02296 02297 /* Leave if the last marked user left */ 02298 if (currentmarked == 0 && lastmarked != 0 && (confflags & CONFFLAG_MARKEDEXIT)) { 02299 if (confflags & CONFFLAG_KICK_CONTINUE) 02300 ret = 0; 02301 else 02302 ret = -1; 02303 break; 02304 } 02305 02306 /* Check if my modes have changed */ 02307 02308 /* If I should be muted but am still talker, mute me */ 02309 if ((user->adminflags & (ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED)) && (dahdic.confmode & DAHDI_CONF_TALKER)) { 02310 dahdic.confmode ^= DAHDI_CONF_TALKER; 02311 if (ioctl(fd, DAHDI_SETCONF, &dahdic)) { 02312 ast_log(LOG_WARNING, "Error setting conference - Un/Mute \n"); 02313 ret = -1; 02314 break; 02315 } 02316 02317 manager_event(EVENT_FLAG_CALL, "MeetmeMute", 02318 "Channel: %s\r\n" 02319 "Uniqueid: %s\r\n" 02320 "Meetme: %s\r\n" 02321 "Usernum: %i\r\n" 02322 "Status: on\r\n", 02323 chan->name, chan->uniqueid, conf->confno, user->user_no); 02324 } 02325 02326 /* If I should be un-muted but am not talker, un-mute me */ 02327 if (!(user->adminflags & (ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED)) && !(confflags & CONFFLAG_MONITOR) && !(dahdic.confmode & DAHDI_CONF_TALKER)) { 02328 dahdic.confmode |= DAHDI_CONF_TALKER; 02329 if (ioctl(fd, DAHDI_SETCONF, &dahdic)) { 02330 ast_log(LOG_WARNING, "Error setting conference - Un/Mute \n"); 02331 ret = -1; 02332 break; 02333 } 02334 02335 manager_event(EVENT_FLAG_CALL, "MeetmeMute", 02336 "Channel: %s\r\n" 02337 "Uniqueid: %s\r\n" 02338 "Meetme: %s\r\n" 02339 "Usernum: %i\r\n" 02340 "Status: off\r\n", 02341 chan->name, chan->uniqueid, conf->confno, user->user_no); 02342 } 02343 02344 if ((user->adminflags & (ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED)) && 02345 (user->adminflags & ADMINFLAG_T_REQUEST) && !(talkreq_manager)) { 02346 talkreq_manager = 1; 02347 02348 manager_event(EVENT_FLAG_CALL, "MeetmeTalkRequest", 02349 "Channel: %s\r\n" 02350 "Uniqueid: %s\r\n" 02351 "Meetme: %s\r\n" 02352 "Usernum: %i\r\n" 02353 "Status: on\r\n", 02354 chan->name, chan->uniqueid, conf->confno, user->user_no); 02355 } 02356 02357 02358 if (!(user->adminflags & (ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED)) && 02359 !(user->adminflags & ADMINFLAG_T_REQUEST) && (talkreq_manager)) { 02360 talkreq_manager = 0; 02361 manager_event(EVENT_FLAG_CALL, "MeetmeTalkRequest", 02362 "Channel: %s\r\n" 02363 "Uniqueid: %s\r\n" 02364 "Meetme: %s\r\n" 02365 "Usernum: %i\r\n" 02366 "Status: off\r\n", 02367 chan->name, chan->uniqueid, conf->confno, user->user_no); 02368 } 02369 02370 /* If I have been kicked, exit the conference */ 02371 if (user->adminflags & ADMINFLAG_KICKME) { 02372 /* You have been kicked. */ 02373 if (!(confflags & CONFFLAG_QUIET) && 02374 !ast_streamfile(chan, "conf-kicked", chan->language)) { 02375 ast_waitstream(chan, ""); 02376 } 02377 ret = 0; 02378 break; 02379 } 02380 02381 /* Perform an extra hangup check just in case */ 02382 if (ast_check_hangup(chan)) 02383 break; 02384 02385 c = ast_waitfor_nandfds(&chan, 1, &fd, nfds, NULL, &outfd, &ms); 02386 02387 if (c) { 02388 char dtmfstr[2] = ""; 02389 02390 if (c->fds[0] != origfd || (user->dahdichannel && (c->audiohooks || c->monitor))) { 02391 if (using_pseudo) { 02392 /* Kill old pseudo */ 02393 close(fd); 02394 using_pseudo = 0; 02395 } 02396 ast_debug(1, "Ooh, something swapped out under us, starting over\n"); 02397 retrydahdi = (strcasecmp(c->tech->type, "DAHDI") || (c->audiohooks || c->monitor) ? 1 : 0); 02398 user->dahdichannel = !retrydahdi; 02399 goto dahdiretry; 02400 } 02401 if ((confflags & CONFFLAG_MONITOR) || (user->adminflags & (ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED))) 02402 f = ast_read_noaudio(c); 02403 else 02404 f = ast_read(c); 02405 if (!f) 02406 break; 02407 if (f->frametype == AST_FRAME_DTMF) { 02408 dtmfstr[0] = f->subclass; 02409 dtmfstr[1] = '\0'; 02410 } 02411 02412 if ((f->frametype == AST_FRAME_VOICE) && (f->subclass == AST_FORMAT_SLINEAR)) { 02413 if (user->talk.actual) 02414 ast_frame_adjust_volume(f, user->talk.actual); 02415 02416 if (confflags & (CONFFLAG_OPTIMIZETALKER | CONFFLAG_MONITORTALKER)) { 02417 int totalsilence; 02418 02419 if (user->talking == -1) 02420 user->talking = 0; 02421 02422 res = ast_dsp_silence(dsp, f, &totalsilence); 02423 if (!user->talking && totalsilence < MEETME_DELAYDETECTTALK) { 02424 user->talking = 1; 02425 if (confflags & CONFFLAG_MONITORTALKER) 02426 manager_event(EVENT_FLAG_CALL, "MeetmeTalking", 02427 "Channel: %s\r\n" 02428 "Uniqueid: %s\r\n" 02429 "Meetme: %s\r\n" 02430 "Usernum: %d\r\n" 02431 "Status: on\r\n", 02432 chan->name, chan->uniqueid, conf->confno, user->user_no); 02433 } 02434 if (user->talking && totalsilence > MEETME_DELAYDETECTENDTALK) { 02435 user->talking = 0; 02436 if (confflags & CONFFLAG_MONITORTALKER) 02437 manager_event(EVENT_FLAG_CALL, "MeetmeTalking", 02438 "Channel: %s\r\n" 02439 "Uniqueid: %s\r\n" 02440 "Meetme: %s\r\n" 02441 "Usernum: %d\r\n" 02442 "Status: off\r\n", 02443 chan->name, chan->uniqueid, conf->confno, user->user_no); 02444 } 02445 } 02446 if (using_pseudo) { 02447 /* Absolutely do _not_ use careful_write here... 02448 it is important that we read data from the channel 02449 as fast as it arrives, and feed it into the conference. 02450 The buffering in the pseudo channel will take care of any 02451 timing differences, unless they are so drastic as to lose 02452 audio frames (in which case carefully writing would only 02453 have delayed the audio even further). 02454 */ 02455 /* As it turns out, we do want to use careful write. We just 02456 don't want to block, but we do want to at least *try* 02457 to write out all the samples. 02458 */ 02459 if (user->talking && !(confflags & CONFFLAG_OPTIMIZETALKER)) { 02460 careful_write(fd, f->data, f->datalen, 0); 02461 } 02462 } 02463 } else if (((f->frametype == AST_FRAME_DTMF) && (f->subclass == '*') && (confflags & CONFFLAG_STARMENU)) || ((f->frametype == AST_FRAME_DTMF) && menu_active)) { 02464 if (confflags & CONFFLAG_PASS_DTMF) 02465 conf_queue_dtmf(conf, user, f); 02466 if (ioctl(fd, DAHDI_SETCONF, &dahdic_empty)) { 02467 ast_log(LOG_WARNING, "Error setting conference\n"); 02468 close(fd); 02469 ast_frfree(f); 02470 goto outrun; 02471 } 02472 02473 /* if we are entering the menu, and the user has a channel-driver 02474 volume adjustment, clear it 02475 */ 02476 if (!menu_active && user->talk.desired && !user->talk.actual) 02477 set_talk_volume(user, 0); 02478 02479 if (musiconhold) { 02480 ast_moh_stop(chan); 02481 } 02482 if ((confflags & CONFFLAG_ADMIN)) { 02483 /* Admin menu */ 02484 if (!menu_active) { 02485 menu_active = 1; 02486 /* Record this sound! */ 02487 if (!ast_streamfile(chan, "conf-adminmenu", chan->language)) { 02488 dtmf = ast_waitstream(chan, AST_DIGIT_ANY); 02489 ast_stopstream(chan); 02490 } else 02491 dtmf = 0; 02492 } else 02493 dtmf = f->subclass; 02494 if (dtmf) { 02495 switch(dtmf) { 02496 case '1': /* Un/Mute */ 02497 menu_active = 0; 02498 02499 /* for admin, change both admin and use flags */ 02500 if (user->adminflags & (ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED)) 02501 user->adminflags &= ~(ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED); 02502 else 02503 user->adminflags |= (ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED); 02504 02505 if ((confflags & CONFFLAG_MONITOR) || (user->adminflags & (ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED))) { 02506 if (!ast_streamfile(chan, "conf-muted", chan->language)) 02507 ast_waitstream(chan, ""); 02508 } else { 02509 if (!ast_streamfile(chan, "conf-unmuted", chan->language)) 02510 ast_waitstream(chan, ""); 02511 } 02512 break; 02513 case '2': /* Un/Lock the Conference */ 02514 menu_active = 0; 02515 if (conf->locked) { 02516 conf->locked = 0; 02517 if (!ast_streamfile(chan, "conf-unlockednow", chan->language)) 02518 ast_waitstream(chan, ""); 02519 } else { 02520 conf->locked = 1; 02521 if (!ast_streamfile(chan, "conf-lockednow", chan->language)) 02522 ast_waitstream(chan, ""); 02523 } 02524 break; 02525 case '3': /* Eject last user */ 02526 menu_active = 0; 02527 usr = AST_LIST_LAST(&conf->userlist); 02528 if ((usr->chan->name == chan->name)||(usr->userflags & CONFFLAG_ADMIN)) { 02529 if (!ast_streamfile(chan, "conf-errormenu", chan->language)) 02530 ast_waitstream(chan, ""); 02531 } else 02532 usr->adminflags |= ADMINFLAG_KICKME; 02533 ast_stopstream(chan); 02534 break; 02535 case '4': 02536 tweak_listen_volume(user, VOL_DOWN); 02537 break; 02538 case '6': 02539 tweak_listen_volume(user, VOL_UP); 02540 break; 02541 case '7': 02542 tweak_talk_volume(user, VOL_DOWN); 02543 break; 02544 case '8': 02545 menu_active = 0; 02546 break; 02547 case '9': 02548 tweak_talk_volume(user, VOL_UP); 02549 break; 02550 default: 02551 menu_active = 0; 02552 /* Play an error message! */ 02553 if (!ast_streamfile(chan, "conf-errormenu", chan->language)) 02554 ast_waitstream(chan, ""); 02555 break; 02556 } 02557 } 02558 } else { 02559 /* User menu */ 02560 if (!menu_active) { 02561 menu_active = 1; 02562 if (!ast_streamfile(chan, "conf-usermenu", chan->language)) { 02563 dtmf = ast_waitstream(chan, AST_DIGIT_ANY); 02564 ast_stopstream(chan); 02565 } else 02566 dtmf = 0; 02567 } else 02568 dtmf = f->subclass; 02569 if (dtmf) { 02570 switch(dtmf) { 02571 case '1': /* Un/Mute */ 02572 menu_active = 0; 02573 02574 /* user can only toggle the self-muted state */ 02575 user->adminflags ^= ADMINFLAG_SELFMUTED; 02576 02577 /* they can't override the admin mute state */ 02578 if ((confflags & CONFFLAG_MONITOR) || (user->adminflags & (ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED))) { 02579 if (!ast_streamfile(chan, "conf-muted", chan->language)) 02580 ast_waitstream(chan, ""); 02581 } else { 02582 if (!ast_streamfile(chan, "conf-unmuted", chan->language)) 02583 ast_waitstream(chan, ""); 02584 } 02585 break; 02586 case '2': 02587 menu_active = 0; 02588 if (user->adminflags & (ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED)) 02589 user->adminflags |= ADMINFLAG_T_REQUEST; 02590 02591 if (user->adminflags & ADMINFLAG_T_REQUEST) 02592 if (!ast_streamfile(chan, "beep", chan->language)) 02593 ast_waitstream(chan, ""); 02594 break; 02595 case '4': 02596 tweak_listen_volume(user, VOL_DOWN); 02597 break; 02598 case '6': 02599 tweak_listen_volume(user, VOL_UP); 02600 break; 02601 case '7': 02602 tweak_talk_volume(user, VOL_DOWN); 02603 break; 02604 case '8': 02605 menu_active = 0; 02606 break; 02607 case '9': 02608 tweak_talk_volume(user, VOL_UP); 02609 break; 02610 default: 02611 menu_active = 0; 02612 if (!ast_streamfile(chan, "conf-errormenu", chan->language)) 02613 ast_waitstream(chan, ""); 02614 break; 02615 } 02616 } 02617 } 02618 if (musiconhold) 02619 conf_start_moh(chan, optargs[OPT_ARG_MOH_CLASS]); 02620 02621 if (ioctl(fd, DAHDI_SETCONF, &dahdic)) { 02622 ast_log(LOG_WARNING, "Error setting conference\n"); 02623 close(fd); 02624 ast_frfree(f); 02625 goto outrun; 02626 } 02627 02628 conf_flush(fd, chan); 02629 /* Since this option could absorb dtmf meant for the previous (menu), we have to check this one last */ 02630 } else if ((f->frametype == AST_FRAME_DTMF) && (confflags & CONFFLAG_EXIT_CONTEXT) && ast_exists_extension(chan, exitcontext, dtmfstr, 1, "")) { 02631 if (confflags & CONFFLAG_PASS_DTMF) 02632 conf_queue_dtmf(conf, user, f); 02633 02634 if (!ast_goto_if_exists(chan, exitcontext, dtmfstr, 1)) { 02635 ast_debug(1, "Got DTMF %c, goto context %s\n", dtmfstr[0], exitcontext); 02636 ret = 0; 02637 ast_frfree(f); 02638 break; 02639 } else { 02640 ast_debug(2, "Exit by single digit did not work in meetme. Extension %s does not exist in context %s\n", dtmfstr, exitcontext); 02641 } 02642 } else if ((f->frametype == AST_FRAME_DTMF) && (confflags & CONFFLAG_KEYEXIT) && (strchr(exitkeys, f->subclass))) { 02643 pbx_builtin_setvar_helper(chan, "MEETME_EXIT_KEY", dtmfstr); 02644 02645 if (confflags & CONFFLAG_PASS_DTMF) 02646 conf_queue_dtmf(conf, user, f); 02647 ret = 0; 02648 ast_frfree(f); 02649 break; 02650 } else if ((f->frametype == AST_FRAME_DTMF_BEGIN || f->frametype == AST_FRAME_DTMF_END) 02651 && confflags & CONFFLAG_PASS_DTMF) { 02652 conf_queue_dtmf(conf, user, f); 02653 } else if ((confflags & CONFFLAG_SLA_STATION) && f->frametype == AST_FRAME_CONTROL) { 02654 switch (f->subclass) { 02655 case AST_CONTROL_HOLD: 02656 sla_queue_event_conf(SLA_EVENT_HOLD, chan, conf); 02657 break; 02658 default: 02659 break; 02660 } 02661 } else if (f->frametype == AST_FRAME_NULL) { 02662 /* Ignore NULL frames. It is perfectly normal to get these if the person is muted. */ 02663 } else { 02664 ast_debug(1, 02665 "Got unrecognized frame on channel %s, f->frametype=%d,f->subclass=%d\n", 02666 chan->name, f->frametype, f->subclass); 02667 } 02668 ast_frfree(f); 02669 } else if (outfd > -1) { 02670 res = read(outfd, buf, CONF_SIZE); 02671 if (res > 0) { 02672 memset(&fr, 0, sizeof(fr)); 02673 fr.frametype = AST_FRAME_VOICE; 02674 fr.subclass = AST_FORMAT_SLINEAR; 02675 fr.datalen = res; 02676 fr.samples = res / 2; 02677 fr.data = buf; 02678 fr.offset = AST_FRIENDLY_OFFSET; 02679 if (!user->listen.actual && 02680 ((confflags & CONFFLAG_MONITOR) || 02681 (user->adminflags & (ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED)) || 02682 (!user->talking && (confflags & CONFFLAG_OPTIMIZETALKER)) 02683 )) { 02684 int index; 02685 for (index = 0; index < AST_FRAME_BITS; index++) 02686 if (chan->rawwriteformat & (1 << index)) 02687 break; 02688 if (index >= AST_FRAME_BITS) 02689 goto bailoutandtrynormal; 02690 ast_mutex_lock(&conf->listenlock); 02691 if (!conf->transframe[index]) { 02692 if (conf->origframe) { 02693 if (!conf->transpath[index]) 02694 conf->transpath[index] = ast_translator_build_path((1 << index), AST_FORMAT_SLINEAR); 02695 if (conf->transpath[index]) { 02696 conf->transframe[index] = ast_translate(conf->transpath[index], conf->origframe, 0); 02697 if (!conf->transframe[index]) 02698 conf->transframe[index] = &ast_null_frame; 02699 } 02700 } 02701 } 02702 if (conf->transframe[index]) { 02703 if ((conf->transframe[index]->frametype != AST_FRAME_NULL) && 02704 can_write(chan, confflags)) { 02705 struct ast_frame *cur; 02706 02707 /* the translator may have returned a list of frames, so 02708 write each one onto the channel 02709 */ 02710 for (cur = conf->transframe[index]; cur; cur = AST_LIST_NEXT(cur, frame_list)) { 02711 if (ast_write(chan, cur)) { 02712 ast_log(LOG_WARNING, "Unable to write frame to channel %s\n", chan->name); 02713 break; 02714 } 02715 } 02716 } 02717 } else { 02718 ast_mutex_unlock(&conf->listenlock); 02719 goto bailoutandtrynormal; 02720 } 02721 ast_mutex_unlock(&conf->listenlock); 02722 } else { 02723 bailoutandtrynormal: 02724 if (user->listen.actual) 02725 ast_frame_adjust_volume(&fr, user->listen.actual); 02726 if (can_write(chan, confflags) && ast_write(chan, &fr) < 0) { 02727 ast_log(LOG_WARNING, "Unable to write frame to channel %s\n", chan->name); 02728 } 02729 } 02730 } else 02731 ast_log(LOG_WARNING, "Failed to read frame: %s\n", strerror(errno)); 02732 } 02733 lastmarked = currentmarked; 02734 } 02735 } 02736 02737 if (musiconhold) 02738 ast_moh_stop(chan); 02739 02740 if (using_pseudo) 02741 close(fd); 02742 else { 02743 /* Take out of conference */ 02744 dahdic.chan = 0; 02745 dahdic.confno = 0; 02746 dahdic.confmode = 0; 02747 if (ioctl(fd, DAHDI_SETCONF, &dahdic)) { 02748 ast_log(LOG_WARNING, "Error setting conference\n"); 02749 } 02750 } 02751 02752 reset_volumes(user); 02753 02754 if (!(confflags & CONFFLAG_QUIET) && !(confflags & CONFFLAG_MONITOR) && !(confflags & CONFFLAG_ADMIN)) 02755 conf_play(chan, conf, LEAVE); 02756 02757 if (!(confflags & CONFFLAG_QUIET) && ((confflags & CONFFLAG_INTROUSER) || (confflags & CONFFLAG_INTROUSERNOREVIEW)) && conf->users > 1) { 02758 struct announce_listitem *item; 02759 if (!(item = ao2_alloc(sizeof(*item), NULL))) 02760 return -1; 02761 ast_copy_string(item->namerecloc, user->namerecloc, sizeof(item->namerecloc)); 02762 ast_copy_string(item->language, chan->language, sizeof(item->language)); 02763 item->confchan = conf->chan; 02764 item->confusers = conf->users; 02765 item->announcetype = CONF_HASLEFT; 02766 ast_mutex_lock(&conf->announcelistlock); 02767 AST_LIST_INSERT_TAIL(&conf->announcelist, item, entry); 02768 ast_cond_signal(&conf->announcelist_addition); 02769 ast_mutex_unlock(&conf->announcelistlock); 02770 } else if (!(confflags & CONFFLAG_QUIET) && ((confflags & CONFFLAG_INTROUSER) || (confflags & CONFFLAG_INTROUSERNOREVIEW)) && conf->users == 1) { 02771 /* Last person is leaving, so no reason to try and announce, but should delete the name recording */ 02772 ast_filedelete(user->namerecloc, NULL); 02773 } 02774 02775 outrun: 02776 AST_LIST_LOCK(&confs); 02777 02778 if (dsp) 02779 ast_dsp_free(dsp); 02780 02781 if (user->user_no) { /* Only cleanup users who really joined! */ 02782 now = ast_tvnow(); 02783 hr = (now.tv_sec - user->jointime) / 3600; 02784 min = ((now.tv_sec - user->jointime) % 3600) / 60; 02785 sec = (now.tv_sec - user->jointime) % 60; 02786 02787 if (sent_event) { 02788 manager_event(EVENT_FLAG_CALL, "MeetmeLeave", 02789 "Channel: %s\r\n" 02790 "Uniqueid: %s\r\n" 02791 "Meetme: %s\r\n" 02792 "Usernum: %d\r\n" 02793 "CallerIDNum: %s\r\n" 02794 "CallerIDName: %s\r\n" 02795 "Duration: %ld\r\n", 02796 chan->name, chan->uniqueid, conf->confno, 02797 user->user_no, 02798 S_OR(user->chan->cid.cid_num, "<unknown>"), 02799 S_OR(user->chan->cid.cid_name, "<unknown>"), 02800 (long)(now.tv_sec - user->jointime)); 02801 } 02802 02803 if (setusercount) { 02804 conf->users--; 02805 if (rt_log_members) { 02806 /* Update table */ 02807 snprintf(members, sizeof(members), "%d", conf->users); 02808 ast_update_realtime("meetme", "confno", conf->confno, "members", members, NULL); 02809 } 02810 if (confflags & CONFFLAG_MARKEDUSER) 02811 conf->markedusers--; 02812 } 02813 /* Remove ourselves from the list */ 02814 AST_LIST_REMOVE(&conf->userlist, user, list); 02815 02816 /* Change any states */ 02817 if (!conf->users) 02818 ast_devstate_changed(AST_DEVICE_NOT_INUSE, "meetme:%s", conf->confno); 02819 02820 /* Return the number of seconds the user was in the conf */ 02821 snprintf(meetmesecs, sizeof(meetmesecs), "%d", (int) (time(NULL) - user->jointime)); 02822 pbx_builtin_setvar_helper(chan, "MEETMESECS", meetmesecs); 02823 } 02824 ast_free(user); 02825 AST_LIST_UNLOCK(&confs); 02826 02827 return ret; 02828 }
static void conf_start_moh | ( | struct ast_channel * | chan, | |
const char * | musicclass | |||
) | [static] |
Definition at line 1512 of file app_meetme.c.
References ast_channel_lock, ast_channel_unlock, ast_moh_start(), ast_strdupa, ast_string_field_set, chan, and ast_channel::musicclass.
Referenced by conf_run().
01513 { 01514 char *original_moh; 01515 01516 ast_channel_lock(chan); 01517 original_moh = ast_strdupa(chan->musicclass); 01518 ast_string_field_set(chan, musicclass, musicclass); 01519 ast_channel_unlock(chan); 01520 01521 ast_moh_start(chan, original_moh, NULL); 01522 01523 ast_channel_lock(chan); 01524 ast_string_field_set(chan, musicclass, original_moh); 01525 ast_channel_unlock(chan); 01526 }
static int count_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
The MeetmeCount application.
Definition at line 3066 of file app_meetme.c.
References ast_channel::_state, 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(), chan, dispose_conf(), find_conf(), LOG_WARNING, pbx_builtin_setvar_helper(), and ast_conference::users.
Referenced by load_module().
03067 { 03068 int res = 0; 03069 struct ast_conference *conf; 03070 int count; 03071 char *localdata; 03072 char val[80] = "0"; 03073 AST_DECLARE_APP_ARGS(args, 03074 AST_APP_ARG(confno); 03075 AST_APP_ARG(varname); 03076 ); 03077 03078 if (ast_strlen_zero(data)) { 03079 ast_log(LOG_WARNING, "MeetMeCount requires an argument (conference number)\n"); 03080 return -1; 03081 } 03082 03083 if (!(localdata = ast_strdupa(data))) 03084 return -1; 03085 03086 AST_STANDARD_APP_ARGS(args, localdata); 03087 03088 conf = find_conf(chan, args.confno, 0, 0, NULL, 0, 1, NULL); 03089 03090 if (conf) { 03091 count = conf->users; 03092 dispose_conf(conf); 03093 conf = NULL; 03094 } else 03095 count = 0; 03096 03097 if (!ast_strlen_zero(args.varname)) { 03098 /* have var so load it and exit */ 03099 snprintf(val, sizeof(val), "%d", count); 03100 pbx_builtin_setvar_helper(chan, args.varname, val); 03101 } else { 03102 if (chan->_state != AST_STATE_UP) 03103 ast_answer(chan); 03104 res = ast_say_number(chan, count, "", chan->language, (char *) NULL); /* Needs gender */ 03105 } 03106 03107 return res; 03108 }
static struct sla_trunk_ref* create_trunk_ref | ( | struct sla_trunk * | trunk | ) | [static] |
Definition at line 5121 of file app_meetme.c.
References ast_calloc, and sla_trunk_ref::trunk.
Referenced by sla_add_trunk_to_station().
05122 { 05123 struct sla_trunk_ref *trunk_ref; 05124 05125 if (!(trunk_ref = ast_calloc(1, sizeof(*trunk_ref)))) 05126 return NULL; 05127 05128 trunk_ref->trunk = trunk; 05129 05130 return trunk_ref; 05131 }
static void destroy_station | ( | struct sla_station * | station | ) | [static] |
Definition at line 5332 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, announce_listitem::entry, exten, sla_trunk::name, sla_station::name, PRIORITY_HINT, sla_registrar, sla_trunk_ref::trunk, and sla_station::trunks.
Referenced by sla_destroy().
05333 { 05334 struct sla_trunk_ref *trunk_ref; 05335 05336 if (!ast_strlen_zero(station->autocontext)) { 05337 AST_RWLIST_RDLOCK(&sla_trunks); 05338 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) { 05339 char exten[AST_MAX_EXTENSION]; 05340 char hint[AST_MAX_APP]; 05341 snprintf(exten, sizeof(exten), "%s_%s", station->name, trunk_ref->trunk->name); 05342 snprintf(hint, sizeof(hint), "SLA:%s", exten); 05343 ast_context_remove_extension(station->autocontext, exten, 05344 1, sla_registrar); 05345 ast_context_remove_extension(station->autocontext, hint, 05346 PRIORITY_HINT, sla_registrar); 05347 } 05348 AST_RWLIST_UNLOCK(&sla_trunks); 05349 } 05350 05351 while ((trunk_ref = AST_LIST_REMOVE_HEAD(&station->trunks, entry))) 05352 ast_free(trunk_ref); 05353 05354 ast_string_field_free_memory(station); 05355 ast_free(station); 05356 }
static void destroy_trunk | ( | struct sla_trunk * | trunk | ) | [static] |
Definition at line 5318 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, announce_listitem::entry, sla_registrar, and sla_trunk::stations.
Referenced by sla_destroy().
05319 { 05320 struct sla_station_ref *station_ref; 05321 05322 if (!ast_strlen_zero(trunk->autocontext)) 05323 ast_context_remove_extension(trunk->autocontext, "s", 1, sla_registrar); 05324 05325 while ((station_ref = AST_LIST_REMOVE_HEAD(&trunk->stations, entry))) 05326 ast_free(station_ref); 05327 05328 ast_string_field_free_memory(trunk); 05329 ast_free(trunk); 05330 }
static void* dial_trunk | ( | void * | data | ) | [static] |
Definition at line 4833 of file app_meetme.c.
References 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_free, ast_mutex_lock(), ast_mutex_unlock(), ast_strdup, ast_strdupa, ast_strlen_zero(), sla_trunk::chan, sla_trunk_ref::chan, ast_channel::cid, ast_callerid::cid_name, cid_name, ast_callerid::cid_num, cid_num, dial_trunk_args::cond, dial_trunk_args::cond_lock, sla_trunk::device, MAX_CONFNUM, sla, strsep(), sla_trunk_ref::trunk, and dial_trunk_args::trunk_ref.
Referenced by sla_station_exec().
04834 { 04835 struct dial_trunk_args *args = data; 04836 struct ast_dial *dial; 04837 char *tech, *tech_data; 04838 enum ast_dial_result dial_res; 04839 char conf_name[MAX_CONFNUM]; 04840 struct ast_conference *conf; 04841 struct ast_flags conf_flags = { 0 }; 04842 struct sla_trunk_ref *trunk_ref = args->trunk_ref; 04843 const char *cid_name = NULL, *cid_num = NULL; 04844 04845 if (!(dial = ast_dial_create())) { 04846 ast_mutex_lock(args->cond_lock); 04847 ast_cond_signal(args->cond); 04848 ast_mutex_unlock(args->cond_lock); 04849 return NULL; 04850 } 04851 04852 tech_data = ast_strdupa(trunk_ref->trunk->device); 04853 tech = strsep(&tech_data, "/"); 04854 if (ast_dial_append(dial, tech, tech_data) == -1) { 04855 ast_mutex_lock(args->cond_lock); 04856 ast_cond_signal(args->cond); 04857 ast_mutex_unlock(args->cond_lock); 04858 ast_dial_destroy(dial); 04859 return NULL; 04860 } 04861 04862 if (!sla.attempt_callerid && !ast_strlen_zero(trunk_ref->chan->cid.cid_name)) { 04863 cid_name = ast_strdupa(trunk_ref->chan->cid.cid_name); 04864 ast_free(trunk_ref->chan->cid.cid_name); 04865 trunk_ref->chan->cid.cid_name = NULL; 04866 } 04867 if (!sla.attempt_callerid && !ast_strlen_zero(trunk_ref->chan->cid.cid_num)) { 04868 cid_num = ast_strdupa(trunk_ref->chan->cid.cid_num); 04869 ast_free(trunk_ref->chan->cid.cid_num); 04870 trunk_ref->chan->cid.cid_num = NULL; 04871 } 04872 04873 dial_res = ast_dial_run(dial, trunk_ref->chan, 1); 04874 04875 if (cid_name) 04876 trunk_ref->chan->cid.cid_name = ast_strdup(cid_name); 04877 if (cid_num) 04878 trunk_ref->chan->cid.cid_num = ast_strdup(cid_num); 04879 04880 if (dial_res != AST_DIAL_RESULT_TRYING) { 04881 ast_mutex_lock(args->cond_lock); 04882 ast_cond_signal(args->cond); 04883 ast_mutex_unlock(args->cond_lock); 04884 ast_dial_destroy(dial); 04885 return NULL; 04886 } 04887 04888 for (;;) { 04889 unsigned int done = 0; 04890 switch ((dial_res = ast_dial_state(dial))) { 04891 case AST_DIAL_RESULT_ANSWERED: 04892 trunk_ref->trunk->chan = ast_dial_answered(dial); 04893 case AST_DIAL_RESULT_HANGUP: 04894 case AST_DIAL_RESULT_INVALID: 04895 case AST_DIAL_RESULT_FAILED: 04896 case AST_DIAL_RESULT_TIMEOUT: 04897 case AST_DIAL_RESULT_UNANSWERED: 04898 done = 1; 04899 case AST_DIAL_RESULT_TRYING: 04900 case AST_DIAL_RESULT_RINGING: 04901 case AST_DIAL_RESULT_PROGRESS: 04902 case AST_DIAL_RESULT_PROCEEDING: 04903 break; 04904 } 04905 if (done) 04906 break; 04907 } 04908 04909 if (!trunk_ref->trunk->chan) { 04910 ast_mutex_lock(args->cond_lock); 04911 ast_cond_signal(args->cond); 04912 ast_mutex_unlock(args->cond_lock); 04913 ast_dial_join(dial); 04914 ast_dial_destroy(dial); 04915 return NULL; 04916 } 04917 04918 snprintf(conf_name, sizeof(conf_name), "SLA_%s", trunk_ref->trunk->name); 04919 ast_set_flag(&conf_flags, 04920 CONFFLAG_QUIET | CONFFLAG_MARKEDEXIT | CONFFLAG_MARKEDUSER | 04921 CONFFLAG_PASS_DTMF | CONFFLAG_SLA_TRUNK); 04922 conf = build_conf(conf_name, "", "", 1, 1, 1, trunk_ref->trunk->chan); 04923 04924 ast_mutex_lock(args->cond_lock); 04925 ast_cond_signal(args->cond); 04926 ast_mutex_unlock(args->cond_lock); 04927 04928 if (conf) { 04929 conf_run(trunk_ref->trunk->chan, conf, conf_flags.flags, NULL); 04930 dispose_conf(conf); 04931 conf = NULL; 04932 } 04933 04934 /* If the trunk is going away, it is definitely now IDLE. */ 04935 sla_change_trunk_state(trunk_ref->trunk, SLA_TRUNK_STATE_IDLE, ALL_TRUNK_REFS, NULL); 04936 04937 trunk_ref->trunk->chan = NULL; 04938 trunk_ref->trunk->on_hold = 0; 04939 04940 ast_dial_join(dial); 04941 ast_dial_destroy(dial); 04942 04943 return NULL; 04944 }
static int dispose_conf | ( | struct ast_conference * | conf | ) | [static] |
Definition at line 1494 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().
01495 { 01496 int res = 0; 01497 int confno_int = 0; 01498 01499 AST_LIST_LOCK(&confs); 01500 if (ast_atomic_dec_and_test(&conf->refcount)) { 01501 /* Take the conference room number out of an inuse state */ 01502 if ((sscanf(conf->confno, "%d", &confno_int) == 1) && (confno_int >= 0 && confno_int < 1024)) 01503 conf_map[confno_int] = 0; 01504 conf_free(conf); 01505 res = 1; 01506 } 01507 AST_LIST_UNLOCK(&confs); 01508 01509 return res; 01510 }
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_flags * | confflags | |||
) | [static] |
Definition at line 2968 of file app_meetme.c.
References AST_APP_ARG, ast_app_getdata(), ast_clear_flag, ast_config_destroy(), ast_config_load, ast_debug, AST_DECLARE_APP_ARGS, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), AST_STANDARD_APP_ARGS, ast_strdupa, ast_test_flag, ast_variable_browse(), build_conf(), ast_conference::chan, chan, CONFFLAG_INTROUSER, CONFFLAG_INTROUSERNOREVIEW, CONFFLAG_QUIET, CONFFLAG_RECORDCONF, CONFIG_FILE_NAME, ast_conference::confno, ast_conference::list, LOG_WARNING, parse(), ast_conference::refcount, S_OR, and var.
Referenced by conf_exec(), and count_exec().
02970 { 02971 struct ast_config *cfg; 02972 struct ast_variable *var; 02973 struct ast_flags config_flags = { 0 }; 02974 struct ast_conference *cnf; 02975 char *parse; 02976 AST_DECLARE_APP_ARGS(args, 02977 AST_APP_ARG(confno); 02978 AST_APP_ARG(pin); 02979 AST_APP_ARG(pinadmin); 02980 ); 02981 02982 /* Check first in the conference list */ 02983 ast_debug(1, "The requested confno is '%s'?\n", confno); 02984 AST_LIST_LOCK(&confs); 02985 AST_LIST_TRAVERSE(&confs, cnf, list) { 02986 ast_debug(3, "Does conf %s match %s?\n", confno, cnf->confno); 02987 if (!strcmp(confno, cnf->confno)) 02988 break; 02989 } 02990 if (cnf) { 02991 cnf->refcount += refcount; 02992 } 02993 AST_LIST_UNLOCK(&confs); 02994 02995 if (!cnf) { 02996 if (dynamic) { 02997 /* No need to parse meetme.conf */ 02998 ast_debug(1, "Building dynamic conference '%s'\n", confno); 02999 if (dynamic_pin) { 03000 if (dynamic_pin[0] == 'q') { 03001 /* Query the user to enter a PIN */ 03002 if (ast_app_getdata(chan, "conf-getpin", dynamic_pin, pin_buf_len - 1, 0) < 0) 03003 return NULL; 03004 } 03005 cnf = build_conf(confno, dynamic_pin, "", make, dynamic, refcount, chan); 03006 } else { 03007 cnf = build_conf(confno, "", "", make, dynamic, refcount, chan); 03008 } 03009 } else { 03010 /* Check the config */ 03011 cfg = ast_config_load(CONFIG_FILE_NAME, config_flags); 03012 if (!cfg) { 03013 ast_log(LOG_WARNING, "No %s file :(\n", CONFIG_FILE_NAME); 03014 return NULL; 03015 } 03016 for (var = ast_variable_browse(cfg, "rooms"); var; var = var->next) { 03017 if (strcasecmp(var->name, "conf")) 03018 continue; 03019 03020 if (!(parse = ast_strdupa(var->value))) 03021 return NULL; 03022 03023 AST_STANDARD_APP_ARGS(args, parse); 03024 ast_debug(3, "Will conf %s match %s?\n", confno, args.confno); 03025 if (!strcasecmp(args.confno, confno)) { 03026 /* Bingo it's a valid conference */ 03027 cnf = build_conf(args.confno, 03028 S_OR(args.pin, ""), 03029 S_OR(args.pinadmin, ""), 03030 make, dynamic, refcount, chan); 03031 break; 03032 } 03033 } 03034 if (!var) { 03035 ast_debug(1, "%s isn't a valid conference\n", confno); 03036 } 03037 ast_config_destroy(cfg); 03038 } 03039 } else if (dynamic_pin) { 03040 /* Correct for the user selecting 'D' instead of 'd' to have 03041 someone join into a conference that has already been created 03042 with a pin. */ 03043 if (dynamic_pin[0] == 'q') 03044 dynamic_pin[0] = '\0'; 03045 } 03046 03047 if (cnf) { 03048 if (confflags && !cnf->chan && 03049 !ast_test_flag(confflags, CONFFLAG_QUIET) && 03050 ast_test_flag(confflags, CONFFLAG_INTROUSER | CONFFLAG_INTROUSERNOREVIEW)) { 03051 ast_log(LOG_WARNING, "No DAHDI channel available for conference, user introduction disabled (is chan_dahdi loaded?)\n"); 03052 ast_clear_flag(confflags, CONFFLAG_INTROUSER | CONFFLAG_INTROUSERNOREVIEW); 03053 } 03054 03055 if (confflags && !cnf->chan && 03056 ast_test_flag(confflags, CONFFLAG_RECORDCONF)) { 03057 ast_log(LOG_WARNING, "No DAHDI channel available for conference, conference recording disabled (is chan_dahdi loaded?)\n"); 03058 ast_clear_flag(confflags, CONFFLAG_RECORDCONF); 03059 } 03060 } 03061 03062 return cnf; 03063 }
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_flags * | confflags, | |||
char * | optargs[], | |||
int * | too_early | |||
) | [static] |
Definition at line 2830 of file app_meetme.c.
References ast_clear_flag, ast_copy_string(), ast_debug, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_load_realtime(), ast_localtime(), ast_log(), ast_mktime(), ast_strdupa, ast_streamfile(), ast_strftime(), ast_test_flag, ast_tvnow(), ast_variables_destroy(), ast_waitstream(), build_conf(), ast_conference::chan, chan, CONFFLAG_INTROUSER, CONFFLAG_INTROUSERNOREVIEW, CONFFLAG_QUIET, CONFFLAG_RECORDCONF, ast_conference::confno, DATE_FORMAT, ast_conference::endalert, ast_conference::endtime, ast_channel::language, ast_conference::list, LOG_WARNING, ast_conference::maxusers, ast_conference::refcount, and var.
Referenced by conf_exec().
02833 { 02834 struct ast_variable *var; 02835 struct ast_conference *cnf; 02836 02837 *too_early = 0; 02838 02839 /* Check first in the conference list */ 02840 AST_LIST_LOCK(&confs); 02841 AST_LIST_TRAVERSE(&confs, cnf, list) { 02842 if (!strcmp(confno, cnf->confno)) 02843 break; 02844 } 02845 if (cnf) { 02846 cnf->refcount += refcount; 02847 } 02848 AST_LIST_UNLOCK(&confs); 02849 02850 if (!cnf) { 02851 char *pin = NULL, *pinadmin = NULL; /* For temp use */ 02852 int maxusers = 0; 02853 struct timeval now; 02854 char currenttime[19] = ""; 02855 char eatime[19] = ""; 02856 char useropts[32] = ""; 02857 char adminopts[32] = ""; 02858 struct ast_tm tm, etm; 02859 struct timeval endtime = { .tv_sec = 0 }; 02860 02861 if (rt_schedule) { 02862 now = ast_tvnow(); 02863 02864 ast_localtime(&now, &tm, NULL); 02865 ast_strftime(currenttime, sizeof(currenttime), DATE_FORMAT, &tm); 02866 02867 ast_debug(1, "Looking for conference %s that starts after %s\n", confno, eatime); 02868 02869 var = ast_load_realtime("meetme", "confno", 02870 confno, "starttime <= ", currenttime, "endtime >= ", 02871 currenttime, NULL); 02872 02873 if (!var && fuzzystart) { 02874 now = ast_tvnow(); 02875 now.tv_sec += fuzzystart; 02876 02877 ast_localtime(&now, &tm, NULL); 02878 ast_strftime(currenttime, sizeof(currenttime), DATE_FORMAT, &tm); 02879 var = ast_load_realtime("meetme", "confno", 02880 confno, "starttime <= ", currenttime, "endtime >= ", 02881 currenttime, NULL); 02882 } 02883 02884 if (!var && earlyalert) { 02885 now = ast_tvnow(); 02886 now.tv_sec += earlyalert; 02887 ast_localtime(&now, &etm, NULL); 02888 ast_strftime(eatime, sizeof(eatime), DATE_FORMAT, &etm); 02889 var = ast_load_realtime("meetme", "confno", 02890 confno, "starttime <= ", eatime, "endtime >= ", 02891 currenttime, NULL); 02892 if (var) 02893 *too_early = 1; 02894 } 02895 02896 } else 02897 var = ast_load_realtime("meetme", "confno", confno, NULL); 02898 02899 if (!var) 02900 return NULL; 02901 02902 if (rt_schedule && *too_early) { 02903 /* Announce that the caller is early and exit */ 02904 if (!ast_streamfile(chan, "conf-has-not-started", chan->language)) 02905 ast_waitstream(chan, ""); 02906 ast_variables_destroy(var); 02907 return NULL; 02908 } 02909 02910 while (var) { 02911 if (!strcasecmp(var->name, "pin")) { 02912 pin = ast_strdupa(var->value); 02913 } else if (!strcasecmp(var->name, "adminpin")) { 02914 pinadmin = ast_strdupa(var->value); 02915 } else if (!strcasecmp(var->name, "opts")) { 02916 ast_copy_string(useropts, var->value, sizeof(useropts)); 02917 } else if (!strcasecmp(var->name, "maxusers")) { 02918 maxusers = atoi(var->value); 02919 } else if (!strcasecmp(var->name, "adminopts")) { 02920 ast_copy_string(adminopts, var->value, sizeof(adminopts)); 02921 } else if (!strcasecmp(var->name, "endtime")) { 02922 union { 02923 struct ast_tm atm; 02924 struct tm tm; 02925 } t = { { 0, }, }; 02926 strptime(var->value, "%Y-%m-%d %H:%M:%S", &t.tm); 02927 /* strptime does not determine if a time is 02928 * in DST or not. Set tm_isdst to -1 to 02929 * allow ast_mktime to adjust for DST 02930 * if needed */ 02931 t.tm.tm_isdst = -1; 02932 endtime = ast_mktime(&t.atm, NULL); 02933 } 02934 02935 var = var->next; 02936 } 02937 02938 ast_variables_destroy(var); 02939 02940 cnf = build_conf(confno, pin ? pin : "", pinadmin ? pinadmin : "", make, dynamic, refcount, chan); 02941 02942 if (cnf) { 02943 cnf->maxusers = maxusers; 02944 cnf->endalert = endalert; 02945 cnf->endtime = endtime.tv_sec; 02946 } 02947 } 02948 02949 if (cnf) { 02950 if (confflags && !cnf->chan && 02951 !ast_test_flag(confflags, CONFFLAG_QUIET) && 02952 ast_test_flag(confflags, CONFFLAG_INTROUSER | CONFFLAG_INTROUSERNOREVIEW)) { 02953 ast_log(LOG_WARNING, "No DAHDI channel available for conference, user introduction disabled (is chan_dahdi loaded?)\n"); 02954 ast_clear_flag(confflags, CONFFLAG_INTROUSER | CONFFLAG_INTROUSERNOREVIEW); 02955 } 02956 02957 if (confflags && !cnf->chan && 02958 ast_test_flag(confflags, CONFFLAG_RECORDCONF)) { 02959 ast_log(LOG_WARNING, "No DAHDI channel available for conference, conference recording disabled (is chan_dahdi loaded?)\n"); 02960 ast_clear_flag(confflags, CONFFLAG_RECORDCONF); 02961 } 02962 } 02963 02964 return cnf; 02965 }
static struct ast_conf_user* find_user | ( | struct ast_conference * | conf, | |
char * | callerident | |||
) | [static] |
Definition at line 3358 of file app_meetme.c.
References AST_LIST_TRAVERSE, ast_conf_user::list, user, and ast_conference::userlist.
03359 { 03360 struct ast_conf_user *user = NULL; 03361 int cid; 03362 03363 sscanf(callerident, "%i", &cid); 03364 if (conf && callerident) { 03365 AST_LIST_TRAVERSE(&conf->userlist, user, list) { 03366 if (cid == user->user_no) 03367 return user; 03368 } 03369 } 03370 return NULL; 03371 }
static const char* get_announce_filename | ( | enum announcetypes | type | ) | [static] |
Definition at line 1528 of file app_meetme.c.
References CONF_HASJOIN.
Referenced by announce_thread().
01529 { 01530 switch (type) { 01531 case CONF_HASLEFT: 01532 return "conf-hasleft"; 01533 break; 01534 case CONF_HASJOIN: 01535 return "conf-hasjoin"; 01536 break; 01537 default: 01538 return ""; 01539 } 01540 }
static char* istalking | ( | int | x | ) | [static] |
Definition at line 654 of file app_meetme.c.
00655 { 00656 if (x > 0) 00657 return "(talking)"; 00658 else if (x < 0) 00659 return "(unmonitored)"; 00660 else 00661 return "(not talking)"; 00662 }
static int load_config | ( | int | reload | ) | [static] |
Definition at line 5692 of file app_meetme.c.
References ast_log(), load_config_meetme(), LOG_NOTICE, SLA_EVENT_RELOAD, sla_load_config(), and sla_queue_event().
05693 { 05694 load_config_meetme(); 05695 05696 if (reload) { 05697 sla_queue_event(SLA_EVENT_RELOAD); 05698 ast_log(LOG_NOTICE, "A reload of the SLA configuration has been requested " 05699 "and will be completed when the system is idle.\n"); 05700 return 0; 05701 } 05702 05703 return sla_load_config(0); 05704 }
static void load_config_meetme | ( | void | ) | [static] |
Definition at line 3817 of file app_meetme.c.
References ast_config_destroy(), ast_config_load, ast_log(), ast_true(), ast_variable_retrieve(), CONFIG_FILE_NAME, DEFAULT_AUDIO_BUFFERS, LOG_NOTICE, and LOG_WARNING.
Referenced by load_config().
03818 { 03819 struct ast_config *cfg; 03820 struct ast_flags config_flags = { 0 }; 03821 const char *val; 03822 03823 if (!(cfg = ast_config_load(CONFIG_FILE_NAME, config_flags))) 03824 return; 03825 03826 audio_buffers = DEFAULT_AUDIO_BUFFERS; 03827 03828 /* Scheduling support is off by default */ 03829 rt_schedule = 0; 03830 fuzzystart = 0; 03831 earlyalert = 0; 03832 endalert = 0; 03833 03834 /* Logging of participants defaults to ON for compatibility reasons */ 03835 rt_log_members = 1; 03836 03837 if ((val = ast_variable_retrieve(cfg, "general", "audiobuffers"))) { 03838 if ((sscanf(val, "%d", &audio_buffers) != 1)) { 03839 ast_log(LOG_WARNING, "audiobuffers setting must be a number, not '%s'\n", val); 03840 audio_buffers = DEFAULT_AUDIO_BUFFERS; 03841 } else if ((audio_buffers < DAHDI_DEFAULT_NUM_BUFS) || (audio_buffers > DAHDI_MAX_NUM_BUFS)) { 03842 ast_log(LOG_WARNING, "audiobuffers setting must be between %d and %d\n", 03843 DAHDI_DEFAULT_NUM_BUFS, DAHDI_MAX_NUM_BUFS); 03844 audio_buffers = DEFAULT_AUDIO_BUFFERS; 03845 } 03846 if (audio_buffers != DEFAULT_AUDIO_BUFFERS) 03847 ast_log(LOG_NOTICE, "Audio buffers per channel set to %d\n", audio_buffers); 03848 } 03849 03850 if ((val = ast_variable_retrieve(cfg, "general", "schedule"))) 03851 rt_schedule = ast_true(val); 03852 if ((val = ast_variable_retrieve(cfg, "general", "logmembercount"))) 03853 rt_log_members = ast_true(val); 03854 if ((val = ast_variable_retrieve(cfg, "general", "fuzzystart"))) { 03855 if ((sscanf(val, "%d", &fuzzystart) != 1)) { 03856 ast_log(LOG_WARNING, "fuzzystart must be a number, not '%s'\n", val); 03857 fuzzystart = 0; 03858 } 03859 } 03860 if ((val = ast_variable_retrieve(cfg, "general", "earlyalert"))) { 03861 if ((sscanf(val, "%d", &earlyalert) != 1)) { 03862 ast_log(LOG_WARNING, "earlyalert must be a number, not '%s'\n", val); 03863 earlyalert = 0; 03864 } 03865 } 03866 if ((val = ast_variable_retrieve(cfg, "general", "endalert"))) { 03867 if ((sscanf(val, "%d", &endalert) != 1)) { 03868 ast_log(LOG_WARNING, "endalert must be a number, not '%s'\n", val); 03869 endalert = 0; 03870 } 03871 } 03872 03873 ast_config_destroy(cfg); 03874 }
static int load_module | ( | void | ) | [static] |
Definition at line 5729 of file app_meetme.c.
References action_meetmelist(), action_meetmemute(), action_meetmeunmute(), admin_exec(), ARRAY_LEN, ast_cli_register_multiple(), ast_devstate_prov_add(), ast_manager_register, ast_manager_register2(), ast_register_application, channel_admin_exec(), cli_meetme, conf_exec(), count_exec(), EVENT_FLAG_CALL, EVENT_FLAG_REPORTING, load_config(), meetmestate(), sla_state(), sla_station_exec(), and sla_trunk_exec().
05730 { 05731 int res = 0; 05732 05733 res |= load_config(0); 05734 05735 ast_cli_register_multiple(cli_meetme, ARRAY_LEN(cli_meetme)); 05736 res |= ast_manager_register("MeetmeMute", EVENT_FLAG_CALL, 05737 action_meetmemute, "Mute a Meetme user"); 05738 res |= ast_manager_register("MeetmeUnmute", EVENT_FLAG_CALL, 05739 action_meetmeunmute, "Unmute a Meetme user"); 05740 res |= ast_manager_register2("MeetmeList", EVENT_FLAG_REPORTING, 05741 action_meetmelist, "List participants in a conference", mandescr_meetmelist); 05742 res |= ast_register_application(app4, channel_admin_exec, synopsis4, descrip4); 05743 res |= ast_register_application(app3, admin_exec, synopsis3, descrip3); 05744 res |= ast_register_application(app2, count_exec, synopsis2, descrip2); 05745 res |= ast_register_application(app, conf_exec, synopsis, descrip); 05746 res |= ast_register_application(slastation_app, sla_station_exec, 05747 slastation_synopsis, slastation_desc); 05748 res |= ast_register_application(slatrunk_app, sla_trunk_exec, 05749 slatrunk_synopsis, slatrunk_desc); 05750 05751 res |= ast_devstate_prov_add("Meetme", meetmestate); 05752 res |= ast_devstate_prov_add("SLA", sla_state); 05753 05754 return res; 05755 }
static char* meetme_cmd | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 980 of file app_meetme.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), AST_LIST_EMPTY, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, 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_conf_user::list, ast_conference::locked, ast_conference::markedusers, MC_DATA_FORMAT, MC_HEADER_FORMAT, ast_cli_args::n, ast_cli_args::pos, sec, ast_conference::start, total, ast_cli_entry::usage, ast_conference::users, and ast_cli_args::word.
00981 { 00982 /* Process the command */ 00983 struct ast_conference *cnf; 00984 struct ast_conf_user *user; 00985 int hr, min, sec; 00986 int i = 0, total = 0; 00987 time_t now; 00988 char cmdline[1024] = ""; 00989 #define MC_HEADER_FORMAT "%-14s %-14s %-10s %-8s %-8s %-6s\n" 00990 #define MC_DATA_FORMAT "%-12.12s %4.4d %4.4s %02d:%02d:%02d %-8s %-6s\n" 00991 00992 switch (cmd) { 00993 case CLI_INIT: 00994 e->command = "meetme"; 00995 e->usage = 00996 "Usage: meetme (un)lock|(un)mute|kick|list [concise] <confno> <usernumber>\n" 00997 " Executes a command for the conference or on a conferee\n"; 00998 return NULL; 00999 case CLI_GENERATE: 01000 return complete_meetmecmd(a->line, a->word, a->pos, a->n); 01001 } 01002 01003 if (a->argc > 8) 01004 ast_cli(a->fd, "Invalid Arguments.\n"); 01005 /* Check for length so no buffer will overflow... */ 01006 for (i = 0; i < a->argc; i++) { 01007 if (strlen(a->argv[i]) > 100) 01008 ast_cli(a->fd, "Invalid Arguments.\n"); 01009 } 01010 if (a->argc == 1 || (a->argc == 2 && !strcasecmp(a->argv[1], "concise"))) { 01011 /* 'MeetMe': List all the conferences */ 01012 int concise = (a->argc == 2 && !strcasecmp(a->argv[1], "concise")); 01013 now = time(NULL); 01014 AST_LIST_LOCK(&confs); 01015 if (AST_LIST_EMPTY(&confs)) { 01016 if (!concise) 01017 ast_cli(a->fd, "No active MeetMe conferences.\n"); 01018 AST_LIST_UNLOCK(&confs); 01019 return CLI_SUCCESS; 01020 } 01021 if (!concise) 01022 ast_cli(a->fd, MC_HEADER_FORMAT, "Conf Num", "Parties", "Marked", "Activity", "Creation", "Locked"); 01023 AST_LIST_TRAVERSE(&confs, cnf, list) { 01024 if (cnf->markedusers == 0) 01025 strcpy(cmdline, "N/A "); 01026 else 01027 snprintf(cmdline, sizeof(cmdline), "%4.4d", cnf->markedusers); 01028 hr = (now - cnf->start) / 3600; 01029 min = ((now - cnf->start) % 3600) / 60; 01030 sec = (now - cnf->start) % 60; 01031 if (!concise) 01032 ast_cli(a->fd, MC_DATA_FORMAT, cnf->confno, cnf->users, cmdline, hr, min, sec, cnf->isdynamic ? "Dynamic" : "Static", cnf->locked ? "Yes" : "No"); 01033 else { 01034 ast_cli(a->fd, "%s!%d!%d!%02d:%02d:%02d!%d!%d\n", 01035 cnf->confno, 01036 cnf->users, 01037 cnf->markedusers, 01038 hr, min, sec, 01039 cnf->isdynamic, 01040 cnf->locked); 01041 } 01042 01043 total += cnf->users; 01044 } 01045 AST_LIST_UNLOCK(&confs); 01046 if (!concise) 01047 ast_cli(a->fd, "* Total number of MeetMe users: %d\n", total); 01048 return CLI_SUCCESS; 01049 } 01050 if (a->argc < 3) 01051 return CLI_SHOWUSAGE; 01052 ast_copy_string(cmdline, a->argv[2], sizeof(cmdline)); /* Argv 2: conference number */ 01053 if (strstr(a->argv[1], "lock")) { 01054 if (strcmp(a->argv[1], "lock") == 0) { 01055 /* Lock */ 01056 strncat(cmdline, ",L", sizeof(cmdline) - strlen(cmdline) - 1); 01057 } else { 01058 /* Unlock */ 01059 strncat(cmdline, ",l", sizeof(cmdline) - strlen(cmdline) - 1); 01060 } 01061 } else if (strstr(a->argv[1], "mute")) { 01062 if (a->argc < 4) 01063 return CLI_SHOWUSAGE; 01064 if (strcmp(a->argv[1], "mute") == 0) { 01065 /* Mute */ 01066 if (strcmp(a->argv[3], "all") == 0) { 01067 strncat(cmdline, ",N", sizeof(cmdline) - strlen(cmdline) - 1); 01068 } else { 01069 strncat(cmdline, ",M,", sizeof(cmdline) - strlen(cmdline) - 1); 01070 strncat(cmdline, a->argv[3], sizeof(cmdline) - strlen(cmdline) - 1); 01071 } 01072 } else { 01073 /* Unmute */ 01074 if (strcmp(a->argv[3], "all") == 0) { 01075 strncat(cmdline, ",n", sizeof(cmdline) - strlen(cmdline) - 1); 01076 } else { 01077 strncat(cmdline, ",m,", sizeof(cmdline) - strlen(cmdline) - 1); 01078 strncat(cmdline, a->argv[3], sizeof(cmdline) - strlen(cmdline) - 1); 01079 } 01080 } 01081 } else if (strcmp(a->argv[1], "kick") == 0) { 01082 if (a->argc < 4) 01083 return CLI_SHOWUSAGE; 01084 if (strcmp(a->argv[3], "all") == 0) { 01085 /* Kick all */ 01086 strncat(cmdline, ",K", sizeof(cmdline) - strlen(cmdline) - 1); 01087 } else { 01088 /* Kick a single user */ 01089 strncat(cmdline, ",k,", sizeof(cmdline) - strlen(cmdline) - 1); 01090 strncat(cmdline, a->argv[3], sizeof(cmdline) - strlen(cmdline) - 1); 01091 } 01092 } else if (strcmp(a->argv[1], "list") == 0) { 01093 int concise = (a->argc == 4 && (!strcasecmp(a->argv[3], "concise"))); 01094 /* List all the users in a conference */ 01095 if (AST_LIST_EMPTY(&confs)) { 01096 if (!concise) 01097 ast_cli(a->fd, "No active conferences.\n"); 01098 return CLI_SUCCESS; 01099 } 01100 /* Find the right conference */ 01101 AST_LIST_LOCK(&confs); 01102 AST_LIST_TRAVERSE(&confs, cnf, list) { 01103 if (strcmp(cnf->confno, a->argv[2]) == 0) 01104 break; 01105 } 01106 if (!cnf) { 01107 if (!concise) 01108 ast_cli(a->fd, "No such conference: %s.\n", a->argv[2]); 01109 AST_LIST_UNLOCK(&confs); 01110 return CLI_SUCCESS; 01111 } 01112 /* Show all the users */ 01113 time(&now); 01114 AST_LIST_TRAVERSE(&cnf->userlist, user, list) { 01115 hr = (now - user->jointime) / 3600; 01116 min = ((now - user->jointime) % 3600) / 60; 01117 sec = (now - user->jointime) % 60; 01118 if (!concise) 01119 ast_cli(a->fd, "User #: %-2.2d %12.12s %-20.20s Channel: %s %s %s %s %s %s %02d:%02d:%02d\n", 01120 user->user_no, 01121 S_OR(user->chan->cid.cid_num, "<unknown>"), 01122 S_OR(user->chan->cid.cid_name, "<no name>"), 01123 user->chan->name, 01124 user->userflags & CONFFLAG_ADMIN ? "(Admin)" : "", 01125 user->userflags & CONFFLAG_MONITOR ? "(Listen only)" : "", 01126 user->adminflags & ADMINFLAG_MUTED ? "(Admin Muted)" : user->adminflags & ADMINFLAG_SELFMUTED ? "(Muted)" : "", 01127 user->adminflags & ADMINFLAG_T_REQUEST ? "(Request to Talk)" : "", 01128 istalking(user->talking), hr, min, sec); 01129 else 01130 ast_cli(a->fd, "%d!%s!%s!%s!%s!%s!%s!%s!%d!%02d:%02d:%02d\n", 01131 user->user_no, 01132 S_OR(user->chan->cid.cid_num, ""), 01133 S_OR(user->chan->cid.cid_name, ""), 01134 user->chan->name, 01135 user->userflags & CONFFLAG_ADMIN ? "1" : "", 01136 user->userflags & CONFFLAG_MONITOR ? "1" : "", 01137 user->adminflags & (ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED) ? "1" : "", 01138 user->adminflags & ADMINFLAG_T_REQUEST ? "1" : "", 01139 user->talking, hr, min, sec); 01140 01141 } 01142 if (!concise) 01143 ast_cli(a->fd, "%d users in that conference.\n", cnf->users); 01144 AST_LIST_UNLOCK(&confs); 01145 return CLI_SUCCESS; 01146 } else 01147 return CLI_SHOWUSAGE; 01148 01149 ast_debug(1, "Cmdline: %s\n", cmdline); 01150 01151 admin_exec(NULL, cmdline); 01152 01153 return CLI_SUCCESS; 01154 }
static int meetmemute | ( | struct mansession * | s, | |
const struct message * | m, | |||
int | mute | |||
) | [static] |
Definition at line 3584 of file app_meetme.c.
References ADMINFLAG_MUTED, ADMINFLAG_SELFMUTED, ADMINFLAG_T_REQUEST, 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, s, user, and ast_conference::userlist.
Referenced by action_meetmemute(), and action_meetmeunmute().
03585 { 03586 struct ast_conference *conf; 03587 struct ast_conf_user *user; 03588 const char *confid = astman_get_header(m, "Meetme"); 03589 char *userid = ast_strdupa(astman_get_header(m, "Usernum")); 03590 int userno; 03591 03592 if (ast_strlen_zero(confid)) { 03593 astman_send_error(s, m, "Meetme conference not specified"); 03594 return 0; 03595 } 03596 03597 if (ast_strlen_zero(userid)) { 03598 astman_send_error(s, m, "Meetme user number not specified"); 03599 return 0; 03600 } 03601 03602 userno = strtoul(userid, &userid, 10); 03603 03604 if (*userid) { 03605 astman_send_error(s, m, "Invalid user number"); 03606 return 0; 03607 } 03608 03609 /* Look in the conference list */ 03610 AST_LIST_LOCK(&confs); 03611 AST_LIST_TRAVERSE(&confs, conf, list) { 03612 if (!strcmp(confid, conf->confno)) 03613 break; 03614 } 03615 03616 if (!conf) { 03617 AST_LIST_UNLOCK(&confs); 03618 astman_send_error(s, m, "Meetme conference does not exist"); 03619 return 0; 03620 } 03621 03622 AST_LIST_TRAVERSE(&conf->userlist, user, list) 03623 if (user->user_no == userno) 03624 break; 03625 03626 if (!user) { 03627 AST_LIST_UNLOCK(&confs); 03628 astman_send_error(s, m, "User number not found"); 03629 return 0; 03630 } 03631 03632 if (mute) 03633 user->adminflags |= ADMINFLAG_MUTED; /* request user muting */ 03634 else 03635 user->adminflags &= ~(ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED | ADMINFLAG_T_REQUEST); /* request user unmuting */ 03636 03637 AST_LIST_UNLOCK(&confs); 03638 03639 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); 03640 03641 astman_send_ack(s, m, mute ? "User muted" : "User unmuted"); 03642 return 0; 03643 }
static enum ast_device_state meetmestate | ( | const char * | data | ) | [static] |
Callback for devicestate providers.
Definition at line 3795 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().
03796 { 03797 struct ast_conference *conf; 03798 03799 /* Find conference */ 03800 AST_LIST_LOCK(&confs); 03801 AST_LIST_TRAVERSE(&confs, conf, list) { 03802 if (!strcmp(data, conf->confno)) 03803 break; 03804 } 03805 AST_LIST_UNLOCK(&confs); 03806 if (!conf) 03807 return AST_DEVICE_INVALID; 03808 03809 03810 /* SKREP to fill */ 03811 if (!conf->users) 03812 return AST_DEVICE_NOT_INUSE; 03813 03814 return AST_DEVICE_INUSE; 03815 }
static struct sla_ringing_trunk* queue_ringing_trunk | ( | struct sla_trunk * | trunk | ) | [static] |
Definition at line 5133 of file app_meetme.c.
References ALL_TRUNK_REFS, ast_calloc, AST_LIST_INSERT_HEAD, ast_mutex_lock(), ast_mutex_unlock(), ast_tvnow(), announce_listitem::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().
05134 { 05135 struct sla_ringing_trunk *ringing_trunk; 05136 05137 if (!(ringing_trunk = ast_calloc(1, sizeof(*ringing_trunk)))) 05138 return NULL; 05139 05140 ringing_trunk->trunk = trunk; 05141 ringing_trunk->ring_begin = ast_tvnow(); 05142 05143 sla_change_trunk_state(trunk, SLA_TRUNK_STATE_RINGING, ALL_TRUNK_REFS, NULL); 05144 05145 ast_mutex_lock(&sla.lock); 05146 AST_LIST_INSERT_HEAD(&sla.ringing_trunks, ringing_trunk, entry); 05147 ast_mutex_unlock(&sla.lock); 05148 05149 sla_queue_event(SLA_EVENT_RINGING_TRUNK); 05150 05151 return ringing_trunk; 05152 }
static void * recordthread | ( | void * | args | ) | [static] |
Definition at line 3730 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, s, and ast_conference::transframe.
03731 { 03732 struct ast_conference *cnf = args; 03733 struct ast_frame *f = NULL; 03734 int flags; 03735 struct ast_filestream *s = NULL; 03736 int res = 0; 03737 int x; 03738 const char *oldrecordingfilename = NULL; 03739 03740 if (!cnf || !cnf->lchan) { 03741 pthread_exit(0); 03742 } 03743 03744 ast_stopstream(cnf->lchan); 03745 flags = O_CREAT | O_TRUNC | O_WRONLY; 03746 03747 03748 cnf->recording = MEETME_RECORD_ACTIVE; 03749 while (ast_waitfor(cnf->lchan, -1) > -1) { 03750 if (cnf->recording == MEETME_RECORD_TERMINATE) { 03751 AST_LIST_LOCK(&confs); 03752 AST_LIST_UNLOCK(&confs); 03753 break; 03754 } 03755 if (!s && cnf->recordingfilename && (cnf->recordingfilename != oldrecordingfilename)) { 03756 s = ast_writefile(cnf->recordingfilename, cnf->recordingformat, NULL, flags, 0, AST_FILE_MODE); 03757 oldrecordingfilename = cnf->recordingfilename; 03758 } 03759 03760 f = ast_read(cnf->lchan); 03761 if (!f) { 03762 res = -1; 03763 break; 03764 } 03765 if (f->frametype == AST_FRAME_VOICE) { 03766 ast_mutex_lock(&cnf->listenlock); 03767 for (x = 0; x < AST_FRAME_BITS; x++) { 03768 /* Free any translations that have occured */ 03769 if (cnf->transframe[x]) { 03770 ast_frfree(cnf->transframe[x]); 03771 cnf->transframe[x] = NULL; 03772 } 03773 } 03774 if (cnf->origframe) 03775 ast_frfree(cnf->origframe); 03776 cnf->origframe = ast_frdup(f); 03777 ast_mutex_unlock(&cnf->listenlock); 03778 if (s) 03779 res = ast_writestream(s, f); 03780 if (res) { 03781 ast_frfree(f); 03782 break; 03783 } 03784 } 03785 ast_frfree(f); 03786 } 03787 cnf->recording = MEETME_RECORD_OFF; 03788 if (s) 03789 ast_closestream(s); 03790 03791 pthread_exit(0); 03792 }
static int reload | ( | void | ) | [static] |
Definition at line 5757 of file app_meetme.c.
References load_config().
05758 { 05759 return load_config(1); 05760 }
static void reset_volumes | ( | struct ast_conf_user * | user | ) | [static] |
Definition at line 774 of file app_meetme.c.
References ast_channel_setoption(), AST_OPTION_RXGAIN, AST_OPTION_TXGAIN, and user.
Referenced by admin_exec(), and conf_run().
00775 { 00776 signed char zero_volume = 0; 00777 00778 ast_channel_setoption(user->chan, AST_OPTION_TXGAIN, &zero_volume, sizeof(zero_volume), 0); 00779 ast_channel_setoption(user->chan, AST_OPTION_RXGAIN, &zero_volume, sizeof(zero_volume), 0); 00780 }
static void* run_station | ( | void * | data | ) | [static] |
Definition at line 4033 of file app_meetme.c.
References sla_trunk::active_stations, admin_exec(), ALL_TRUNK_REFS, answer_trunk_chan(), ast_atomic_dec_and_test(), ast_atomic_fetchadd_int(), ast_cond_signal(), ast_dial_destroy(), ast_dial_join(), ast_mutex_lock(), ast_mutex_unlock(), ast_set_flag, build_conf(), sla_trunk_ref::chan, run_station_args::cond, run_station_args::cond_lock, conf_run(), CONFFLAG_MARKEDEXIT, CONFFLAG_PASS_DTMF, CONFFLAG_QUIET, CONFFLAG_SLA_STATION, sla_station::dial, dispose_conf(), ast_flags::flags, sla_trunk::hold_stations, MAX_CONFNUM, 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().
04034 { 04035 struct sla_station *station; 04036 struct sla_trunk_ref *trunk_ref; 04037 char conf_name[MAX_CONFNUM]; 04038 struct ast_flags conf_flags = { 0 }; 04039 struct ast_conference *conf; 04040 04041 { 04042 struct run_station_args *args = data; 04043 station = args->station; 04044 trunk_ref = args->trunk_ref; 04045 ast_mutex_lock(args->cond_lock); 04046 ast_cond_signal(args->cond); 04047 ast_mutex_unlock(args->cond_lock); 04048 /* args is no longer valid here. */ 04049 } 04050 04051 ast_atomic_fetchadd_int((int *) &trunk_ref->trunk->active_stations, 1); 04052 snprintf(conf_name, sizeof(conf_name), "SLA_%s", trunk_ref->trunk->name); 04053 ast_set_flag(&conf_flags, 04054 CONFFLAG_QUIET | CONFFLAG_MARKEDEXIT | CONFFLAG_PASS_DTMF | CONFFLAG_SLA_STATION); 04055 answer_trunk_chan(trunk_ref->chan); 04056 conf = build_conf(conf_name, "", "", 0, 0, 1, trunk_ref->chan); 04057 if (conf) { 04058 conf_run(trunk_ref->chan, conf, conf_flags.flags, NULL); 04059 dispose_conf(conf); 04060 conf = NULL; 04061 } 04062 trunk_ref->chan = NULL; 04063 if (ast_atomic_dec_and_test((int *) &trunk_ref->trunk->active_stations) && 04064 trunk_ref->state != SLA_TRUNK_STATE_ONHOLD_BYME) { 04065 strncat(conf_name, ",K", sizeof(conf_name) - strlen(conf_name) - 1); 04066 admin_exec(NULL, conf_name); 04067 trunk_ref->trunk->hold_stations = 0; 04068 sla_change_trunk_state(trunk_ref->trunk, SLA_TRUNK_STATE_IDLE, ALL_TRUNK_REFS, NULL); 04069 } 04070 04071 ast_dial_join(station->dial); 04072 ast_dial_destroy(station->dial); 04073 station->dial = NULL; 04074 04075 return NULL; 04076 }
static int set_listen_volume | ( | struct ast_conf_user * | user, | |
int | volume | |||
) | [static] |
Definition at line 703 of file app_meetme.c.
References ast_channel_setoption(), AST_OPTION_TXGAIN, and user.
Referenced by tweak_listen_volume().
00704 { 00705 char gain_adjust; 00706 00707 /* attempt to make the adjustment in the channel driver; 00708 if successful, don't adjust in the frame reading routine 00709 */ 00710 gain_adjust = gain_map[volume + 5]; 00711 00712 return ast_channel_setoption(user->chan, AST_OPTION_TXGAIN, &gain_adjust, sizeof(gain_adjust), 0); 00713 }
static int set_talk_volume | ( | struct ast_conf_user * | user, | |
int | volume | |||
) | [static] |
Definition at line 691 of file app_meetme.c.
References ast_channel_setoption(), AST_OPTION_RXGAIN, and user.
Referenced by conf_run(), and tweak_talk_volume().
00692 { 00693 char gain_adjust; 00694 00695 /* attempt to make the adjustment in the channel driver; 00696 if successful, don't adjust in the frame reading routine 00697 */ 00698 gain_adjust = gain_map[volume + 5]; 00699 00700 return ast_channel_setoption(user->chan, AST_OPTION_RXGAIN, &gain_adjust, sizeof(gain_adjust), 0); 00701 }
static void sla_add_trunk_to_station | ( | struct sla_station * | station, | |
struct ast_variable * | var | |||
) | [static] |
Definition at line 5479 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(), announce_listitem::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, and var.
Referenced by sla_build_station().
05480 { 05481 struct sla_trunk *trunk; 05482 struct sla_trunk_ref *trunk_ref; 05483 struct sla_station_ref *station_ref; 05484 char *trunk_name, *options, *cur; 05485 05486 options = ast_strdupa(var->value); 05487 trunk_name = strsep(&options, ","); 05488 05489 AST_RWLIST_RDLOCK(&sla_trunks); 05490 AST_RWLIST_TRAVERSE(&sla_trunks, trunk, entry) { 05491 if (!strcasecmp(trunk->name, trunk_name)) 05492 break; 05493 } 05494 05495 AST_RWLIST_UNLOCK(&sla_trunks); 05496 if (!trunk) { 05497 ast_log(LOG_ERROR, "Trunk '%s' not found!\n", var->value); 05498 return; 05499 } 05500 if (!(trunk_ref = create_trunk_ref(trunk))) 05501 return; 05502 trunk_ref->state = SLA_TRUNK_STATE_IDLE; 05503 05504 while ((cur = strsep(&options, ","))) { 05505 char *name, *value = cur; 05506 name = strsep(&value, "="); 05507 if (!strcasecmp(name, "ringtimeout")) { 05508 if (sscanf(value, "%u", &trunk_ref->ring_timeout) != 1) { 05509 ast_log(LOG_WARNING, "Invalid ringtimeout value '%s' for " 05510 "trunk '%s' on station '%s'\n", value, trunk->name, station->name); 05511 trunk_ref->ring_timeout = 0; 05512 } 05513 } else if (!strcasecmp(name, "ringdelay")) { 05514 if (sscanf(value, "%u", &trunk_ref->ring_delay) != 1) { 05515 ast_log(LOG_WARNING, "Invalid ringdelay value '%s' for " 05516 "trunk '%s' on station '%s'\n", value, trunk->name, station->name); 05517 trunk_ref->ring_delay = 0; 05518 } 05519 } else { 05520 ast_log(LOG_WARNING, "Invalid option '%s' for " 05521 "trunk '%s' on station '%s'\n", name, trunk->name, station->name); 05522 } 05523 } 05524 05525 if (!(station_ref = sla_create_station_ref(station))) { 05526 ast_free(trunk_ref); 05527 return; 05528 } 05529 ast_atomic_fetchadd_int((int *) &trunk->num_stations, 1); 05530 AST_RWLIST_WRLOCK(&sla_trunks); 05531 AST_LIST_INSERT_TAIL(&trunk->stations, station_ref, entry); 05532 AST_RWLIST_UNLOCK(&sla_trunks); 05533 AST_LIST_INSERT_TAIL(&station->trunks, trunk_ref, entry); 05534 }
static int sla_build_station | ( | struct ast_config * | cfg, | |
const char * | cat | |||
) | [static] |
Definition at line 5536 of file app_meetme.c.
References ast_calloc, ast_free, ast_log(), ast_string_field_init, ast_string_field_set, ast_variable_browse(), ast_variable_retrieve(), LOG_WARNING, sla_add_trunk_to_station(), and var.
Referenced by sla_load_config().
05537 { 05538 struct sla_station *station; 05539 struct ast_variable *var; 05540 const char *dev; 05541 05542 if (!(dev = ast_variable_retrieve(cfg, cat, "device"))) { 05543 ast_log(LOG_ERROR, "SLA Station '%s' defined with no device!\n", cat); 05544 return -1; 05545 } 05546 05547 if (!(station = ast_calloc(1, sizeof(*station)))) 05548 return -1; 05549 if (ast_string_field_init(station, 32)) { 05550 ast_free(station); 05551 return -1; 05552 } 05553 05554 ast_string_field_set(station, name, cat); 05555 ast_string_field_set(station, device, dev); 05556 05557 for (var = ast_variable_browse(cfg, cat); var; var = var->next) { 05558 if (!strcasecmp(var->name, "trunk")) 05559 sla_add_trunk_to_station(station, var); 05560 else if (!strcasecmp(var->name, "autocontext")) 05561 ast_string_field_set(station, autocontext, var->value); 05562 else if (!strcasecmp(var->name, "ringtimeout")) { 05563 if (sscanf(var->value, "%u", &station->ring_timeout) != 1) { 05564 ast_log(LOG_WARNING, "Invalid ringtimeout '%s' specified for station '%s'\n", 05565 var->value, station->name); 05566 station->ring_timeout = 0; 05567 } 05568 } else if (!strcasecmp(var->name, "ringdelay")) { 05569 if (sscanf(var->value, "%u", &station->ring_delay) != 1) { 05570 ast_log(LOG_WARNING, "Invalid ringdelay '%s' specified for station '%s'\n", 05571 var->value, station->name); 05572 station->ring_delay = 0; 05573 } 05574 } else if (!strcasecmp(var->name, "hold")) { 05575 if (!strcasecmp(var->value, "private")) 05576 station->hold_access = SLA_HOLD_PRIVATE; 05577 else if (!strcasecmp(var->value, "open")) 05578 station->hold_access = SLA_HOLD_OPEN; 05579 else { 05580 ast_log(LOG_WARNING, "Invalid value '%s' for hold on station %s\n", 05581 var->value, station->name); 05582 } 05583 05584 } else if (strcasecmp(var->name, "type") && strcasecmp(var->name, "device")) { 05585 ast_log(LOG_ERROR, "Invalid option '%s' specified at line %d of %s!\n", 05586 var->name, var->lineno, SLA_CONFIG_FILE); 05587 } 05588 } 05589 05590 if (!ast_strlen_zero(station->autocontext)) { 05591 struct ast_context *context; 05592 struct sla_trunk_ref *trunk_ref; 05593 context = ast_context_find_or_create(NULL, NULL, station->autocontext, sla_registrar); 05594 if (!context) { 05595 ast_log(LOG_ERROR, "Failed to automatically find or create " 05596 "context '%s' for SLA!\n", station->autocontext); 05597 destroy_station(station); 05598 return -1; 05599 } 05600 /* The extension for when the handset goes off-hook. 05601 * exten => station1,1,SLAStation(station1) */ 05602 if (ast_add_extension2(context, 0 /* don't replace */, station->name, 1, 05603 NULL, NULL, slastation_app, ast_strdup(station->name), ast_free_ptr, sla_registrar)) { 05604 ast_log(LOG_ERROR, "Failed to automatically create extension " 05605 "for trunk '%s'!\n", station->name); 05606 destroy_station(station); 05607 return -1; 05608 } 05609 AST_RWLIST_RDLOCK(&sla_trunks); 05610 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) { 05611 char exten[AST_MAX_EXTENSION]; 05612 char hint[AST_MAX_APP]; 05613 snprintf(exten, sizeof(exten), "%s_%s", station->name, trunk_ref->trunk->name); 05614 snprintf(hint, sizeof(hint), "SLA:%s", exten); 05615 /* Extension for this line button 05616 * exten => station1_line1,1,SLAStation(station1_line1) */ 05617 if (ast_add_extension2(context, 0 /* don't replace */, exten, 1, 05618 NULL, NULL, slastation_app, ast_strdup(exten), ast_free_ptr, sla_registrar)) { 05619 ast_log(LOG_ERROR, "Failed to automatically create extension " 05620 "for trunk '%s'!\n", station->name); 05621 destroy_station(station); 05622 return -1; 05623 } 05624 /* Hint for this line button 05625 * exten => station1_line1,hint,SLA:station1_line1 */ 05626 if (ast_add_extension2(context, 0 /* don't replace */, exten, PRIORITY_HINT, 05627 NULL, NULL, hint, NULL, NULL, sla_registrar)) { 05628 ast_log(LOG_ERROR, "Failed to automatically create hint " 05629 "for trunk '%s'!\n", station->name); 05630 destroy_station(station); 05631 return -1; 05632 } 05633 } 05634 AST_RWLIST_UNLOCK(&sla_trunks); 05635 } 05636 05637 AST_RWLIST_WRLOCK(&sla_stations); 05638 AST_RWLIST_INSERT_TAIL(&sla_stations, station, entry); 05639 AST_RWLIST_UNLOCK(&sla_stations); 05640 05641 return 0; 05642 }
static int sla_build_trunk | ( | struct ast_config * | cfg, | |
const char * | cat | |||
) | [static] |
Definition at line 5401 of file app_meetme.c.
References ast_calloc, ast_free, ast_log(), ast_string_field_init, ast_string_field_set, ast_variable_browse(), ast_variable_retrieve(), LOG_ERROR, LOG_WARNING, sla_check_device(), and var.
Referenced by sla_load_config().
05402 { 05403 struct sla_trunk *trunk; 05404 struct ast_variable *var; 05405 const char *dev; 05406 05407 if (!(dev = ast_variable_retrieve(cfg, cat, "device"))) { 05408 ast_log(LOG_ERROR, "SLA Trunk '%s' defined with no device!\n", cat); 05409 return -1; 05410 } 05411 05412 if (sla_check_device(dev)) { 05413 ast_log(LOG_ERROR, "SLA Trunk '%s' define with invalid device '%s'!\n", 05414 cat, dev); 05415 return -1; 05416 } 05417 05418 if (!(trunk = ast_calloc(1, sizeof(*trunk)))) 05419 return -1; 05420 if (ast_string_field_init(trunk, 32)) { 05421 ast_free(trunk); 05422 return -1; 05423 } 05424 05425 ast_string_field_set(trunk, name, cat); 05426 ast_string_field_set(trunk, device, dev); 05427 05428 for (var = ast_variable_browse(cfg, cat); var; var = var->next) { 05429 if (!strcasecmp(var->name, "autocontext")) 05430 ast_string_field_set(trunk, autocontext, var->value); 05431 else if (!strcasecmp(var->name, "ringtimeout")) { 05432 if (sscanf(var->value, "%u", &trunk->ring_timeout) != 1) { 05433 ast_log(LOG_WARNING, "Invalid ringtimeout '%s' specified for trunk '%s'\n", 05434 var->value, trunk->name); 05435 trunk->ring_timeout = 0; 05436 } 05437 } else if (!strcasecmp(var->name, "barge")) 05438 trunk->barge_disabled = ast_false(var->value); 05439 else if (!strcasecmp(var->name, "hold")) { 05440 if (!strcasecmp(var->value, "private")) 05441 trunk->hold_access = SLA_HOLD_PRIVATE; 05442 else if (!strcasecmp(var->value, "open")) 05443 trunk->hold_access = SLA_HOLD_OPEN; 05444 else { 05445 ast_log(LOG_WARNING, "Invalid value '%s' for hold on trunk %s\n", 05446 var->value, trunk->name); 05447 } 05448 } else if (strcasecmp(var->name, "type") && strcasecmp(var->name, "device")) { 05449 ast_log(LOG_ERROR, "Invalid option '%s' specified at line %d of %s!\n", 05450 var->name, var->lineno, SLA_CONFIG_FILE); 05451 } 05452 } 05453 05454 if (!ast_strlen_zero(trunk->autocontext)) { 05455 struct ast_context *context; 05456 context = ast_context_find_or_create(NULL, NULL, trunk->autocontext, sla_registrar); 05457 if (!context) { 05458 ast_log(LOG_ERROR, "Failed to automatically find or create " 05459 "context '%s' for SLA!\n", trunk->autocontext); 05460 destroy_trunk(trunk); 05461 return -1; 05462 } 05463 if (ast_add_extension2(context, 0 /* don't replace */, "s", 1, 05464 NULL, NULL, slatrunk_app, ast_strdup(trunk->name), ast_free_ptr, sla_registrar)) { 05465 ast_log(LOG_ERROR, "Failed to automatically create extension " 05466 "for trunk '%s'!\n", trunk->name); 05467 destroy_trunk(trunk); 05468 return -1; 05469 } 05470 } 05471 05472 AST_RWLIST_WRLOCK(&sla_trunks); 05473 AST_RWLIST_INSERT_TAIL(&sla_trunks, trunk, entry); 05474 AST_RWLIST_UNLOCK(&sla_trunks); 05475 05476 return 0; 05477 }
static int sla_calc_station_delays | ( | unsigned int * | timeout | ) | [static] |
Calculate the ring delay for a station.
Definition at line 4645 of file app_meetme.c.
References AST_LIST_TRAVERSE, announce_listitem::entry, sla_check_inuse_station(), sla_check_ringing_station(), sla_check_station_delay(), and sla_choose_ringing_trunk().
Referenced by sla_process_timers().
04646 { 04647 struct sla_station *station; 04648 int res = 0; 04649 04650 AST_LIST_TRAVERSE(&sla_stations, station, entry) { 04651 struct sla_ringing_trunk *ringing_trunk; 04652 int time_left; 04653 04654 /* Ignore stations already ringing */ 04655 if (sla_check_ringing_station(station)) 04656 continue; 04657 04658 /* Ignore stations already on a call */ 04659 if (sla_check_inuse_station(station)) 04660 continue; 04661 04662 /* Ignore stations that don't have one of their trunks ringing */ 04663 if (!(ringing_trunk = sla_choose_ringing_trunk(station, NULL, 0))) 04664 continue; 04665 04666 if ((time_left = sla_check_station_delay(station, ringing_trunk)) == INT_MAX) 04667 continue; 04668 04669 /* If there is no time left, then the station needs to start ringing. 04670 * Return non-zero so that an event will be queued up an event to 04671 * make that happen. */ 04672 if (time_left <= 0) { 04673 res = 1; 04674 continue; 04675 } 04676 04677 if (time_left < *timeout) 04678 *timeout = time_left; 04679 } 04680 04681 return res; 04682 }
static int sla_calc_station_timeouts | ( | unsigned int * | timeout | ) | [static] |
Process station ring timeouts.
Definition at line 4562 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(), announce_listitem::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().
04563 { 04564 struct sla_ringing_trunk *ringing_trunk; 04565 struct sla_ringing_station *ringing_station; 04566 int res = 0; 04567 04568 AST_LIST_TRAVERSE_SAFE_BEGIN(&sla.ringing_stations, ringing_station, entry) { 04569 unsigned int ring_timeout = 0; 04570 int time_elapsed, time_left = INT_MAX, final_trunk_time_left = INT_MIN; 04571 struct sla_trunk_ref *trunk_ref; 04572 04573 /* If there are any ring timeouts specified for a specific trunk 04574 * on the station, then use the highest per-trunk ring timeout. 04575 * Otherwise, use the ring timeout set for the entire station. */ 04576 AST_LIST_TRAVERSE(&ringing_station->station->trunks, trunk_ref, entry) { 04577 struct sla_station_ref *station_ref; 04578 int trunk_time_elapsed, trunk_time_left; 04579 04580 AST_LIST_TRAVERSE(&sla.ringing_trunks, ringing_trunk, entry) { 04581 if (ringing_trunk->trunk == trunk_ref->trunk) 04582 break; 04583 } 04584 if (!ringing_trunk) 04585 continue; 04586 04587 /* If there is a trunk that is ringing without a timeout, then the 04588 * only timeout that could matter is a global station ring timeout. */ 04589 if (!trunk_ref->ring_timeout) 04590 break; 04591 04592 /* This trunk on this station is ringing and has a timeout. 04593 * However, make sure this trunk isn't still ringing from a 04594 * previous timeout. If so, don't consider it. */ 04595 AST_LIST_TRAVERSE(&ringing_trunk->timed_out_stations, station_ref, entry) { 04596 if (station_ref->station == ringing_station->station) 04597 break; 04598 } 04599 if (station_ref) 04600 continue; 04601 04602 trunk_time_elapsed = ast_tvdiff_ms(ast_tvnow(), ringing_trunk->ring_begin); 04603 trunk_time_left = (trunk_ref->ring_timeout * 1000) - trunk_time_elapsed; 04604 if (trunk_time_left > final_trunk_time_left) 04605 final_trunk_time_left = trunk_time_left; 04606 } 04607 04608 /* No timeout was found for ringing trunks, and no timeout for the entire station */ 04609 if (final_trunk_time_left == INT_MIN && !ringing_station->station->ring_timeout) 04610 continue; 04611 04612 /* Compute how much time is left for a global station timeout */ 04613 if (ringing_station->station->ring_timeout) { 04614 ring_timeout = ringing_station->station->ring_timeout; 04615 time_elapsed = ast_tvdiff_ms(ast_tvnow(), ringing_station->ring_begin); 04616 time_left = (ring_timeout * 1000) - time_elapsed; 04617 } 04618 04619 /* If the time left based on the per-trunk timeouts is smaller than the 04620 * global station ring timeout, use that. */ 04621 if (final_trunk_time_left > INT_MIN && final_trunk_time_left < time_left) 04622 time_left = final_trunk_time_left; 04623 04624 /* If there is no time left, the station needs to stop ringing */ 04625 if (time_left <= 0) { 04626 AST_LIST_REMOVE_CURRENT(entry); 04627 sla_stop_ringing_station(ringing_station, SLA_STATION_HANGUP_TIMEOUT); 04628 res = 1; 04629 continue; 04630 } 04631 04632 /* There is still some time left for this station to ring, so save that 04633 * timeout if it is the first event scheduled to occur */ 04634 if (time_left < *timeout) 04635 *timeout = time_left; 04636 } 04637 AST_LIST_TRAVERSE_SAFE_END; 04638 04639 return res; 04640 }
static int sla_calc_trunk_timeouts | ( | unsigned int * | timeout | ) | [static] |
Process trunk ring timeouts.
Definition at line 4532 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, announce_listitem::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().
04533 { 04534 struct sla_ringing_trunk *ringing_trunk; 04535 int res = 0; 04536 04537 AST_LIST_TRAVERSE_SAFE_BEGIN(&sla.ringing_trunks, ringing_trunk, entry) { 04538 int time_left, time_elapsed; 04539 if (!ringing_trunk->trunk->ring_timeout) 04540 continue; 04541 time_elapsed = ast_tvdiff_ms(ast_tvnow(), ringing_trunk->ring_begin); 04542 time_left = (ringing_trunk->trunk->ring_timeout * 1000) - time_elapsed; 04543 if (time_left <= 0) { 04544 pbx_builtin_setvar_helper(ringing_trunk->trunk->chan, "SLATRUNK_STATUS", "RINGTIMEOUT"); 04545 AST_LIST_REMOVE_CURRENT(entry); 04546 sla_stop_ringing_trunk(ringing_trunk); 04547 res = 1; 04548 continue; 04549 } 04550 if (time_left < *timeout) 04551 *timeout = time_left; 04552 } 04553 AST_LIST_TRAVERSE_SAFE_END; 04554 04555 return res; 04556 }
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 4001 of file app_meetme.c.
References ast_devstate_changed(), AST_LIST_TRAVERSE, sla_trunk_ref::chan, announce_listitem::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().
04003 { 04004 struct sla_station *station; 04005 struct sla_trunk_ref *trunk_ref; 04006 04007 AST_LIST_TRAVERSE(&sla_stations, station, entry) { 04008 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) { 04009 if (trunk_ref->trunk != trunk || (inactive_only ? trunk_ref->chan : 0) 04010 || trunk_ref == exclude) 04011 continue; 04012 trunk_ref->state = state; 04013 ast_devstate_changed(sla_state_to_devstate(state), 04014 "SLA:%s_%s", station->name, trunk->name); 04015 break; 04016 } 04017 } 04018 }
static int sla_check_device | ( | const char * | device | ) | [static] |
Definition at line 5388 of file app_meetme.c.
References ast_strdupa, ast_strlen_zero(), and strsep().
Referenced by sla_build_trunk().
05389 { 05390 char *tech, *tech_data; 05391 05392 tech_data = ast_strdupa(device); 05393 tech = strsep(&tech_data, "/"); 05394 05395 if (ast_strlen_zero(tech) || ast_strlen_zero(tech_data)) 05396 return -1; 05397 05398 return 0; 05399 }
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 4280 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(), announce_listitem::entry, sla_failed_station::last_try, sla, and sla_failed_station::station.
Referenced by sla_ring_stations().
04281 { 04282 struct sla_failed_station *failed_station; 04283 int res = 0; 04284 04285 AST_LIST_TRAVERSE_SAFE_BEGIN(&sla.failed_stations, failed_station, entry) { 04286 if (station != failed_station->station) 04287 continue; 04288 if (ast_tvdiff_ms(ast_tvnow(), failed_station->last_try) > 1000) { 04289 AST_LIST_REMOVE_CURRENT(entry); 04290 ast_free(failed_station); 04291 break; 04292 } 04293 res = 1; 04294 } 04295 AST_LIST_TRAVERSE_SAFE_END 04296 04297 return res; 04298 }
static int sla_check_inuse_station | ( | const struct sla_station * | station | ) | [static] |
Check to see if a station is in use.
Definition at line 4366 of file app_meetme.c.
References AST_LIST_TRAVERSE, sla_trunk_ref::chan, announce_listitem::entry, and sla_station::trunks.
Referenced by sla_calc_station_delays(), and sla_ring_stations().
04367 { 04368 struct sla_trunk_ref *trunk_ref; 04369 04370 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) { 04371 if (trunk_ref->chan) 04372 return 1; 04373 } 04374 04375 return 0; 04376 }
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 4724 of file app_meetme.c.
References AST_LIST_EMPTY, ast_mutex_lock(), ast_mutex_unlock(), AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, announce_listitem::entry, sla_trunk::ref_count, sla_station::ref_count, sla, and sla_load_config().
Referenced by sla_thread().
04725 { 04726 struct sla_station *station; 04727 struct sla_trunk *trunk; 04728 04729 ast_mutex_lock(&sla.lock); 04730 04731 if (!AST_LIST_EMPTY(&sla.event_q) || !AST_LIST_EMPTY(&sla.ringing_trunks) 04732 || !AST_LIST_EMPTY(&sla.ringing_stations)) { 04733 ast_mutex_unlock(&sla.lock); 04734 return; 04735 } 04736 04737 AST_RWLIST_RDLOCK(&sla_stations); 04738 AST_RWLIST_TRAVERSE(&sla_stations, station, entry) { 04739 if (station->ref_count) 04740 break; 04741 } 04742 AST_RWLIST_UNLOCK(&sla_stations); 04743 if (station) { 04744 ast_mutex_unlock(&sla.lock); 04745 return; 04746 } 04747 04748 AST_RWLIST_RDLOCK(&sla_trunks); 04749 AST_RWLIST_TRAVERSE(&sla_trunks, trunk, entry) { 04750 if (trunk->ref_count) 04751 break; 04752 } 04753 AST_RWLIST_UNLOCK(&sla_trunks); 04754 if (trunk) { 04755 ast_mutex_unlock(&sla.lock); 04756 return; 04757 } 04758 04759 /* yay */ 04760 sla_load_config(1); 04761 sla.reload = 0; 04762 04763 ast_mutex_unlock(&sla.lock); 04764 }
static int sla_check_ringing_station | ( | const struct sla_station * | station | ) | [static] |
Check to see if this station is already ringing.
Definition at line 4265 of file app_meetme.c.
References AST_LIST_TRAVERSE, announce_listitem::entry, sla, and sla_ringing_station::station.
Referenced by sla_calc_station_delays(), and sla_ring_stations().
04266 { 04267 struct sla_ringing_station *ringing_station; 04268 04269 AST_LIST_TRAVERSE(&sla.ringing_stations, ringing_station, entry) { 04270 if (station == ringing_station->station) 04271 return 1; 04272 } 04273 04274 return 0; 04275 }
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 4396 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().
04398 { 04399 struct sla_trunk_ref *trunk_ref; 04400 unsigned int delay = UINT_MAX; 04401 int time_left, time_elapsed; 04402 04403 if (!ringing_trunk) 04404 ringing_trunk = sla_choose_ringing_trunk(station, &trunk_ref, 0); 04405 else 04406 trunk_ref = sla_find_trunk_ref(station, ringing_trunk->trunk); 04407 04408 if (!ringing_trunk || !trunk_ref) 04409 return delay; 04410 04411 /* If this station has a ring delay specific to the highest priority 04412 * ringing trunk, use that. Otherwise, use the ring delay specified 04413 * globally for the station. */ 04414 delay = trunk_ref->ring_delay; 04415 if (!delay) 04416 delay = station->ring_delay; 04417 if (!delay) 04418 return INT_MAX; 04419 04420 time_elapsed = ast_tvdiff_ms(ast_tvnow(), ringing_trunk->ring_begin); 04421 time_left = (delay * 1000) - time_elapsed; 04422 04423 return time_left; 04424 }
static int sla_check_station_hold_access | ( | const struct sla_trunk * | trunk, | |
const struct sla_station * | station | |||
) | [static] |
Definition at line 3906 of file app_meetme.c.
References AST_LIST_TRAVERSE, announce_listitem::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().
03908 { 03909 struct sla_station_ref *station_ref; 03910 struct sla_trunk_ref *trunk_ref; 03911 03912 /* For each station that has this call on hold, check for private hold. */ 03913 AST_LIST_TRAVERSE(&trunk->stations, station_ref, entry) { 03914 AST_LIST_TRAVERSE(&station_ref->station->trunks, trunk_ref, entry) { 03915 if (trunk_ref->trunk != trunk || station_ref->station == station) 03916 continue; 03917 if (trunk_ref->state == SLA_TRUNK_STATE_ONHOLD_BYME && 03918 station_ref->station->hold_access == SLA_HOLD_PRIVATE) 03919 return 1; 03920 return 0; 03921 } 03922 } 03923 03924 return 0; 03925 }
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 4136 of file app_meetme.c.
References AST_LIST_TRAVERSE, announce_listitem::entry, sla_station_ref::station, and sla_ringing_trunk::timed_out_stations.
Referenced by sla_choose_ringing_trunk(), and sla_ring_stations().
04138 { 04139 struct sla_station_ref *timed_out_station; 04140 04141 AST_LIST_TRAVERSE(&ringing_trunk->timed_out_stations, timed_out_station, entry) { 04142 if (station == timed_out_station->station) 04143 return 1; 04144 } 04145 04146 return 0; 04147 }
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 4948 of file app_meetme.c.
References AST_LIST_TRAVERSE, announce_listitem::entry, SLA_TRUNK_STATE_IDLE, sla_trunk_ref::state, and sla_station::trunks.
Referenced by sla_station_exec().
04949 { 04950 struct sla_trunk_ref *trunk_ref = NULL; 04951 04952 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) { 04953 if (trunk_ref->state == SLA_TRUNK_STATE_IDLE) 04954 break; 04955 } 04956 04957 return trunk_ref; 04958 }
static struct sla_ringing_trunk* sla_choose_ringing_trunk | ( | struct sla_station * | station, | |
struct sla_trunk_ref ** | trunk_ref, | |||
int | remove | |||
) | [static] |
Choose the highest priority ringing trunk for a station.
station | the station | |
remove | 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 4157 of file app_meetme.c.
References AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, announce_listitem::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().
04159 { 04160 struct sla_trunk_ref *s_trunk_ref; 04161 struct sla_ringing_trunk *ringing_trunk = NULL; 04162 04163 AST_LIST_TRAVERSE(&station->trunks, s_trunk_ref, entry) { 04164 AST_LIST_TRAVERSE_SAFE_BEGIN(&sla.ringing_trunks, ringing_trunk, entry) { 04165 /* Make sure this is the trunk we're looking for */ 04166 if (s_trunk_ref->trunk != ringing_trunk->trunk) 04167 continue; 04168 04169 /* This trunk on the station is ringing. But, make sure this station 04170 * didn't already time out while this trunk was ringing. */ 04171 if (sla_check_timed_out_station(ringing_trunk, station)) 04172 continue; 04173 04174 if (remove) 04175 AST_LIST_REMOVE_CURRENT(entry); 04176 04177 if (trunk_ref) 04178 *trunk_ref = s_trunk_ref; 04179 04180 break; 04181 } 04182 AST_LIST_TRAVERSE_SAFE_END; 04183 04184 if (ringing_trunk) 04185 break; 04186 } 04187 04188 return ringing_trunk; 04189 }
static struct sla_ringing_station* sla_create_ringing_station | ( | struct sla_station * | station | ) | [static] |
Definition at line 3971 of file app_meetme.c.
References ast_calloc, ast_tvnow(), and sla_ringing_station::station.
Referenced by sla_ring_station().
03972 { 03973 struct sla_ringing_station *ringing_station; 03974 03975 if (!(ringing_station = ast_calloc(1, sizeof(*ringing_station)))) 03976 return NULL; 03977 03978 ringing_station->station = station; 03979 ringing_station->ring_begin = ast_tvnow(); 03980 03981 return ringing_station; 03982 }
static struct sla_station_ref* sla_create_station_ref | ( | struct sla_station * | station | ) | [static] |
Definition at line 3959 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().
03960 { 03961 struct sla_station_ref *station_ref; 03962 03963 if (!(station_ref = ast_calloc(1, sizeof(*station_ref)))) 03964 return NULL; 03965 03966 station_ref->station = station; 03967 03968 return station_ref; 03969 }
static void sla_destroy | ( | void | ) | [static] |
Definition at line 5358 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(), announce_listitem::entry, sla, and sla_registrar.
Referenced by unload_module().
05359 { 05360 struct sla_trunk *trunk; 05361 struct sla_station *station; 05362 05363 AST_RWLIST_WRLOCK(&sla_trunks); 05364 while ((trunk = AST_RWLIST_REMOVE_HEAD(&sla_trunks, entry))) 05365 destroy_trunk(trunk); 05366 AST_RWLIST_UNLOCK(&sla_trunks); 05367 05368 AST_RWLIST_WRLOCK(&sla_stations); 05369 while ((station = AST_RWLIST_REMOVE_HEAD(&sla_stations, entry))) 05370 destroy_station(station); 05371 AST_RWLIST_UNLOCK(&sla_stations); 05372 05373 if (sla.thread != AST_PTHREADT_NULL) { 05374 ast_mutex_lock(&sla.lock); 05375 sla.stop = 1; 05376 ast_cond_signal(&sla.cond); 05377 ast_mutex_unlock(&sla.lock); 05378 pthread_join(sla.thread, NULL); 05379 } 05380 05381 /* Drop any created contexts from the dialplan */ 05382 ast_context_destroy(NULL, sla_registrar); 05383 05384 ast_mutex_destroy(&sla.lock); 05385 ast_cond_destroy(&sla.cond); 05386 }
static void sla_dial_state_callback | ( | struct ast_dial * | dial | ) | [static] |
Definition at line 4128 of file app_meetme.c.
References SLA_EVENT_DIAL_STATE, and sla_queue_event().
Referenced by sla_ring_station().
04129 { 04130 sla_queue_event(SLA_EVENT_DIAL_STATE); 04131 }
static struct sla_station* sla_find_station | ( | const char * | name | ) | [static] |
Find an SLA station by name.
Definition at line 3894 of file app_meetme.c.
References AST_RWLIST_TRAVERSE, announce_listitem::entry, and sla_station::name.
Referenced by sla_station_exec().
03895 { 03896 struct sla_station *station = NULL; 03897 03898 AST_RWLIST_TRAVERSE(&sla_stations, station, entry) { 03899 if (!strcasecmp(station->name, name)) 03900 break; 03901 } 03902 03903 return station; 03904 }
static struct sla_trunk* sla_find_trunk | ( | const char * | name | ) | [static] |
Find an SLA trunk by name.
Definition at line 3879 of file app_meetme.c.
References AST_RWLIST_TRAVERSE, announce_listitem::entry, and sla_trunk::name.
Referenced by sla_trunk_exec().
03880 { 03881 struct sla_trunk *trunk = NULL; 03882 03883 AST_RWLIST_TRAVERSE(&sla_trunks, trunk, entry) { 03884 if (!strcasecmp(trunk->name, name)) 03885 break; 03886 } 03887 03888 return trunk; 03889 }
static struct sla_trunk_ref* sla_find_trunk_ref | ( | const struct sla_station * | station, | |
const struct sla_trunk * | trunk | |||
) | [static] |
Definition at line 4378 of file app_meetme.c.
References AST_LIST_TRAVERSE, announce_listitem::entry, sla_trunk_ref::trunk, and sla_station::trunks.
Referenced by sla_check_station_delay().
04380 { 04381 struct sla_trunk_ref *trunk_ref = NULL; 04382 04383 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) { 04384 if (trunk_ref->trunk == trunk) 04385 break; 04386 } 04387 04388 return trunk_ref; 04389 }
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 3934 of file app_meetme.c.
References AST_LIST_TRAVERSE, sla_trunk::barge_disabled, announce_listitem::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().
03936 { 03937 struct sla_trunk_ref *trunk_ref = NULL; 03938 03939 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) { 03940 if (strcasecmp(trunk_ref->trunk->name, name)) 03941 continue; 03942 03943 if ( (trunk_ref->trunk->barge_disabled 03944 && trunk_ref->state == SLA_TRUNK_STATE_UP) || 03945 (trunk_ref->trunk->hold_stations 03946 && trunk_ref->trunk->hold_access == SLA_HOLD_PRIVATE 03947 && trunk_ref->state != SLA_TRUNK_STATE_ONHOLD_BYME) || 03948 sla_check_station_hold_access(trunk_ref->trunk, station) ) 03949 { 03950 trunk_ref = NULL; 03951 } 03952 03953 break; 03954 } 03955 03956 return trunk_ref; 03957 }
static void sla_handle_dial_state_event | ( | void | ) | [static] |
Definition at line 4191 of file app_meetme.c.
References ALL_TRUNK_REFS, answer_trunk_chan(), ast_cond_destroy(), ast_cond_init(), ast_cond_wait(), ast_debug, ast_dial_answered(), AST_DIAL_RESULT_ANSWERED, AST_DIAL_RESULT_FAILED, AST_DIAL_RESULT_HANGUP, AST_DIAL_RESULT_INVALID, AST_DIAL_RESULT_PROCEEDING, AST_DIAL_RESULT_PROGRESS, AST_DIAL_RESULT_RINGING, AST_DIAL_RESULT_TIMEOUT, AST_DIAL_RESULT_TRYING, AST_DIAL_RESULT_UNANSWERED, ast_dial_state(), ast_free, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_mutex_destroy(), ast_mutex_init(), ast_mutex_lock(), ast_mutex_unlock(), ast_pthread_create_detached_background, sla_trunk::chan, sla_trunk_ref::chan, run_station_args::cond, run_station_args::cond_lock, sla_station::dial, announce_listitem::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, run_station_args::station, sla_ringing_station::station, sla_ringing_trunk::trunk, and run_station_args::trunk_ref.
Referenced by sla_thread().
04192 { 04193 struct sla_ringing_station *ringing_station; 04194 04195 AST_LIST_TRAVERSE_SAFE_BEGIN(&sla.ringing_stations, ringing_station, entry) { 04196 struct sla_trunk_ref *s_trunk_ref = NULL; 04197 struct sla_ringing_trunk *ringing_trunk = NULL; 04198 struct run_station_args args; 04199 enum ast_dial_result dial_res; 04200 pthread_t dont_care; 04201 ast_mutex_t cond_lock; 04202 ast_cond_t cond; 04203 04204 switch ((dial_res = ast_dial_state(ringing_station->station->dial))) { 04205 case AST_DIAL_RESULT_HANGUP: 04206 case AST_DIAL_RESULT_INVALID: 04207 case AST_DIAL_RESULT_FAILED: 04208 case AST_DIAL_RESULT_TIMEOUT: 04209 case AST_DIAL_RESULT_UNANSWERED: 04210 AST_LIST_REMOVE_CURRENT(entry); 04211 sla_stop_ringing_station(ringing_station, SLA_STATION_HANGUP_NORMAL); 04212 break; 04213 case AST_DIAL_RESULT_ANSWERED: 04214 AST_LIST_REMOVE_CURRENT(entry); 04215 /* Find the appropriate trunk to answer. */ 04216 ast_mutex_lock(&sla.lock); 04217 ringing_trunk = sla_choose_ringing_trunk(ringing_station->station, &s_trunk_ref, 1); 04218 ast_mutex_unlock(&sla.lock); 04219 if (!ringing_trunk) { 04220 ast_debug(1, "Found no ringing trunk for station '%s' to answer!\n", ringing_station->station->name); 04221 break; 04222 } 04223 /* Track the channel that answered this trunk */ 04224 s_trunk_ref->chan = ast_dial_answered(ringing_station->station->dial); 04225 /* Actually answer the trunk */ 04226 answer_trunk_chan(ringing_trunk->trunk->chan); 04227 sla_change_trunk_state(ringing_trunk->trunk, SLA_TRUNK_STATE_UP, ALL_TRUNK_REFS, NULL); 04228 /* Now, start a thread that will connect this station to the trunk. The rest of 04229 * the code here sets up the thread and ensures that it is able to save the arguments 04230 * before they are no longer valid since they are allocated on the stack. */ 04231 args.trunk_ref = s_trunk_ref; 04232 args.station = ringing_station->station; 04233 args.cond = &cond; 04234 args.cond_lock = &cond_lock; 04235 ast_free(ringing_trunk); 04236 ast_free(ringing_station); 04237 ast_mutex_init(&cond_lock); 04238 ast_cond_init(&cond, NULL); 04239 ast_mutex_lock(&cond_lock); 04240 ast_pthread_create_detached_background(&dont_care, NULL, run_station, &args); 04241 ast_cond_wait(&cond, &cond_lock); 04242 ast_mutex_unlock(&cond_lock); 04243 ast_mutex_destroy(&cond_lock); 04244 ast_cond_destroy(&cond); 04245 break; 04246 case AST_DIAL_RESULT_TRYING: 04247 case AST_DIAL_RESULT_RINGING: 04248 case AST_DIAL_RESULT_PROGRESS: 04249 case AST_DIAL_RESULT_PROCEEDING: 04250 break; 04251 } 04252 if (dial_res == AST_DIAL_RESULT_ANSWERED) { 04253 /* Queue up reprocessing ringing trunks, and then ringing stations again */ 04254 sla_queue_event(SLA_EVENT_RINGING_TRUNK); 04255 sla_queue_event(SLA_EVENT_DIAL_STATE); 04256 break; 04257 } 04258 } 04259 AST_LIST_TRAVERSE_SAFE_END; 04260 }
static void sla_handle_hold_event | ( | struct sla_event * | event | ) | [static] |
Definition at line 4508 of file app_meetme.c.
References sla_trunk::active_stations, ast_atomic_fetchadd_int(), AST_CAUSE_NORMAL, AST_CONTROL_HOLD, AST_DEVICE_ONHOLD, ast_devstate_changed(), ast_indicate(), ast_softhangup(), 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().
04509 { 04510 ast_atomic_fetchadd_int((int *) &event->trunk_ref->trunk->hold_stations, 1); 04511 event->trunk_ref->state = SLA_TRUNK_STATE_ONHOLD_BYME; 04512 ast_devstate_changed(AST_DEVICE_ONHOLD, "SLA:%s_%s", 04513 event->station->name, event->trunk_ref->trunk->name); 04514 sla_change_trunk_state(event->trunk_ref->trunk, SLA_TRUNK_STATE_ONHOLD, 04515 INACTIVE_TRUNK_REFS, event->trunk_ref); 04516 04517 if (event->trunk_ref->trunk->active_stations == 1) { 04518 /* The station putting it on hold is the only one on the call, so start 04519 * Music on hold to the trunk. */ 04520 event->trunk_ref->trunk->on_hold = 1; 04521 ast_indicate(event->trunk_ref->trunk->chan, AST_CONTROL_HOLD); 04522 } 04523 04524 ast_softhangup(event->trunk_ref->chan, AST_CAUSE_NORMAL); 04525 event->trunk_ref->chan = NULL; 04526 }
static void sla_handle_ringing_trunk_event | ( | void | ) | [static] |
Definition at line 4498 of file app_meetme.c.
References ast_mutex_lock(), ast_mutex_unlock(), sla, sla_hangup_stations(), and sla_ring_stations().
Referenced by sla_thread().
04499 { 04500 ast_mutex_lock(&sla.lock); 04501 sla_ring_stations(); 04502 ast_mutex_unlock(&sla.lock); 04503 04504 /* Find stations that shouldn't be ringing anymore. */ 04505 sla_hangup_stations(); 04506 }
static void sla_hangup_stations | ( | void | ) | [static] |
Definition at line 4470 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, announce_listitem::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().
04471 { 04472 struct sla_trunk_ref *trunk_ref; 04473 struct sla_ringing_station *ringing_station; 04474 04475 AST_LIST_TRAVERSE_SAFE_BEGIN(&sla.ringing_stations, ringing_station, entry) { 04476 AST_LIST_TRAVERSE(&ringing_station->station->trunks, trunk_ref, entry) { 04477 struct sla_ringing_trunk *ringing_trunk; 04478 ast_mutex_lock(&sla.lock); 04479 AST_LIST_TRAVERSE(&sla.ringing_trunks, ringing_trunk, entry) { 04480 if (trunk_ref->trunk == ringing_trunk->trunk) 04481 break; 04482 } 04483 ast_mutex_unlock(&sla.lock); 04484 if (ringing_trunk) 04485 break; 04486 } 04487 if (!trunk_ref) { 04488 AST_LIST_REMOVE_CURRENT(entry); 04489 ast_dial_join(ringing_station->station->dial); 04490 ast_dial_destroy(ringing_station->station->dial); 04491 ringing_station->station->dial = NULL; 04492 ast_free(ringing_station); 04493 } 04494 } 04495 AST_LIST_TRAVERSE_SAFE_END 04496 }
static const char* sla_hold_str | ( | unsigned int | hold_access | ) | [static] |
Definition at line 1156 of file app_meetme.c.
References SLA_HOLD_OPEN, and SLA_HOLD_PRIVATE.
Referenced by sla_show_stations(), and sla_show_trunks().
01157 { 01158 const char *hold = "Unknown"; 01159 01160 switch (hold_access) { 01161 case SLA_HOLD_OPEN: 01162 hold = "Open"; 01163 break; 01164 case SLA_HOLD_PRIVATE: 01165 hold = "Private"; 01166 default: 01167 break; 01168 } 01169 01170 return hold; 01171 }
static int sla_load_config | ( | int | reload | ) | [static] |
Definition at line 5644 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_true(), ast_variable_retrieve(), CONFIG_FLAG_FILEUNCHANGED, 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().
05645 { 05646 struct ast_config *cfg; 05647 struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; 05648 const char *cat = NULL; 05649 int res = 0; 05650 const char *val; 05651 05652 if (!reload) { 05653 ast_mutex_init(&sla.lock); 05654 ast_cond_init(&sla.cond, NULL); 05655 } 05656 05657 if (!(cfg = ast_config_load(SLA_CONFIG_FILE, config_flags))) 05658 return 0; /* Treat no config as normal */ 05659 else if (cfg == CONFIG_STATUS_FILEUNCHANGED) 05660 return 0; 05661 05662 if ((val = ast_variable_retrieve(cfg, "general", "attemptcallerid"))) 05663 sla.attempt_callerid = ast_true(val); 05664 05665 while ((cat = ast_category_browse(cfg, cat)) && !res) { 05666 const char *type; 05667 if (!strcasecmp(cat, "general")) 05668 continue; 05669 if (!(type = ast_variable_retrieve(cfg, cat, "type"))) { 05670 ast_log(LOG_WARNING, "Invalid entry in %s defined with no type!\n", 05671 SLA_CONFIG_FILE); 05672 continue; 05673 } 05674 if (!strcasecmp(type, "trunk")) 05675 res = sla_build_trunk(cfg, cat); 05676 else if (!strcasecmp(type, "station")) 05677 res = sla_build_station(cfg, cat); 05678 else { 05679 ast_log(LOG_WARNING, "Entry in %s defined with invalid type '%s'!\n", 05680 SLA_CONFIG_FILE, type); 05681 } 05682 } 05683 05684 ast_config_destroy(cfg); 05685 05686 if (!reload && (!AST_LIST_EMPTY(&sla_stations) || !AST_LIST_EMPTY(&sla_stations))) 05687 ast_pthread_create(&sla.thread, NULL, sla_thread, NULL); 05688 05689 return res; 05690 }
static int sla_process_timers | ( | struct timespec * | ts | ) | [static] |
Calculate the time until the next known event.
Definition at line 4686 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().
04687 { 04688 unsigned int timeout = UINT_MAX; 04689 struct timeval tv; 04690 unsigned int change_made = 0; 04691 04692 /* Check for ring timeouts on ringing trunks */ 04693 if (sla_calc_trunk_timeouts(&timeout)) 04694 change_made = 1; 04695 04696 /* Check for ring timeouts on ringing stations */ 04697 if (sla_calc_station_timeouts(&timeout)) 04698 change_made = 1; 04699 04700 /* Check for station ring delays */ 04701 if (sla_calc_station_delays(&timeout)) 04702 change_made = 1; 04703 04704 /* queue reprocessing of ringing trunks */ 04705 if (change_made) 04706 sla_queue_event_nolock(SLA_EVENT_RINGING_TRUNK); 04707 04708 /* No timeout */ 04709 if (timeout == UINT_MAX) 04710 return 0; 04711 04712 if (ts) { 04713 tv = ast_tvadd(ast_tvnow(), ast_samp2tv(timeout, 1000)); 04714 ts->tv_sec = tv.tv_sec; 04715 ts->tv_nsec = tv.tv_usec * 1000; 04716 } 04717 04718 return 1; 04719 }
static void sla_queue_event | ( | enum sla_event_type | type | ) | [static] |
Definition at line 1454 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().
01455 { 01456 sla_queue_event_full(type, NULL, NULL, 1); 01457 }
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 1460 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(), chan, 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().
01462 { 01463 struct sla_station *station; 01464 struct sla_trunk_ref *trunk_ref = NULL; 01465 char *trunk_name; 01466 01467 trunk_name = ast_strdupa(conf->confno); 01468 strsep(&trunk_name, "_"); 01469 if (ast_strlen_zero(trunk_name)) { 01470 ast_log(LOG_ERROR, "Invalid conference name for SLA - '%s'!\n", conf->confno); 01471 return; 01472 } 01473 01474 AST_RWLIST_RDLOCK(&sla_stations); 01475 AST_RWLIST_TRAVERSE(&sla_stations, station, entry) { 01476 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) { 01477 if (trunk_ref->chan == chan && !strcmp(trunk_ref->trunk->name, trunk_name)) 01478 break; 01479 } 01480 if (trunk_ref) 01481 break; 01482 } 01483 AST_RWLIST_UNLOCK(&sla_stations); 01484 01485 if (!trunk_ref) { 01486 ast_debug(1, "Trunk not found for event!\n"); 01487 return; 01488 } 01489 01490 sla_queue_event_full(type, trunk_ref, station, 1); 01491 }
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 1422 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().
01424 { 01425 struct sla_event *event; 01426 01427 if (sla.thread == AST_PTHREADT_NULL) { 01428 return; 01429 } 01430 01431 if (!(event = ast_calloc(1, sizeof(*event)))) 01432 return; 01433 01434 event->type = type; 01435 event->trunk_ref = trunk_ref; 01436 event->station = station; 01437 01438 if (!lock) { 01439 AST_LIST_INSERT_TAIL(&sla.event_q, event, entry); 01440 return; 01441 } 01442 01443 ast_mutex_lock(&sla.lock); 01444 AST_LIST_INSERT_TAIL(&sla.event_q, event, entry); 01445 ast_cond_signal(&sla.cond); 01446 ast_mutex_unlock(&sla.lock); 01447 }
static void sla_queue_event_nolock | ( | enum sla_event_type | type | ) | [static] |
Definition at line 1449 of file app_meetme.c.
References sla_queue_event_full().
Referenced by sla_process_timers().
01450 { 01451 sla_queue_event_full(type, NULL, NULL, 0); 01452 }
static int sla_ring_station | ( | struct sla_ringing_trunk * | ringing_trunk, | |
struct sla_station * | station | |||
) | [static] |
Ring a station.
Definition at line 4303 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_free, AST_LIST_INSERT_HEAD, ast_strdup, ast_strdupa, ast_strlen_zero(), ast_tvnow(), sla_trunk::chan, ast_channel::cid, ast_callerid::cid_name, cid_name, ast_callerid::cid_num, cid_num, sla_station::device, sla_station::dial, announce_listitem::entry, sla, sla_create_ringing_station(), sla_dial_state_callback(), sla_failed_station::station, sla_ringing_station::station, strsep(), and sla_ringing_trunk::trunk.
Referenced by sla_ring_stations().
04304 { 04305 char *tech, *tech_data; 04306 struct ast_dial *dial; 04307 struct sla_ringing_station *ringing_station; 04308 const char *cid_name = NULL, *cid_num = NULL; 04309 enum ast_dial_result res; 04310 04311 if (!(dial = ast_dial_create())) 04312 return -1; 04313 04314 ast_dial_set_state_callback(dial, sla_dial_state_callback); 04315 tech_data = ast_strdupa(station->device); 04316 tech = strsep(&tech_data, "/"); 04317 04318 if (ast_dial_append(dial, tech, tech_data) == -1) { 04319 ast_dial_destroy(dial); 04320 return -1; 04321 } 04322 04323 if (!sla.attempt_callerid && !ast_strlen_zero(ringing_trunk->trunk->chan->cid.cid_name)) { 04324 cid_name = ast_strdupa(ringing_trunk->trunk->chan->cid.cid_name); 04325 ast_free(ringing_trunk->trunk->chan->cid.cid_name); 04326 ringing_trunk->trunk->chan->cid.cid_name = NULL; 04327 } 04328 if (!sla.attempt_callerid && !ast_strlen_zero(ringing_trunk->trunk->chan->cid.cid_num)) { 04329 cid_num = ast_strdupa(ringing_trunk->trunk->chan->cid.cid_num); 04330 ast_free(ringing_trunk->trunk->chan->cid.cid_num); 04331 ringing_trunk->trunk->chan->cid.cid_num = NULL; 04332 } 04333 04334 res = ast_dial_run(dial, ringing_trunk->trunk->chan, 1); 04335 04336 if (cid_name) 04337 ringing_trunk->trunk->chan->cid.cid_name = ast_strdup(cid_name); 04338 if (cid_num) 04339 ringing_trunk->trunk->chan->cid.cid_num = ast_strdup(cid_num); 04340 04341 if (res != AST_DIAL_RESULT_TRYING) { 04342 struct sla_failed_station *failed_station; 04343 ast_dial_destroy(dial); 04344 if (!(failed_station = ast_calloc(1, sizeof(*failed_station)))) 04345 return -1; 04346 failed_station->station = station; 04347 failed_station->last_try = ast_tvnow(); 04348 AST_LIST_INSERT_HEAD(&sla.failed_stations, failed_station, entry); 04349 return -1; 04350 } 04351 if (!(ringing_station = sla_create_ringing_station(station))) { 04352 ast_dial_join(dial); 04353 ast_dial_destroy(dial); 04354 return -1; 04355 } 04356 04357 station->dial = dial; 04358 04359 AST_LIST_INSERT_HEAD(&sla.ringing_stations, ringing_station, entry); 04360 04361 return 0; 04362 }
static void sla_ring_stations | ( | void | ) | [static] |
Ring stations based on current set of ringing trunks.
Definition at line 4429 of file app_meetme.c.
References AST_LIST_TRAVERSE, announce_listitem::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().
04430 { 04431 struct sla_station_ref *station_ref; 04432 struct sla_ringing_trunk *ringing_trunk; 04433 04434 /* Make sure that every station that uses at least one of the ringing 04435 * trunks, is ringing. */ 04436 AST_LIST_TRAVERSE(&sla.ringing_trunks, ringing_trunk, entry) { 04437 AST_LIST_TRAVERSE(&ringing_trunk->trunk->stations, station_ref, entry) { 04438 int time_left; 04439 04440 /* Is this station already ringing? */ 04441 if (sla_check_ringing_station(station_ref->station)) 04442 continue; 04443 04444 /* Is this station already in a call? */ 04445 if (sla_check_inuse_station(station_ref->station)) 04446 continue; 04447 04448 /* Did we fail to dial this station earlier? If so, has it been 04449 * a minute since we tried? */ 04450 if (sla_check_failed_station(station_ref->station)) 04451 continue; 04452 04453 /* If this station already timed out while this trunk was ringing, 04454 * do not dial it again for this ringing trunk. */ 04455 if (sla_check_timed_out_station(ringing_trunk, station_ref->station)) 04456 continue; 04457 04458 /* Check for a ring delay in progress */ 04459 time_left = sla_check_station_delay(station_ref->station, ringing_trunk); 04460 if (time_left != INT_MAX && time_left > 0) 04461 continue; 04462 04463 /* It is time to make this station begin to ring. Do it! */ 04464 sla_ring_station(ringing_trunk, station_ref->station); 04465 } 04466 } 04467 /* Now, all of the stations that should be ringing, are ringing. */ 04468 }
static char* sla_show_stations | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 1238 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.
01239 { 01240 const struct sla_station *station; 01241 01242 switch (cmd) { 01243 case CLI_INIT: 01244 e->command = "sla show stations"; 01245 e->usage = 01246 "Usage: sla show stations\n" 01247 " This will list all stations defined in sla.conf\n"; 01248 return NULL; 01249 case CLI_GENERATE: 01250 return NULL; 01251 } 01252 01253 ast_cli(a->fd, "\n" 01254 "=============================================================\n" 01255 "=== Configured SLA Stations =================================\n" 01256 "=============================================================\n" 01257 "===\n"); 01258 AST_RWLIST_RDLOCK(&sla_stations); 01259 AST_RWLIST_TRAVERSE(&sla_stations, station, entry) { 01260 struct sla_trunk_ref *trunk_ref; 01261 char ring_timeout[16] = "(none)"; 01262 char ring_delay[16] = "(none)"; 01263 if (station->ring_timeout) { 01264 snprintf(ring_timeout, sizeof(ring_timeout), 01265 "%u", station->ring_timeout); 01266 } 01267 if (station->ring_delay) { 01268 snprintf(ring_delay, sizeof(ring_delay), 01269 "%u", station->ring_delay); 01270 } 01271 ast_cli(a->fd, "=== ---------------------------------------------------------\n" 01272 "=== Station Name: %s\n" 01273 "=== ==> Device: %s\n" 01274 "=== ==> AutoContext: %s\n" 01275 "=== ==> RingTimeout: %s\n" 01276 "=== ==> RingDelay: %s\n" 01277 "=== ==> HoldAccess: %s\n" 01278 "=== ==> Trunks ...\n", 01279 station->name, station->device, 01280 S_OR(station->autocontext, "(none)"), 01281 ring_timeout, ring_delay, 01282 sla_hold_str(station->hold_access)); 01283 AST_RWLIST_RDLOCK(&sla_trunks); 01284 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) { 01285 if (trunk_ref->ring_timeout) { 01286 snprintf(ring_timeout, sizeof(ring_timeout), 01287 "%u", trunk_ref->ring_timeout); 01288 } else 01289 strcpy(ring_timeout, "(none)"); 01290 if (trunk_ref->ring_delay) { 01291 snprintf(ring_delay, sizeof(ring_delay), 01292 "%u", trunk_ref->ring_delay); 01293 } else 01294 strcpy(ring_delay, "(none)"); 01295 ast_cli(a->fd, "=== ==> Trunk Name: %s\n" 01296 "=== ==> State: %s\n" 01297 "=== ==> RingTimeout: %s\n" 01298 "=== ==> RingDelay: %s\n", 01299 trunk_ref->trunk->name, 01300 trunkstate2str(trunk_ref->state), 01301 ring_timeout, ring_delay); 01302 } 01303 AST_RWLIST_UNLOCK(&sla_trunks); 01304 ast_cli(a->fd, "=== ---------------------------------------------------------\n" 01305 "===\n"); 01306 } 01307 AST_RWLIST_UNLOCK(&sla_stations); 01308 ast_cli(a->fd, "============================================================\n" 01309 "\n"); 01310 01311 return CLI_SUCCESS; 01312 }
static char* sla_show_trunks | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 1173 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.
01174 { 01175 const struct sla_trunk *trunk; 01176 01177 switch (cmd) { 01178 case CLI_INIT: 01179 e->command = "sla show trunks"; 01180 e->usage = 01181 "Usage: sla show trunks\n" 01182 " This will list all trunks defined in sla.conf\n"; 01183 return NULL; 01184 case CLI_GENERATE: 01185 return NULL; 01186 } 01187 01188 ast_cli(a->fd, "\n" 01189 "=============================================================\n" 01190 "=== Configured SLA Trunks ===================================\n" 01191 "=============================================================\n" 01192 "===\n"); 01193 AST_RWLIST_RDLOCK(&sla_trunks); 01194 AST_RWLIST_TRAVERSE(&sla_trunks, trunk, entry) { 01195 struct sla_station_ref *station_ref; 01196 char ring_timeout[16] = "(none)"; 01197 if (trunk->ring_timeout) 01198 snprintf(ring_timeout, sizeof(ring_timeout), "%u Seconds", trunk->ring_timeout); 01199 ast_cli(a->fd, "=== ---------------------------------------------------------\n" 01200 "=== Trunk Name: %s\n" 01201 "=== ==> Device: %s\n" 01202 "=== ==> AutoContext: %s\n" 01203 "=== ==> RingTimeout: %s\n" 01204 "=== ==> BargeAllowed: %s\n" 01205 "=== ==> HoldAccess: %s\n" 01206 "=== ==> Stations ...\n", 01207 trunk->name, trunk->device, 01208 S_OR(trunk->autocontext, "(none)"), 01209 ring_timeout, 01210 trunk->barge_disabled ? "No" : "Yes", 01211 sla_hold_str(trunk->hold_access)); 01212 AST_RWLIST_RDLOCK(&sla_stations); 01213 AST_LIST_TRAVERSE(&trunk->stations, station_ref, entry) 01214 ast_cli(a->fd, "=== ==> Station name: %s\n", station_ref->station->name); 01215 AST_RWLIST_UNLOCK(&sla_stations); 01216 ast_cli(a->fd, "=== ---------------------------------------------------------\n===\n"); 01217 } 01218 AST_RWLIST_UNLOCK(&sla_trunks); 01219 ast_cli(a->fd, "=============================================================\n\n"); 01220 01221 return CLI_SUCCESS; 01222 }
static enum ast_device_state sla_state | ( | const char * | data | ) | [static] |
Definition at line 5282 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, buf, announce_listitem::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().
05283 { 05284 char *buf, *station_name, *trunk_name; 05285 struct sla_station *station; 05286 struct sla_trunk_ref *trunk_ref; 05287 enum ast_device_state res = AST_DEVICE_INVALID; 05288 05289 trunk_name = buf = ast_strdupa(data); 05290 station_name = strsep(&trunk_name, "_"); 05291 05292 AST_RWLIST_RDLOCK(&sla_stations); 05293 AST_LIST_TRAVERSE(&sla_stations, station, entry) { 05294 if (strcasecmp(station_name, station->name)) 05295 continue; 05296 AST_RWLIST_RDLOCK(&sla_trunks); 05297 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) { 05298 if (!strcasecmp(trunk_name, trunk_ref->trunk->name)) 05299 break; 05300 } 05301 if (!trunk_ref) { 05302 AST_RWLIST_UNLOCK(&sla_trunks); 05303 break; 05304 } 05305 res = sla_state_to_devstate(trunk_ref->state); 05306 AST_RWLIST_UNLOCK(&sla_trunks); 05307 } 05308 AST_RWLIST_UNLOCK(&sla_stations); 05309 05310 if (res == AST_DEVICE_INVALID) { 05311 ast_log(LOG_ERROR, "Could not determine state for trunk %s on station %s!\n", 05312 trunk_name, station_name); 05313 } 05314 05315 return res; 05316 }
static enum ast_device_state sla_state_to_devstate | ( | enum sla_trunk_state | state | ) | [static] |
Definition at line 3984 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().
03985 { 03986 switch (state) { 03987 case SLA_TRUNK_STATE_IDLE: 03988 return AST_DEVICE_NOT_INUSE; 03989 case SLA_TRUNK_STATE_RINGING: 03990 return AST_DEVICE_RINGING; 03991 case SLA_TRUNK_STATE_UP: 03992 return AST_DEVICE_INUSE; 03993 case SLA_TRUNK_STATE_ONHOLD: 03994 case SLA_TRUNK_STATE_ONHOLD_BYME: 03995 return AST_DEVICE_ONHOLD; 03996 } 03997 03998 return AST_DEVICE_UNKNOWN; 03999 }
static int sla_station_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Definition at line 4960 of file app_meetme.c.
References sla_trunk::active_stations, admin_exec(), ALL_TRUNK_REFS, answer_trunk_chan(), ast_answer(), ast_atomic_dec_and_test(), ast_atomic_fetchadd_int(), ast_autoservice_start(), ast_autoservice_stop(), ast_cond_destroy(), ast_cond_init(), ast_cond_wait(), AST_CONTROL_UNHOLD, ast_debug, AST_DEVICE_INUSE, ast_devstate_changed(), ast_indicate(), AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_log(), ast_mutex_destroy(), ast_mutex_init(), ast_mutex_lock(), ast_mutex_unlock(), ast_pthread_create_detached_background, AST_RWLIST_RDLOCK, AST_RWLIST_UNLOCK, ast_set_flag, ast_strdupa, ast_strlen_zero(), build_conf(), sla_trunk_ref::chan, sla_trunk::chan, chan, conf_run(), CONFFLAG_MARKEDEXIT, CONFFLAG_PASS_DTMF, CONFFLAG_QUIET, CONFFLAG_SLA_STATION, dial_trunk(), dispose_conf(), announce_listitem::entry, ast_flags::flags, 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().
04961 { 04962 char *station_name, *trunk_name; 04963 struct sla_station *station; 04964 struct sla_trunk_ref *trunk_ref = NULL; 04965 char conf_name[MAX_CONFNUM]; 04966 struct ast_flags conf_flags = { 0 }; 04967 struct ast_conference *conf; 04968 04969 if (ast_strlen_zero(data)) { 04970 ast_log(LOG_WARNING, "Invalid Arguments to SLAStation!\n"); 04971 pbx_builtin_setvar_helper(chan, "SLASTATION_STATUS", "FAILURE"); 04972 return 0; 04973 } 04974 04975 trunk_name = ast_strdupa(data); 04976 station_name = strsep(&trunk_name, "_"); 04977 04978 if (ast_strlen_zero(station_name)) { 04979 ast_log(LOG_WARNING, "Invalid Arguments to SLAStation!\n"); 04980 pbx_builtin_setvar_helper(chan, "SLASTATION_STATUS", "FAILURE"); 04981 return 0; 04982 } 04983 04984 AST_RWLIST_RDLOCK(&sla_stations); 04985 station = sla_find_station(station_name); 04986 if (station) 04987 ast_atomic_fetchadd_int((int *) &station->ref_count, 1); 04988 AST_RWLIST_UNLOCK(&sla_stations); 04989 04990 if (!station) { 04991 ast_log(LOG_WARNING, "Station '%s' not found!\n", station_name); 04992 pbx_builtin_setvar_helper(chan, "SLASTATION_STATUS", "FAILURE"); 04993 sla_queue_event(SLA_EVENT_CHECK_RELOAD); 04994 return 0; 04995 } 04996 04997 AST_RWLIST_RDLOCK(&sla_trunks); 04998 if (!ast_strlen_zero(trunk_name)) { 04999 trunk_ref = sla_find_trunk_ref_byname(station, trunk_name); 05000 } else 05001 trunk_ref = sla_choose_idle_trunk(station); 05002 AST_RWLIST_UNLOCK(&sla_trunks); 05003 05004 if (!trunk_ref) { 05005 if (ast_strlen_zero(trunk_name)) 05006 ast_log(LOG_NOTICE, "No trunks available for call.\n"); 05007 else { 05008 ast_log(LOG_NOTICE, "Can't join existing call on trunk " 05009 "'%s' due to access controls.\n", trunk_name); 05010 } 05011 pbx_builtin_setvar_helper(chan, "SLASTATION_STATUS", "CONGESTION"); 05012 ast_atomic_fetchadd_int((int *) &station->ref_count, -1); 05013 sla_queue_event(SLA_EVENT_CHECK_RELOAD); 05014 return 0; 05015 } 05016 05017 if (trunk_ref->state == SLA_TRUNK_STATE_ONHOLD_BYME) { 05018 if (ast_atomic_dec_and_test((int *) &trunk_ref->trunk->hold_stations) == 1) 05019 sla_change_trunk_state(trunk_ref->trunk, SLA_TRUNK_STATE_UP, ALL_TRUNK_REFS, NULL); 05020 else { 05021 trunk_ref->state = SLA_TRUNK_STATE_UP; 05022 ast_devstate_changed(AST_DEVICE_INUSE, 05023 "SLA:%s_%s", station->name, trunk_ref->trunk->name); 05024 } 05025 } else if (trunk_ref->state == SLA_TRUNK_STATE_RINGING) { 05026 struct sla_ringing_trunk *ringing_trunk; 05027 05028 ast_mutex_lock(&sla.lock); 05029 AST_LIST_TRAVERSE_SAFE_BEGIN(&sla.ringing_trunks, ringing_trunk, entry) { 05030 if (ringing_trunk->trunk == trunk_ref->trunk) { 05031 AST_LIST_REMOVE_CURRENT(entry); 05032 break; 05033 } 05034 } 05035 AST_LIST_TRAVERSE_SAFE_END 05036 ast_mutex_unlock(&sla.lock); 05037 05038 if (ringing_trunk) { 05039 answer_trunk_chan(ringing_trunk->trunk->chan); 05040 sla_change_trunk_state(ringing_trunk->trunk, SLA_TRUNK_STATE_UP, ALL_TRUNK_REFS, NULL); 05041 05042 free(ringing_trunk); 05043 05044 /* Queue up reprocessing ringing trunks, and then ringing stations again */ 05045 sla_queue_event(SLA_EVENT_RINGING_TRUNK); 05046 sla_queue_event(SLA_EVENT_DIAL_STATE); 05047 } 05048 } 05049 05050 trunk_ref->chan = chan; 05051 05052 if (!trunk_ref->trunk->chan) { 05053 ast_mutex_t cond_lock; 05054 ast_cond_t cond; 05055 pthread_t dont_care; 05056 struct dial_trunk_args args = { 05057 .trunk_ref = trunk_ref, 05058 .station = station, 05059 .cond_lock = &cond_lock, 05060 .cond = &cond, 05061 }; 05062 sla_change_trunk_state(trunk_ref->trunk, SLA_TRUNK_STATE_UP, ALL_TRUNK_REFS, NULL); 05063 /* Create a thread to dial the trunk and dump it into the conference. 05064 * However, we want to wait until the trunk has been dialed and the 05065 * conference is created before continuing on here. */ 05066 ast_autoservice_start(chan); 05067 ast_mutex_init(&cond_lock); 05068 ast_cond_init(&cond, NULL); 05069 ast_mutex_lock(&cond_lock); 05070 ast_pthread_create_detached_background(&dont_care, NULL, dial_trunk, &args); 05071 ast_cond_wait(&cond, &cond_lock); 05072 ast_mutex_unlock(&cond_lock); 05073 ast_mutex_destroy(&cond_lock); 05074 ast_cond_destroy(&cond); 05075 ast_autoservice_stop(chan); 05076 if (!trunk_ref->trunk->chan) { 05077 ast_debug(1, "Trunk didn't get created. chan: %lx\n", (long) trunk_ref->trunk->chan); 05078 pbx_builtin_setvar_helper(chan, "SLASTATION_STATUS", "CONGESTION"); 05079 sla_change_trunk_state(trunk_ref->trunk, SLA_TRUNK_STATE_IDLE, ALL_TRUNK_REFS, NULL); 05080 trunk_ref->chan = NULL; 05081 ast_atomic_fetchadd_int((int *) &station->ref_count, -1); 05082 sla_queue_event(SLA_EVENT_CHECK_RELOAD); 05083 return 0; 05084 } 05085 } 05086 05087 if (ast_atomic_fetchadd_int((int *) &trunk_ref->trunk->active_stations, 1) == 0 && 05088 trunk_ref->trunk->on_hold) { 05089 trunk_ref->trunk->on_hold = 0; 05090 ast_indicate(trunk_ref->trunk->chan, AST_CONTROL_UNHOLD); 05091 sla_change_trunk_state(trunk_ref->trunk, SLA_TRUNK_STATE_UP, ALL_TRUNK_REFS, NULL); 05092 } 05093 05094 snprintf(conf_name, sizeof(conf_name), "SLA_%s", trunk_ref->trunk->name); 05095 ast_set_flag(&conf_flags, 05096 CONFFLAG_QUIET | CONFFLAG_MARKEDEXIT | CONFFLAG_PASS_DTMF | CONFFLAG_SLA_STATION); 05097 ast_answer(chan); 05098 conf = build_conf(conf_name, "", "", 0, 0, 1, chan); 05099 if (conf) { 05100 conf_run(chan, conf, conf_flags.flags, NULL); 05101 dispose_conf(conf); 05102 conf = NULL; 05103 } 05104 trunk_ref->chan = NULL; 05105 if (ast_atomic_dec_and_test((int *) &trunk_ref->trunk->active_stations) && 05106 trunk_ref->state != SLA_TRUNK_STATE_ONHOLD_BYME) { 05107 strncat(conf_name, ",K", sizeof(conf_name) - strlen(conf_name) - 1); 05108 admin_exec(NULL, conf_name); 05109 trunk_ref->trunk->hold_stations = 0; 05110 sla_change_trunk_state(trunk_ref->trunk, SLA_TRUNK_STATE_IDLE, ALL_TRUNK_REFS, NULL); 05111 } 05112 05113 pbx_builtin_setvar_helper(chan, "SLASTATION_STATUS", "SUCCESS"); 05114 05115 ast_atomic_fetchadd_int((int *) &station->ref_count, -1); 05116 sla_queue_event(SLA_EVENT_CHECK_RELOAD); 05117 05118 return 0; 05119 }
static void sla_stop_ringing_station | ( | struct sla_ringing_station * | ringing_station, | |
enum sla_station_hangup | hangup | |||
) | [static] |
Definition at line 4093 of file app_meetme.c.
References ast_dial_destroy(), ast_dial_join(), ast_free, AST_LIST_INSERT_TAIL, AST_LIST_TRAVERSE, sla_station::dial, announce_listitem::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().
04095 { 04096 struct sla_ringing_trunk *ringing_trunk; 04097 struct sla_trunk_ref *trunk_ref; 04098 struct sla_station_ref *station_ref; 04099 04100 ast_dial_join(ringing_station->station->dial); 04101 ast_dial_destroy(ringing_station->station->dial); 04102 ringing_station->station->dial = NULL; 04103 04104 if (hangup == SLA_STATION_HANGUP_NORMAL) 04105 goto done; 04106 04107 /* If the station is being hung up because of a timeout, then add it to the 04108 * list of timed out stations on each of the ringing trunks. This is so 04109 * that when doing further processing to figure out which stations should be 04110 * ringing, which trunk to answer, determining timeouts, etc., we know which 04111 * ringing trunks we should ignore. */ 04112 AST_LIST_TRAVERSE(&sla.ringing_trunks, ringing_trunk, entry) { 04113 AST_LIST_TRAVERSE(&ringing_station->station->trunks, trunk_ref, entry) { 04114 if (ringing_trunk->trunk == trunk_ref->trunk) 04115 break; 04116 } 04117 if (!trunk_ref) 04118 continue; 04119 if (!(station_ref = sla_create_station_ref(ringing_station->station))) 04120 continue; 04121 AST_LIST_INSERT_TAIL(&ringing_trunk->timed_out_stations, station_ref, entry); 04122 } 04123 04124 done: 04125 ast_free(ringing_station); 04126 }
static void sla_stop_ringing_trunk | ( | struct sla_ringing_trunk * | ringing_trunk | ) | [static] |
Definition at line 4078 of file app_meetme.c.
References admin_exec(), ALL_TRUNK_REFS, ast_free, AST_LIST_REMOVE_HEAD, buf, announce_listitem::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().
04079 { 04080 char buf[80]; 04081 struct sla_station_ref *station_ref; 04082 04083 snprintf(buf, sizeof(buf), "SLA_%s,K", ringing_trunk->trunk->name); 04084 admin_exec(NULL, buf); 04085 sla_change_trunk_state(ringing_trunk->trunk, SLA_TRUNK_STATE_IDLE, ALL_TRUNK_REFS, NULL); 04086 04087 while ((station_ref = AST_LIST_REMOVE_HEAD(&ringing_trunk->timed_out_stations, entry))) 04088 ast_free(station_ref); 04089 04090 ast_free(ringing_trunk); 04091 }
static void* sla_thread | ( | void * | data | ) | [static] |
Definition at line 4766 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(), announce_listitem::entry, 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().
04767 { 04768 struct sla_failed_station *failed_station; 04769 struct sla_ringing_station *ringing_station; 04770 04771 ast_mutex_lock(&sla.lock); 04772 04773 while (!sla.stop) { 04774 struct sla_event *event; 04775 struct timespec ts = { 0, }; 04776 unsigned int have_timeout = 0; 04777 04778 if (AST_LIST_EMPTY(&sla.event_q)) { 04779 if ((have_timeout = sla_process_timers(&ts))) 04780 ast_cond_timedwait(&sla.cond, &sla.lock, &ts); 04781 else 04782 ast_cond_wait(&sla.cond, &sla.lock); 04783 if (sla.stop) 04784 break; 04785 } 04786 04787 if (have_timeout) 04788 sla_process_timers(NULL); 04789 04790 while ((event = AST_LIST_REMOVE_HEAD(&sla.event_q, entry))) { 04791 ast_mutex_unlock(&sla.lock); 04792 switch (event->type) { 04793 case SLA_EVENT_HOLD: 04794 sla_handle_hold_event(event); 04795 break; 04796 case SLA_EVENT_DIAL_STATE: 04797 sla_handle_dial_state_event(); 04798 break; 04799 case SLA_EVENT_RINGING_TRUNK: 04800 sla_handle_ringing_trunk_event(); 04801 break; 04802 case SLA_EVENT_RELOAD: 04803 sla.reload = 1; 04804 case SLA_EVENT_CHECK_RELOAD: 04805 break; 04806 } 04807 ast_free(event); 04808 ast_mutex_lock(&sla.lock); 04809 } 04810 04811 if (sla.reload) 04812 sla_check_reload(); 04813 } 04814 04815 ast_mutex_unlock(&sla.lock); 04816 04817 while ((ringing_station = AST_LIST_REMOVE_HEAD(&sla.ringing_stations, entry))) 04818 ast_free(ringing_station); 04819 04820 while ((failed_station = AST_LIST_REMOVE_HEAD(&sla.failed_stations, entry))) 04821 ast_free(failed_station); 04822 04823 return NULL; 04824 }
static int sla_trunk_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Definition at line 5167 of file app_meetme.c.
References ALL_TRUNK_REFS, 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_flag, AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), ast_test_flag, build_conf(), sla_trunk::chan, chan, conf_run(), CONFFLAG_MARKEDEXIT, CONFFLAG_MARKEDUSER, CONFFLAG_MOH, CONFFLAG_NO_AUDIO_UNTIL_UP, CONFFLAG_PASS_DTMF, CONFFLAG_QUIET, dispose_conf(), announce_listitem::entry, ast_flags::flags, 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().
05168 { 05169 char conf_name[MAX_CONFNUM]; 05170 struct ast_conference *conf; 05171 struct ast_flags conf_flags = { 0 }; 05172 struct sla_trunk *trunk; 05173 struct sla_ringing_trunk *ringing_trunk; 05174 AST_DECLARE_APP_ARGS(args, 05175 AST_APP_ARG(trunk_name); 05176 AST_APP_ARG(options); 05177 ); 05178 char *opts[SLA_TRUNK_OPT_ARG_ARRAY_SIZE] = { NULL, }; 05179 char *conf_opt_args[OPT_ARG_ARRAY_SIZE] = { NULL, }; 05180 struct ast_flags opt_flags = { 0 }; 05181 char *parse; 05182 05183 if (ast_strlen_zero(data)) { 05184 ast_log(LOG_ERROR, "The SLATrunk application requires an argument, the trunk name\n"); 05185 return -1; 05186 } 05187 05188 parse = ast_strdupa(data); 05189 AST_STANDARD_APP_ARGS(args, parse); 05190 if (args.argc == 2) { 05191 if (ast_app_parse_options(sla_trunk_opts, &opt_flags, opts, args.options)) { 05192 ast_log(LOG_ERROR, "Error parsing options for SLATrunk\n"); 05193 return -1; 05194 } 05195 } 05196 05197 AST_RWLIST_RDLOCK(&sla_trunks); 05198 trunk = sla_find_trunk(args.trunk_name); 05199 if (trunk) 05200 ast_atomic_fetchadd_int((int *) &trunk->ref_count, 1); 05201 AST_RWLIST_UNLOCK(&sla_trunks); 05202 05203 if (!trunk) { 05204 ast_log(LOG_ERROR, "SLA Trunk '%s' not found!\n", args.trunk_name); 05205 pbx_builtin_setvar_helper(chan, "SLATRUNK_STATUS", "FAILURE"); 05206 ast_atomic_fetchadd_int((int *) &trunk->ref_count, -1); 05207 sla_queue_event(SLA_EVENT_CHECK_RELOAD); 05208 return 0; 05209 } 05210 05211 if (trunk->chan) { 05212 ast_log(LOG_ERROR, "Call came in on %s, but the trunk is already in use!\n", 05213 args.trunk_name); 05214 pbx_builtin_setvar_helper(chan, "SLATRUNK_STATUS", "FAILURE"); 05215 ast_atomic_fetchadd_int((int *) &trunk->ref_count, -1); 05216 sla_queue_event(SLA_EVENT_CHECK_RELOAD); 05217 return 0; 05218 } 05219 05220 trunk->chan = chan; 05221 05222 if (!(ringing_trunk = queue_ringing_trunk(trunk))) { 05223 pbx_builtin_setvar_helper(chan, "SLATRUNK_STATUS", "FAILURE"); 05224 ast_atomic_fetchadd_int((int *) &trunk->ref_count, -1); 05225 sla_queue_event(SLA_EVENT_CHECK_RELOAD); 05226 return 0; 05227 } 05228 05229 snprintf(conf_name, sizeof(conf_name), "SLA_%s", args.trunk_name); 05230 conf = build_conf(conf_name, "", "", 1, 1, 1, chan); 05231 if (!conf) { 05232 pbx_builtin_setvar_helper(chan, "SLATRUNK_STATUS", "FAILURE"); 05233 ast_atomic_fetchadd_int((int *) &trunk->ref_count, -1); 05234 sla_queue_event(SLA_EVENT_CHECK_RELOAD); 05235 return 0; 05236 } 05237 ast_set_flag(&conf_flags, 05238 CONFFLAG_QUIET | CONFFLAG_MARKEDEXIT | CONFFLAG_MARKEDUSER | CONFFLAG_PASS_DTMF | CONFFLAG_NO_AUDIO_UNTIL_UP); 05239 05240 if (ast_test_flag(&opt_flags, SLA_TRUNK_OPT_MOH)) { 05241 ast_indicate(chan, -1); 05242 ast_set_flag(&conf_flags, CONFFLAG_MOH); 05243 conf_opt_args[OPT_ARG_MOH_CLASS] = opts[SLA_TRUNK_OPT_ARG_MOH_CLASS]; 05244 } else 05245 ast_indicate(chan, AST_CONTROL_RINGING); 05246 05247 conf_run(chan, conf, conf_flags.flags, opts); 05248 dispose_conf(conf); 05249 conf = NULL; 05250 trunk->chan = NULL; 05251 trunk->on_hold = 0; 05252 05253 sla_change_trunk_state(trunk, SLA_TRUNK_STATE_IDLE, ALL_TRUNK_REFS, NULL); 05254 05255 if (!pbx_builtin_getvar_helper(chan, "SLATRUNK_STATUS")) 05256 pbx_builtin_setvar_helper(chan, "SLATRUNK_STATUS", "SUCCESS"); 05257 05258 /* Remove the entry from the list of ringing trunks if it is still there. */ 05259 ast_mutex_lock(&sla.lock); 05260 AST_LIST_TRAVERSE_SAFE_BEGIN(&sla.ringing_trunks, ringing_trunk, entry) { 05261 if (ringing_trunk->trunk == trunk) { 05262 AST_LIST_REMOVE_CURRENT(entry); 05263 break; 05264 } 05265 } 05266 AST_LIST_TRAVERSE_SAFE_END; 05267 ast_mutex_unlock(&sla.lock); 05268 if (ringing_trunk) { 05269 ast_free(ringing_trunk); 05270 pbx_builtin_setvar_helper(chan, "SLATRUNK_STATUS", "UNANSWERED"); 05271 /* Queue reprocessing of ringing trunks to make stations stop ringing 05272 * that shouldn't be ringing after this trunk stopped. */ 05273 sla_queue_event(SLA_EVENT_RINGING_TRUNK); 05274 } 05275 05276 ast_atomic_fetchadd_int((int *) &trunk->ref_count, -1); 05277 sla_queue_event(SLA_EVENT_CHECK_RELOAD); 05278 05279 return 0; 05280 }
static const char* trunkstate2str | ( | enum sla_trunk_state | state | ) | [static] |
Definition at line 1224 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().
01225 { 01226 #define S(e) case e: return # e; 01227 switch (state) { 01228 S(SLA_TRUNK_STATE_IDLE) 01229 S(SLA_TRUNK_STATE_RINGING) 01230 S(SLA_TRUNK_STATE_UP) 01231 S(SLA_TRUNK_STATE_ONHOLD) 01232 S(SLA_TRUNK_STATE_ONHOLD_BYME) 01233 } 01234 return "Uknown State"; 01235 #undef S 01236 }
static void tweak_listen_volume | ( | struct ast_conf_user * | user, | |
enum volume_action | action | |||
) | [static] |
Definition at line 762 of file app_meetme.c.
References set_listen_volume(), tweak_volume(), and user.
Referenced by admin_exec(), and conf_run().
00763 { 00764 tweak_volume(&user->listen, action); 00765 /* attempt to make the adjustment in the channel driver; 00766 if successful, don't adjust in the frame reading routine 00767 */ 00768 if (!set_listen_volume(user, user->listen.desired)) 00769 user->listen.actual = 0; 00770 else 00771 user->listen.actual = user->listen.desired; 00772 }
static void tweak_talk_volume | ( | struct ast_conf_user * | user, | |
enum volume_action | action | |||
) | [static] |
Definition at line 750 of file app_meetme.c.
References set_talk_volume(), tweak_volume(), and user.
Referenced by admin_exec(), and conf_run().
00751 { 00752 tweak_volume(&user->talk, action); 00753 /* attempt to make the adjustment in the channel driver; 00754 if successful, don't adjust in the frame reading routine 00755 */ 00756 if (!set_talk_volume(user, user->talk.desired)) 00757 user->talk.actual = 0; 00758 else 00759 user->talk.actual = user->talk.desired; 00760 }
static void tweak_volume | ( | struct volume * | vol, | |
enum volume_action | action | |||
) | [static] |
Definition at line 715 of file app_meetme.c.
References volume::desired, and VOL_UP.
Referenced by tweak_listen_volume(), and tweak_talk_volume().
00716 { 00717 switch (action) { 00718 case VOL_UP: 00719 switch (vol->desired) { 00720 case 5: 00721 break; 00722 case 0: 00723 vol->desired = 2; 00724 break; 00725 case -2: 00726 vol->desired = 0; 00727 break; 00728 default: 00729 vol->desired++; 00730 break; 00731 } 00732 break; 00733 case VOL_DOWN: 00734 switch (vol->desired) { 00735 case -5: 00736 break; 00737 case 2: 00738 vol->desired = 0; 00739 break; 00740 case 0: 00741 vol->desired = -2; 00742 break; 00743 default: 00744 vol->desired--; 00745 break; 00746 } 00747 } 00748 }
static int unload_module | ( | void | ) | [static] |
Definition at line 5706 of file app_meetme.c.
References ARRAY_LEN, ast_cli_unregister_multiple(), ast_devstate_prov_del(), ast_manager_unregister(), ast_unregister_application(), cli_meetme, and sla_destroy().
05707 { 05708 int res = 0; 05709 05710 ast_cli_unregister_multiple(cli_meetme, ARRAY_LEN(cli_meetme)); 05711 res = ast_manager_unregister("MeetmeMute"); 05712 res |= ast_manager_unregister("MeetmeUnmute"); 05713 res |= ast_manager_unregister("MeetmeList"); 05714 res |= ast_unregister_application(app4); 05715 res |= ast_unregister_application(app3); 05716 res |= ast_unregister_application(app2); 05717 res |= ast_unregister_application(app); 05718 res |= ast_unregister_application(slastation_app); 05719 res |= ast_unregister_application(slatrunk_app); 05720 05721 ast_devstate_prov_del("Meetme"); 05722 ast_devstate_prov_del("SLA"); 05723 05724 sla_destroy(); 05725 05726 return res; 05727 }
struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .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 = "068e67f60f50dd9ee86464c05884a49d" , .load = load_module, .unload = unload_module, .reload = reload, } [static] |
Definition at line 5766 of file app_meetme.c.
const char* app = "MeetMe" [static] |
Definition at line 211 of file app_meetme.c.
const char* app2 = "MeetMeCount" [static] |
const char* app3 = "MeetMeAdmin" [static] |
Definition at line 213 of file app_meetme.c.
const char* app4 = "MeetMeChannelAdmin" [static] |
Definition at line 214 of file app_meetme.c.
const struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 5766 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 619 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 628 of file app_meetme.c.
struct ast_cli_entry cli_meetme[] [static] |
Initial value:
{ { .handler = meetme_cmd , .summary = "Execute a command on a conference or conferee" ,__VA_ARGS__ }, { .handler = sla_show_trunks , .summary = "Show SLA Trunks" ,__VA_ARGS__ }, { .handler = sla_show_stations , .summary = "Show SLA Stations" ,__VA_ARGS__ }, }
Definition at line 1314 of file app_meetme.c.
Referenced by load_module(), and unload_module().
Definition at line 610 of file app_meetme.c.
unsigned int conf_map[1024] = {0, } [static] |
Definition at line 421 of file app_meetme.c.
Referenced by build_conf(), conf_exec(), and dispose_conf().
const char* descrip [static] |
Definition at line 234 of file app_meetme.c.
const char* descrip2 [static] |
Definition at line 297 of file app_meetme.c.
const char* descrip3 [static] |
Definition at line 305 of file app_meetme.c.
const char* descrip4 [static] |
Definition at line 328 of file app_meetme.c.
int earlyalert [static] |
Definition at line 228 of file app_meetme.c.
int endalert [static] |
Definition at line 229 of file app_meetme.c.
struct { ... } event_q |
struct { ... } failed_stations |
Definition at line 615 of file app_meetme.c.
struct sla_failed_station* first |
Definition at line 614 of file app_meetme.c.
struct sla_ringing_station* first |
Definition at line 613 of file app_meetme.c.
struct sla_ringing_trunk* first |
Definition at line 612 of file app_meetme.c.
int fuzzystart [static] |
Definition at line 227 of file app_meetme.c.
char const gain_map[] [static] |
Map 'volume' levels from -5 through +5 into decibel (dB) settings for channel drivers Note: these are not a straight linear-to-dB conversion... the numbers have been modified to give the user a better level of adjustability
Definition at line 636 of file app_meetme.c.
Definition at line 615 of file app_meetme.c.
struct sla_failed_station* last |
Definition at line 614 of file app_meetme.c.
struct sla_ringing_station* last |
Definition at line 613 of file app_meetme.c.
struct sla_ringing_trunk* last |
Definition at line 612 of file app_meetme.c.
Definition at line 611 of file app_meetme.c.
char mandescr_meetmelist[] [static] |
Definition at line 3655 of file app_meetme.c.
struct ast_app_option meetme_opts[128] = { [ 'A' ] = { .flag = CONFFLAG_MARKEDUSER }, [ 'a' ] = { .flag = CONFFLAG_ADMIN }, [ 'b' ] = { .flag = CONFFLAG_AGI }, [ 'c' ] = { .flag = CONFFLAG_ANNOUNCEUSERCOUNT }, [ 'C' ] = { .flag = CONFFLAG_KICK_CONTINUE }, [ 'D' ] = { .flag = CONFFLAG_DYNAMICPIN }, [ 'd' ] = { .flag = CONFFLAG_DYNAMIC }, [ 'E' ] = { .flag = CONFFLAG_EMPTYNOPIN }, [ 'e' ] = { .flag = CONFFLAG_EMPTY }, [ 'F' ] = { .flag = CONFFLAG_PASS_DTMF }, [ '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 621 of file app_meetme.c.
Referenced by handle_cli_moh_reload(), handle_cli_rpt_reload(), handle_minivm_reload(), reload(), and show_console().
struct { ... } ringing_stations |
struct { ... } ringing_trunks |
int rt_log_members [static] |
Definition at line 232 of file app_meetme.c.
int rt_schedule [static] |
Definition at line 226 of file app_meetme.c.
struct { ... } sla [static] |
A structure for data used by the sla thread.
Referenced by dial_trunk(), 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 551 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* slastation_app = "SLAStation" [static] |
Definition at line 215 of file app_meetme.c.
const char* slastation_desc [static] |
Definition at line 336 of file app_meetme.c.
const char* slastation_synopsis = "Shared Line Appearance Station" [static] |
Definition at line 222 of file app_meetme.c.
const char* slatrunk_app = "SLATrunk" [static] |
Definition at line 216 of file app_meetme.c.
const char* slatrunk_desc [static] |
Definition at line 349 of file app_meetme.c.
const char* slatrunk_synopsis = "Shared Line Appearance Trunk" [static] |
Definition at line 223 of file app_meetme.c.
unsigned int stop |
Definition at line 616 of file app_meetme.c.
const char* synopsis = "MeetMe conference bridge" [static] |
Definition at line 218 of file app_meetme.c.
const char* synopsis2 = "MeetMe participant count" [static] |
Definition at line 219 of file app_meetme.c.
const char* synopsis3 = "MeetMe conference Administration" [static] |
Definition at line 220 of file app_meetme.c.
const char* synopsis4 = "MeetMe conference Administration (channel specific)" [static] |
Definition at line 221 of file app_meetme.c.
pthread_t thread |
The SLA thread ID
Definition at line 609 of file app_meetme.c.