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