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