#include "asterisk.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include "asterisk/lock.h"
#include "asterisk/file.h"
#include "asterisk/logger.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/options.h"
#include "asterisk/cli.h"
#include "asterisk/say.h"
#include "asterisk/utils.h"
#include "asterisk/translate.h"
#include "asterisk/ulaw.h"
#include "asterisk/astobj.h"
#include "asterisk/astobj2.h"
#include "asterisk/devicestate.h"
#include "asterisk/dial.h"
#include "asterisk/causes.h"
#include "asterisk/dahdi_compat.h"
#include "enter.h"
#include "leave.h"
Go to the source code of this file.
Data Structures | |
struct | announce_listitem |
struct | ast_conf_user |
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 | DEFAULT_AUDIO_BUFFERS 32 |
#define | MAX_CONFNUM 80 |
#define | MAX_PIN 80 |
#define | MAX_SETTINGS (MAX_CONFNUM + MAX_PIN + MAX_PIN + 3) |
#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) } |
enum | { CONFFLAG_ADMIN = (1 << 0), CONFFLAG_MONITOR = (1 << 1), CONFFLAG_POUNDEXIT = (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_NO_AUDIO_UNTIL_UP = (1 << 28), CONFFLAG_INTROMSG = (1 << 29) } |
enum | { OPT_ARG_WAITMARKED = 0, OPT_ARG_INTROMSG = 1, OPT_ARG_ARRAY_SIZE = 2 } |
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 } |
Event types that can be queued up for the SLA thread. More... | |
enum | sla_hold_access { SLA_HOLD_OPEN, SLA_HOLD_PRIVATE } |
enum | sla_station_hangup { SLA_STATION_HANGUP_NORMAL, SLA_STATION_HANGUP_TIMEOUT } |
enum | sla_trunk_state { SLA_TRUNK_STATE_IDLE, SLA_TRUNK_STATE_RINGING, SLA_TRUNK_STATE_UP, SLA_TRUNK_STATE_ONHOLD, SLA_TRUNK_STATE_ONHOLD_BYME } |
enum | sla_which_trunk_refs { ALL_TRUNK_REFS, INACTIVE_TRUNK_REFS } |
enum | volume_action { VOL_UP, VOL_DOWN } |
Functions | |
static void | __reg_module (void) |
static void | __unreg_module (void) |
static int | action_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) |
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 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 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) |
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 int | meetme_cmd (int fd, int argc, char **argv) |
static int | meetmemute (struct mansession *s, const struct message *m, int mute) |
static int | 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 int | sla_check_ringing_station (const struct sla_station *station) |
Check to see if this station is already ringing. | |
static int | sla_check_station_delay (struct sla_station *station, struct sla_ringing_trunk *ringing_trunk) |
Calculate the ring delay for a given ringing trunk on a station. | |
static int | sla_check_station_hold_access (const struct sla_trunk *trunk, const struct sla_station *station) |
static int | sla_check_timed_out_station (const struct sla_ringing_trunk *ringing_trunk, const struct sla_station *station) |
Check to see if dialing this station already timed out for this ringing trunk. | |
static struct sla_trunk_ref * | sla_choose_idle_trunk (const struct sla_station *station) |
For a given station, choose the highest priority idle trunk. | |
static struct sla_ringing_trunk * | sla_choose_ringing_trunk (struct sla_station *station, struct sla_trunk_ref **trunk_ref, int remove) |
Choose the highest priority ringing trunk for a station. | |
static struct sla_ringing_station * | sla_create_ringing_station (struct sla_station *station) |
static struct sla_station_ref * | sla_create_station_ref (struct sla_station *station) |
static void | sla_destroy (void) |
static void | sla_dial_state_callback (struct ast_dial *dial) |
static struct sla_station * | sla_find_station (const char *name) |
Find an SLA station by name. | |
static struct sla_trunk * | sla_find_trunk (const char *name) |
Find an SLA trunk by name. | |
static struct sla_trunk_ref * | sla_find_trunk_ref (const struct sla_station *station, const struct sla_trunk *trunk) |
static struct sla_trunk_ref * | sla_find_trunk_ref_byname (const struct sla_station *station, const char *name) |
Find a trunk reference on a station by name. | |
static void | sla_handle_dial_state_event (void) |
static void | sla_handle_hold_event (struct sla_event *event) |
static void | sla_handle_ringing_trunk_event (void) |
static void | sla_hangup_stations (void) |
static const char * | sla_hold_str (unsigned int hold_access) |
static int | sla_load_config (void) |
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 int | sla_show_stations (int fd, int argc, char **argv) |
static int | sla_show_trunks (int fd, int argc, char **argv) |
static int | sla_state (const char *data) |
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) |
static int | user_listen_voldown_cb (void *obj, void *unused, int flags) |
static int | user_listen_volup_cb (void *obj, void *unused, int flags) |
static int | user_max_cmp (void *obj, void *arg, int flags) |
static int | user_no_cmp (void *obj, void *arg, int flags) |
static int | user_reset_vol_cb (void *obj, void *unused, int flags) |
static int | user_set_kickme_cb (void *obj, void *unused, int flags) |
static int | user_set_muted_cb (void *obj, void *unused, int flags) |
static int | user_set_unmuted_cb (void *obj, void *unused, int flags) |
static int | user_talk_voldown_cb (void *obj, void *unused, int flags) |
static int | user_talk_volup_cb (void *obj, void *unused, int flags) |
Variables | |
static struct ast_module_info | __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT | AST_MODFLAG_BUILDSUM, .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 = "361d7bb937402d51e4658efb5b4d76e4" , .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 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 char const | gain_map [] |
static struct ast_app_option | meetme_opts [128] = { [ 'A' ] = { .flag = CONFFLAG_MARKEDUSER }, [ 'a' ] = { .flag = CONFFLAG_ADMIN }, [ 'b' ] = { .flag = CONFFLAG_AGI }, [ 'c' ] = { .flag = CONFFLAG_ANNOUNCEUSERCOUNT }, [ 'D' ] = { .flag = CONFFLAG_DYNAMICPIN }, [ 'd' ] = { .flag = CONFFLAG_DYNAMIC }, [ 'E' ] = { .flag = CONFFLAG_EMPTYNOPIN }, [ 'e' ] = { .flag = CONFFLAG_EMPTY }, [ 'F' ] = { .flag = CONFFLAG_PASS_DTMF }, [ 'G' ] = { .flag = CONFFLAG_INTROMSG , .arg_index = OPT_ARG_INTROMSG + 1 }, [ 'i' ] = { .flag = CONFFLAG_INTROUSER }, [ 'I' ] = { .flag = CONFFLAG_INTROUSERNOREVIEW }, [ 'M' ] = { .flag = CONFFLAG_MOH }, [ 'm' ] = { .flag = CONFFLAG_STARTMUTED }, [ 'o' ] = { .flag = CONFFLAG_OPTIMIZETALKER }, [ 'P' ] = { .flag = CONFFLAG_ALWAYSPROMPT }, [ 'p' ] = { .flag = CONFFLAG_POUNDEXIT }, [ '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 }, } |
static char | meetme_usage [] |
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 | |
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 const char | sla_show_stations_usage [] |
static const char | sla_show_trunks_usage [] |
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" |
(SLA) Russell Bryant <russell@digium.com>
Definition in file app_meetme.c.
#define AST_FRAME_BITS 32 |
Definition at line 92 of file app_meetme.c.
Referenced by conf_free(), conf_run(), and recordthread().
#define CONF_SIZE 320 |
Definition at line 111 of file app_meetme.c.
#define CONFIG_FILE_NAME "meetme.conf" |
Definition at line 77 of file app_meetme.c.
Referenced by conf_exec(), find_conf(), and load_config_meetme().
#define DEFAULT_AUDIO_BUFFERS 32 |
each buffer is 20ms, so this is 640ms total
Definition at line 81 of file app_meetme.c.
Referenced by load_config_meetme().
#define MAX_CONFNUM 80 |
Definition at line 325 of file app_meetme.c.
Referenced by conf_exec(), dial_trunk(), run_station(), sla_station_exec(), and sla_trunk_exec().
#define MAX_PIN 80 |
#define MAX_SETTINGS (MAX_CONFNUM + MAX_PIN + MAX_PIN + 3) |
#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 |
Definition at line 83 of file app_meetme.c.
00083 { 00084 ADMINFLAG_MUTED = (1 << 1), /*!< User is muted */ 00085 ADMINFLAG_SELFMUTED = (1 << 2), /*!< User muted self */ 00086 ADMINFLAG_KICKME = (1 << 3) /*!< User has been kicked */ 00087 };
anonymous enum |
Definition at line 113 of file app_meetme.c.
00113 { 00114 /*! user has admin access on the conference */ 00115 CONFFLAG_ADMIN = (1 << 0), 00116 /*! If set the user can only receive audio from the conference */ 00117 CONFFLAG_MONITOR = (1 << 1), 00118 /*! If set asterisk will exit conference when '#' is pressed */ 00119 CONFFLAG_POUNDEXIT = (1 << 2), 00120 /*! If set asterisk will provide a menu to the user when '*' is pressed */ 00121 CONFFLAG_STARMENU = (1 << 3), 00122 /*! If set the use can only send audio to the conference */ 00123 CONFFLAG_TALKER = (1 << 4), 00124 /*! If set there will be no enter or leave sounds */ 00125 CONFFLAG_QUIET = (1 << 5), 00126 /*! If set, when user joins the conference, they will be told the number 00127 * of users that are already in */ 00128 CONFFLAG_ANNOUNCEUSERCOUNT = (1 << 6), 00129 /*! Set to run AGI Script in Background */ 00130 CONFFLAG_AGI = (1 << 7), 00131 /*! Set to have music on hold when user is alone in conference */ 00132 CONFFLAG_MOH = (1 << 8), 00133 /*! If set the MeetMe will return if all marked with this flag left */ 00134 CONFFLAG_MARKEDEXIT = (1 << 9), 00135 /*! If set, the MeetMe will wait until a marked user enters */ 00136 CONFFLAG_WAITMARKED = (1 << 10), 00137 /*! If set, the MeetMe will exit to the specified context */ 00138 CONFFLAG_EXIT_CONTEXT = (1 << 11), 00139 /*! If set, the user will be marked */ 00140 CONFFLAG_MARKEDUSER = (1 << 12), 00141 /*! If set, user will be ask record name on entry of conference */ 00142 CONFFLAG_INTROUSER = (1 << 13), 00143 /*! If set, the MeetMe will be recorded */ 00144 CONFFLAG_RECORDCONF = (1<< 14), 00145 /*! If set, the user will be monitored if the user is talking or not */ 00146 CONFFLAG_MONITORTALKER = (1 << 15), 00147 CONFFLAG_DYNAMIC = (1 << 16), 00148 CONFFLAG_DYNAMICPIN = (1 << 17), 00149 CONFFLAG_EMPTY = (1 << 18), 00150 CONFFLAG_EMPTYNOPIN = (1 << 19), 00151 CONFFLAG_ALWAYSPROMPT = (1 << 20), 00152 /*! If set, treats talking users as muted users */ 00153 CONFFLAG_OPTIMIZETALKER = (1 << 21), 00154 /*! If set, won't speak the extra prompt when the first person 00155 * enters the conference */ 00156 CONFFLAG_NOONLYPERSON = (1 << 22), 00157 /*! If set, user will be asked to record name on entry of conference 00158 * without review */ 00159 CONFFLAG_INTROUSERNOREVIEW = (1 << 23), 00160 /*! If set, the user will be initially self-muted */ 00161 CONFFLAG_STARTMUTED = (1 << 24), 00162 /*! Pass DTMF through the conference */ 00163 CONFFLAG_PASS_DTMF = (1 << 25), 00164 /*! This is a SLA station. (Only for use by the SLA applications.) */ 00165 CONFFLAG_SLA_STATION = (1 << 26), 00166 /*! This is a SLA trunk. (Only for use by the SLA applications.) */ 00167 CONFFLAG_SLA_TRUNK = (1 << 27), 00168 /*! Do not write any audio to this channel until the state is up. */ 00169 CONFFLAG_NO_AUDIO_UNTIL_UP = (1 << 28), 00170 /*! Play an arbitrary Intro message */ 00171 CONFFLAG_INTROMSG = (1 << 29), 00172 };
anonymous enum |
Definition at line 174 of file app_meetme.c.
00174 { 00175 OPT_ARG_WAITMARKED = 0, 00176 OPT_ARG_INTROMSG = 1, 00177 OPT_ARG_ARRAY_SIZE = 2, 00178 };
enum announcetypes |
enum entrance_sound |
enum recording_state |
Definition at line 104 of file app_meetme.c.
00104 { 00105 MEETME_RECORD_OFF, 00106 MEETME_RECORD_STARTED, 00107 MEETME_RECORD_ACTIVE, 00108 MEETME_RECORD_TERMINATE 00109 };
enum sla_event_type |
Event types that can be queued up for the SLA thread.
SLA_EVENT_HOLD | A station has put the call on hold |
SLA_EVENT_DIAL_STATE | The state of a dial has changed |
SLA_EVENT_RINGING_TRUNK | The state of a ringing trunk has changed |
Definition at line 505 of file app_meetme.c.
00505 { 00506 /*! A station has put the call on hold */ 00507 SLA_EVENT_HOLD, 00508 /*! The state of a dial has changed */ 00509 SLA_EVENT_DIAL_STATE, 00510 /*! The state of a ringing trunk has changed */ 00511 SLA_EVENT_RINGING_TRUNK, 00512 };
enum sla_hold_access |
Definition at line 419 of file app_meetme.c.
00419 { 00420 /*! This means that any station can put it on hold, and any station 00421 * can retrieve the call from hold. */ 00422 SLA_HOLD_OPEN, 00423 /*! This means that only the station that put the call on hold may 00424 * retrieve it from hold. */ 00425 SLA_HOLD_PRIVATE, 00426 };
enum sla_station_hangup |
Definition at line 538 of file app_meetme.c.
00538 { 00539 SLA_STATION_HANGUP_NORMAL, 00540 SLA_STATION_HANGUP_TIMEOUT, 00541 };
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 411 of file app_meetme.c.
00411 { 00412 SLA_TRUNK_STATE_IDLE, 00413 SLA_TRUNK_STATE_RINGING, 00414 SLA_TRUNK_STATE_UP, 00415 SLA_TRUNK_STATE_ONHOLD, 00416 SLA_TRUNK_STATE_ONHOLD_BYME, 00417 };
enum sla_which_trunk_refs |
Definition at line 406 of file app_meetme.c.
00406 { 00407 ALL_TRUNK_REFS, 00408 INACTIVE_TRUNK_REFS, 00409 };
enum volume_action |
static void __reg_module | ( | void | ) | [static] |
Definition at line 5204 of file app_meetme.c.
static void __unreg_module | ( | void | ) | [static] |
Definition at line 5204 of file app_meetme.c.
static int action_meetmemute | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 3317 of file app_meetme.c.
References meetmemute(), and s.
Referenced by load_module().
03318 { 03319 return meetmemute(s, m, 1); 03320 }
static int action_meetmeunmute | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 3322 of file app_meetme.c.
References meetmemute(), and s.
Referenced by load_module().
03323 { 03324 return meetmemute(s, m, 0); 03325 }
static int admin_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
The MeetMeadmin application.
Definition at line 3123 of file app_meetme.c.
References ADMINFLAG_KICKME, ADMINFLAG_MUTED, ADMINFLAG_SELFMUTED, ast_conf_user::adminflags, ao2_callback(), ao2_find(), ao2_ref(), AST_APP_ARG, ast_atomic_fetchadd_int(), AST_DECLARE_APP_ARGS, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_module_user_add, ast_module_user_remove, AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), ast_module_user::chan, ast_conference::confno, dispose_conf(), find_user(), ast_conference::locked, LOG_NOTICE, LOG_WARNING, ast_conference::refcount, reset_volumes(), tweak_listen_volume(), tweak_talk_volume(), user_listen_voldown_cb(), user_listen_volup_cb(), user_max_cmp(), user_reset_vol_cb(), user_set_kickme_cb(), user_set_muted_cb(), user_set_unmuted_cb(), user_talk_voldown_cb(), user_talk_volup_cb(), ast_conference::usercontainer, ast_conf_user::userflags, and VOL_UP.
Referenced by load_module(), meetme_cmd(), run_station(), sla_station_exec(), and sla_stop_ringing_trunk().
03123 { 03124 char *params; 03125 struct ast_conference *cnf; 03126 struct ast_conf_user *user = NULL; 03127 struct ast_module_user *u; 03128 AST_DECLARE_APP_ARGS(args, 03129 AST_APP_ARG(confno); 03130 AST_APP_ARG(command); 03131 AST_APP_ARG(user); 03132 ); 03133 03134 if (ast_strlen_zero(data)) { 03135 ast_log(LOG_WARNING, "MeetMeAdmin requires an argument!\n"); 03136 return -1; 03137 } 03138 03139 u = ast_module_user_add(chan); 03140 03141 AST_LIST_LOCK(&confs); 03142 03143 params = ast_strdupa(data); 03144 AST_STANDARD_APP_ARGS(args, params); 03145 03146 if (!args.command) { 03147 ast_log(LOG_WARNING, "MeetmeAdmin requires a command!\n"); 03148 AST_LIST_UNLOCK(&confs); 03149 ast_module_user_remove(u); 03150 return -1; 03151 } 03152 AST_LIST_TRAVERSE(&confs, cnf, list) { 03153 if (!strcmp(cnf->confno, args.confno)) 03154 break; 03155 } 03156 03157 if (!cnf) { 03158 ast_log(LOG_WARNING, "Conference number '%s' not found!\n", args.confno); 03159 AST_LIST_UNLOCK(&confs); 03160 ast_module_user_remove(u); 03161 return 0; 03162 } 03163 03164 ast_atomic_fetchadd_int(&cnf->refcount, 1); 03165 03166 if (args.user) { 03167 user = find_user(cnf, args.user); 03168 if (!user) { 03169 ast_log(LOG_NOTICE, "Specified User not found!\n"); 03170 goto usernotfound; 03171 } 03172 } 03173 03174 switch (*args.command) { 03175 case 76: /* L: Lock */ 03176 cnf->locked = 1; 03177 break; 03178 case 108: /* l: Unlock */ 03179 cnf->locked = 0; 03180 break; 03181 case 75: /* K: kick all users */ 03182 ao2_callback(cnf->usercontainer, 0, user_set_kickme_cb, NULL); 03183 break; 03184 case 101: /* e: Eject last user*/ 03185 { 03186 int max_no = 0; 03187 ao2_callback(cnf->usercontainer, OBJ_NODATA, user_max_cmp, &max_no); 03188 user = ao2_find(cnf->usercontainer, &max_no, 0); 03189 if (!(user->userflags & CONFFLAG_ADMIN)) 03190 user->adminflags |= ADMINFLAG_KICKME; 03191 else 03192 ast_log(LOG_NOTICE, "Not kicking last user, is an Admin!\n"); 03193 ao2_ref(user, -1); 03194 break; 03195 } 03196 case 77: /* M: Mute */ 03197 user->adminflags |= ADMINFLAG_MUTED; 03198 break; 03199 case 78: /* N: Mute all (non-admin) users */ 03200 ao2_callback(cnf->usercontainer, 0, user_set_muted_cb, NULL); 03201 break; 03202 case 109: /* m: Unmute */ 03203 user->adminflags &= ~(ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED); 03204 break; 03205 case 110: /* n: Unmute all users */ 03206 ao2_callback(cnf->usercontainer, 0, user_set_unmuted_cb, NULL); 03207 break; 03208 case 107: /* k: Kick user */ 03209 user->adminflags |= ADMINFLAG_KICKME; 03210 break; 03211 case 118: /* v: Lower all users listen volume */ 03212 ao2_callback(cnf->usercontainer, 0, user_listen_voldown_cb, NULL); 03213 break; 03214 case 86: /* V: Raise all users listen volume */ 03215 ao2_callback(cnf->usercontainer, 0, user_listen_volup_cb, NULL); 03216 break; 03217 case 115: /* s: Lower all users speaking volume */ 03218 ao2_callback(cnf->usercontainer, 0, user_talk_voldown_cb, NULL); 03219 break; 03220 case 83: /* S: Raise all users speaking volume */ 03221 ao2_callback(cnf->usercontainer, 0, user_talk_volup_cb, NULL); 03222 break; 03223 case 82: /* R: Reset all volume levels */ 03224 ao2_callback(cnf->usercontainer, 0, user_reset_vol_cb, NULL); 03225 break; 03226 case 114: /* r: Reset user's volume level */ 03227 reset_volumes(user); 03228 break; 03229 case 85: /* U: Raise user's listen volume */ 03230 tweak_listen_volume(user, VOL_UP); 03231 break; 03232 case 117: /* u: Lower user's listen volume */ 03233 tweak_listen_volume(user, VOL_DOWN); 03234 break; 03235 case 84: /* T: Raise user's talk volume */ 03236 tweak_talk_volume(user, VOL_UP); 03237 break; 03238 case 116: /* t: Lower user's talk volume */ 03239 tweak_talk_volume(user, VOL_DOWN); 03240 break; 03241 } 03242 03243 if (args.user) { 03244 /* decrement reference from find_user */ 03245 ao2_ref(user, -1); 03246 } 03247 usernotfound: 03248 AST_LIST_UNLOCK(&confs); 03249 03250 dispose_conf(cnf); 03251 03252 ast_module_user_remove(u); 03253 03254 return 0; 03255 }
static void* announce_thread | ( | void * | data | ) | [static] |
Definition at line 1495 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().
01496 { 01497 struct announce_listitem *current; 01498 struct ast_conference *conf = data; 01499 int res; 01500 char filename[PATH_MAX] = ""; 01501 AST_LIST_HEAD_NOLOCK(, announce_listitem) local_list; 01502 AST_LIST_HEAD_INIT_NOLOCK(&local_list); 01503 01504 while (!conf->announcethread_stop) { 01505 ast_mutex_lock(&conf->announcelistlock); 01506 if (conf->announcethread_stop) { 01507 ast_mutex_unlock(&conf->announcelistlock); 01508 break; 01509 } 01510 if (AST_LIST_EMPTY(&conf->announcelist)) 01511 ast_cond_wait(&conf->announcelist_addition, &conf->announcelistlock); 01512 01513 AST_LIST_APPEND_LIST(&local_list, &conf->announcelist, entry); 01514 AST_LIST_HEAD_INIT_NOLOCK(&conf->announcelist); 01515 01516 ast_mutex_unlock(&conf->announcelistlock); 01517 if (conf->announcethread_stop) { 01518 break; 01519 } 01520 01521 for (res = 1; !conf->announcethread_stop && (current = AST_LIST_REMOVE_HEAD(&local_list, entry)); ao2_ref(current, -1)) { 01522 ast_log(LOG_DEBUG, "About to play %s\n", current->namerecloc); 01523 if (!ast_fileexists(current->namerecloc, NULL, NULL)) 01524 continue; 01525 if ((current->confchan) && (current->confusers > 1) && !ast_check_hangup(current->confchan)) { 01526 if (!ast_streamfile(current->confchan, current->namerecloc, current->language)) 01527 res = ast_waitstream(current->confchan, ""); 01528 if (!res) { 01529 ast_copy_string(filename, get_announce_filename(current->announcetype), sizeof(filename)); 01530 if (!ast_streamfile(current->confchan, filename, current->language)) 01531 ast_waitstream(current->confchan, ""); 01532 } 01533 } 01534 if (current->announcetype == CONF_HASLEFT) { 01535 ast_filedelete(current->namerecloc, NULL); 01536 } 01537 } 01538 } 01539 01540 /* thread marked to stop, clean up */ 01541 while ((current = AST_LIST_REMOVE_HEAD(&local_list, entry))) { 01542 ast_filedelete(current->namerecloc, NULL); 01543 ao2_ref(current, -1); 01544 } 01545 return NULL; 01546 }
static void answer_trunk_chan | ( | struct ast_channel * | chan | ) | [static] |
Definition at line 3573 of file app_meetme.c.
References ast_answer(), ast_indicate(), and sla_trunk_ref::chan.
Referenced by run_station(), sla_handle_dial_state_event(), and sla_station_exec().
03574 { 03575 ast_answer(chan); 03576 ast_indicate(chan, -1); 03577 }
static struct ast_conference* build_conf | ( | char * | confno, | |
char * | pin, | |||
char * | pinadmin, | |||
int | make, | |||
int | dynamic, | |||
int | refcount | |||
) | [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 |
Definition at line 798 of file app_meetme.c.
References ao2_container_alloc(), ao2_ref(), ast_atomic_fetchadd_int(), ast_calloc, ast_copy_string(), AST_FORMAT_SLINEAR, ast_hangup(), AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_mutex_destroy(), ast_mutex_init(), AST_PTHREADT_NULL, ast_request(), ast_set_read_format(), ast_set_write_format(), ast_verbose(), conf_map, ast_conference::confno, dahdi_chan_name, DAHDI_FILE_PSEUDO, free, LOG_WARNING, option_verbose, user_no_cmp(), and VERBOSE_PREFIX_3.
Referenced by find_conf(), find_conf_realtime(), run_station(), sla_station_exec(), and sla_trunk_exec().
00799 { 00800 struct ast_conference *cnf; 00801 struct dahdi_confinfo ztc = { 0, }; 00802 int confno_int = 0; 00803 00804 AST_LIST_LOCK(&confs); 00805 00806 AST_LIST_TRAVERSE(&confs, cnf, list) { 00807 if (!strcmp(confno, cnf->confno)) 00808 break; 00809 } 00810 00811 if (cnf || (!make && !dynamic)) 00812 goto cnfout; 00813 00814 /* Make a new one */ 00815 if (!(cnf = ast_calloc(1, sizeof(*cnf))) || 00816 !(cnf->usercontainer = ao2_container_alloc(1, NULL, user_no_cmp))) { 00817 goto cnfout; 00818 } 00819 00820 ast_mutex_init(&cnf->playlock); 00821 ast_mutex_init(&cnf->listenlock); 00822 cnf->recordthread = AST_PTHREADT_NULL; 00823 ast_mutex_init(&cnf->recordthreadlock); 00824 cnf->announcethread = AST_PTHREADT_NULL; 00825 ast_mutex_init(&cnf->announcethreadlock); 00826 ast_copy_string(cnf->confno, confno, sizeof(cnf->confno)); 00827 ast_copy_string(cnf->pin, pin, sizeof(cnf->pin)); 00828 ast_copy_string(cnf->pinadmin, pinadmin, sizeof(cnf->pinadmin)); 00829 00830 /* Setup a new zap conference */ 00831 ztc.confno = -1; 00832 ztc.confmode = DAHDI_CONF_CONFANN | DAHDI_CONF_CONFANNMON; 00833 cnf->fd = open(DAHDI_FILE_PSEUDO, O_RDWR); 00834 if (cnf->fd < 0 || ioctl(cnf->fd, DAHDI_SETCONF, &ztc)) { 00835 ast_log(LOG_WARNING, "Unable to open DAHDI pseudo device\n"); 00836 if (cnf->fd >= 0) 00837 close(cnf->fd); 00838 ao2_ref(cnf->usercontainer, -1); 00839 ast_mutex_destroy(&cnf->playlock); 00840 ast_mutex_destroy(&cnf->listenlock); 00841 ast_mutex_destroy(&cnf->recordthreadlock); 00842 ast_mutex_destroy(&cnf->announcethreadlock); 00843 free(cnf); 00844 cnf = NULL; 00845 goto cnfout; 00846 } 00847 00848 cnf->zapconf = ztc.confno; 00849 00850 /* Setup a new channel for playback of audio files */ 00851 cnf->chan = ast_request(dahdi_chan_name, AST_FORMAT_SLINEAR, "pseudo", NULL); 00852 if (cnf->chan) { 00853 ast_set_read_format(cnf->chan, AST_FORMAT_SLINEAR); 00854 ast_set_write_format(cnf->chan, AST_FORMAT_SLINEAR); 00855 ztc.chan = 0; 00856 ztc.confno = cnf->zapconf; 00857 ztc.confmode = DAHDI_CONF_CONFANN | DAHDI_CONF_CONFANNMON; 00858 if (ioctl(cnf->chan->fds[0], DAHDI_SETCONF, &ztc)) { 00859 ast_log(LOG_WARNING, "Error setting conference\n"); 00860 if (cnf->chan) 00861 ast_hangup(cnf->chan); 00862 else 00863 close(cnf->fd); 00864 ao2_ref(cnf->usercontainer, -1); 00865 ast_mutex_destroy(&cnf->playlock); 00866 ast_mutex_destroy(&cnf->listenlock); 00867 ast_mutex_destroy(&cnf->recordthreadlock); 00868 ast_mutex_destroy(&cnf->announcethreadlock); 00869 free(cnf); 00870 cnf = NULL; 00871 goto cnfout; 00872 } 00873 } 00874 00875 /* Fill the conference struct */ 00876 cnf->start = time(NULL); 00877 cnf->isdynamic = dynamic ? 1 : 0; 00878 if (option_verbose > 2) 00879 ast_verbose(VERBOSE_PREFIX_3 "Created MeetMe conference %d for conference '%s'\n", cnf->zapconf, cnf->confno); 00880 AST_LIST_INSERT_HEAD(&confs, cnf, list); 00881 00882 /* Reserve conference number in map */ 00883 if ((sscanf(cnf->confno, "%30d", &confno_int) == 1) && (confno_int >= 0 && confno_int < 1024)) 00884 conf_map[confno_int] = 1; 00885 00886 cnfout: 00887 if (cnf) 00888 ast_atomic_fetchadd_int(&cnf->refcount, refcount); 00889 00890 AST_LIST_UNLOCK(&confs); 00891 00892 return cnf; 00893 }
static int can_write | ( | struct ast_channel * | chan, | |
int | confflags | |||
) | [static] |
Definition at line 1548 of file app_meetme.c.
References ast_channel::_state, AST_STATE_UP, ast_conference::chan, and CONFFLAG_NO_AUDIO_UNTIL_UP.
Referenced by conf_run().
01549 { 01550 if (!(confflags & CONFFLAG_NO_AUDIO_UNTIL_UP)) { 01551 return 1; 01552 } 01553 01554 return (chan->_state == AST_STATE_UP); 01555 }
static int careful_write | ( | int | fd, | |
unsigned char * | data, | |||
int | len, | |||
int | block | |||
) | [static] |
Definition at line 609 of file app_meetme.c.
References ast_log(), errno, and LOG_WARNING.
00610 { 00611 int res; 00612 int x; 00613 00614 while (len) { 00615 if (block) { 00616 x = DAHDI_IOMUX_WRITE | DAHDI_IOMUX_SIGEVENT; 00617 res = ioctl(fd, DAHDI_IOMUX, &x); 00618 } else 00619 res = 0; 00620 if (res >= 0) 00621 res = write(fd, data, len); 00622 if (res < 1) { 00623 if (errno != EAGAIN) { 00624 ast_log(LOG_WARNING, "Failed to write audio data to conference: %s\n", strerror(errno)); 00625 return -1; 00626 } else 00627 return 0; 00628 } 00629 len -= res; 00630 data += res; 00631 } 00632 00633 return 0; 00634 }
static char* complete_meetmecmd | ( | const char * | line, | |
const char * | word, | |||
int | pos, | |||
int | state | |||
) | [static] |
Definition at line 1047 of file app_meetme.c.
References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next(), ao2_ref(), ast_cli_complete(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_strdup, ast_strdupa, ast_conference::confno, len(), ast_conf_user::list, strdup, ast_conf_user::user_no, and ast_conference::usercontainer.
01048 { 01049 static char *cmds[] = {"lock", "unlock", "mute", "unmute", "kick", "list", NULL}; 01050 01051 int len = strlen(word); 01052 int which = 0; 01053 struct ast_conference *cnf = NULL; 01054 struct ast_conf_user *usr = NULL; 01055 char *confno = NULL; 01056 char usrno[50] = ""; 01057 char *myline, *ret = NULL; 01058 01059 if (pos == 1) { /* Command */ 01060 return ast_cli_complete(word, cmds, state); 01061 } else if (pos == 2) { /* Conference Number */ 01062 AST_LIST_LOCK(&confs); 01063 AST_LIST_TRAVERSE(&confs, cnf, list) { 01064 if (!strncasecmp(word, cnf->confno, len) && ++which > state) { 01065 ret = cnf->confno; 01066 break; 01067 } 01068 } 01069 ret = ast_strdup(ret); /* dup before releasing the lock */ 01070 AST_LIST_UNLOCK(&confs); 01071 return ret; 01072 } else if (pos == 3) { 01073 /* User Number || Conf Command option*/ 01074 if (strstr(line, "mute") || strstr(line, "kick")) { 01075 if (state == 0 && (strstr(line, "kick") || strstr(line,"mute")) && !strncasecmp(word, "all", len)) 01076 return strdup("all"); 01077 which++; 01078 AST_LIST_LOCK(&confs); 01079 01080 /* TODO: Find the conf number from the cmdline (ignore spaces) <- test this and make it fail-safe! */ 01081 myline = ast_strdupa(line); 01082 if (strsep(&myline, " ") && strsep(&myline, " ") && !confno) { 01083 while((confno = strsep(&myline, " ")) && (strcmp(confno, " ") == 0)) 01084 ; 01085 } 01086 01087 AST_LIST_TRAVERSE(&confs, cnf, list) { 01088 if (!strcmp(confno, cnf->confno)) 01089 break; 01090 } 01091 01092 if (cnf) { 01093 struct ao2_iterator user_iter; 01094 user_iter = ao2_iterator_init(cnf->usercontainer, 0); 01095 /* Search for the user */ 01096 while((usr = ao2_iterator_next(&user_iter))) { 01097 snprintf(usrno, sizeof(usrno), "%d", usr->user_no); 01098 if (!strncasecmp(word, usrno, len) && ++which > state) { 01099 ao2_ref(usr, -1); 01100 break; 01101 } 01102 ao2_ref(usr, -1); 01103 } 01104 ao2_iterator_destroy(&user_iter); 01105 AST_LIST_UNLOCK(&confs); 01106 return usr ? strdup(usrno) : NULL; 01107 } 01108 AST_LIST_UNLOCK(&confs); 01109 } else if ( strstr(line, "list") && ( 0 == state ) ) 01110 return strdup("concise"); 01111 } 01112 01113 return NULL; 01114 }
static int conf_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
The meetme() application.
Definition at line 2798 of file app_meetme.c.
References ast_channel::_state, 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_module_user_add, ast_module_user_remove, 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(), conf_map, conf_run(), CONFFLAG_ALWAYSPROMPT, CONFFLAG_DYNAMIC, CONFFLAG_DYNAMICPIN, CONFFLAG_EMPTY, CONFFLAG_EMPTYNOPIN, CONFIG_FILE_NAME, ast_conference::confno, dispose_conf(), find_conf(), find_conf_realtime(), ast_flags::flags, ast_conference::isdynamic, LOG_ERROR, LOG_WARNING, MAX_CONFNUM, MAX_PIN, MAX_SETTINGS, meetme_opts, OPT_ARG_ARRAY_SIZE, parse(), ast_conference::pin, ast_conference::pinadmin, ast_conference::users, and var.
02799 { 02800 int res=-1; 02801 struct ast_module_user *u; 02802 char confno[MAX_CONFNUM] = ""; 02803 int allowretry = 0; 02804 int retrycnt = 0; 02805 struct ast_conference *cnf = NULL; 02806 struct ast_flags confflags = {0}; 02807 int dynamic = 0; 02808 int empty = 0, empty_no_pin = 0; 02809 int always_prompt = 0; 02810 char *notdata, *info, the_pin[MAX_PIN] = ""; 02811 AST_DECLARE_APP_ARGS(args, 02812 AST_APP_ARG(confno); 02813 AST_APP_ARG(options); 02814 AST_APP_ARG(pin); 02815 ); 02816 char *optargs[OPT_ARG_ARRAY_SIZE] = { NULL, }; 02817 02818 u = ast_module_user_add(chan); 02819 02820 if (ast_strlen_zero(data)) { 02821 allowretry = 1; 02822 notdata = ""; 02823 } else { 02824 notdata = data; 02825 } 02826 02827 if (chan->_state != AST_STATE_UP) 02828 ast_answer(chan); 02829 02830 info = ast_strdupa(notdata); 02831 02832 AST_STANDARD_APP_ARGS(args, info); 02833 02834 if (args.confno) { 02835 ast_copy_string(confno, args.confno, sizeof(confno)); 02836 if (ast_strlen_zero(confno)) { 02837 allowretry = 1; 02838 } 02839 } 02840 02841 if (args.pin) 02842 ast_copy_string(the_pin, args.pin, sizeof(the_pin)); 02843 02844 if (args.options) { 02845 ast_app_parse_options(meetme_opts, &confflags, optargs, args.options); 02846 dynamic = ast_test_flag(&confflags, CONFFLAG_DYNAMIC | CONFFLAG_DYNAMICPIN); 02847 if (ast_test_flag(&confflags, CONFFLAG_DYNAMICPIN) && ast_strlen_zero(args.pin)) 02848 strcpy(the_pin, "q"); 02849 02850 empty = ast_test_flag(&confflags, CONFFLAG_EMPTY | CONFFLAG_EMPTYNOPIN); 02851 empty_no_pin = ast_test_flag(&confflags, CONFFLAG_EMPTYNOPIN); 02852 always_prompt = ast_test_flag(&confflags, CONFFLAG_ALWAYSPROMPT | CONFFLAG_DYNAMICPIN); 02853 } 02854 02855 do { 02856 if (retrycnt > 3) 02857 allowretry = 0; 02858 if (empty) { 02859 int i; 02860 struct ast_config *cfg; 02861 struct ast_variable *var; 02862 int confno_int; 02863 02864 /* We only need to load the config file for static and empty_no_pin (otherwise we don't care) */ 02865 if ((empty_no_pin) || (!dynamic)) { 02866 cfg = ast_config_load(CONFIG_FILE_NAME); 02867 if (cfg) { 02868 var = ast_variable_browse(cfg, "rooms"); 02869 while (var) { 02870 char parse[MAX_SETTINGS], *stringp = parse, *confno_tmp; 02871 if (!strcasecmp(var->name, "conf")) { 02872 int found = 0; 02873 ast_copy_string(parse, var->value, sizeof(parse)); 02874 confno_tmp = strsep(&stringp, "|,"); 02875 if (!dynamic) { 02876 /* For static: run through the list and see if this conference is empty */ 02877 AST_LIST_LOCK(&confs); 02878 AST_LIST_TRAVERSE(&confs, cnf, list) { 02879 if (!strcmp(confno_tmp, cnf->confno)) { 02880 /* The conference exists, therefore it's not empty */ 02881 found = 1; 02882 break; 02883 } 02884 } 02885 AST_LIST_UNLOCK(&confs); 02886 if (!found) { 02887 /* At this point, we have a confno_tmp (static conference) that is empty */ 02888 if ((empty_no_pin && ast_strlen_zero(stringp)) || (!empty_no_pin)) { 02889 /* Case 1: empty_no_pin and pin is nonexistent (NULL) 02890 * Case 2: empty_no_pin and pin is blank (but not NULL) 02891 * Case 3: not empty_no_pin 02892 */ 02893 ast_copy_string(confno, confno_tmp, sizeof(confno)); 02894 break; 02895 /* XXX the map is not complete (but we do have a confno) */ 02896 } 02897 } 02898 } 02899 } 02900 var = var->next; 02901 } 02902 ast_config_destroy(cfg); 02903 } 02904 } 02905 02906 /* Select first conference number not in use */ 02907 if (ast_strlen_zero(confno) && dynamic) { 02908 AST_LIST_LOCK(&confs); 02909 for (i = 0; i < sizeof(conf_map) / sizeof(conf_map[0]); i++) { 02910 if (!conf_map[i]) { 02911 snprintf(confno, sizeof(confno), "%d", i); 02912 conf_map[i] = 1; 02913 break; 02914 } 02915 } 02916 AST_LIST_UNLOCK(&confs); 02917 } 02918 02919 /* Not found? */ 02920 if (ast_strlen_zero(confno)) { 02921 res = ast_streamfile(chan, "conf-noempty", chan->language); 02922 if (!res) 02923 ast_waitstream(chan, ""); 02924 } else { 02925 if (sscanf(confno, "%30d", &confno_int) == 1) { 02926 res = ast_streamfile(chan, "conf-enteringno", chan->language); 02927 if (!res) { 02928 ast_waitstream(chan, ""); 02929 res = ast_say_digits(chan, confno_int, "", chan->language); 02930 } 02931 } else { 02932 ast_log(LOG_ERROR, "Could not scan confno '%s'\n", confno); 02933 } 02934 } 02935 } 02936 02937 while (allowretry && (ast_strlen_zero(confno)) && (++retrycnt < 4)) { 02938 /* Prompt user for conference number */ 02939 res = ast_app_getdata(chan, "conf-getconfno", confno, sizeof(confno) - 1, 0); 02940 if (res < 0) { 02941 /* Don't try to validate when we catch an error */ 02942 confno[0] = '\0'; 02943 allowretry = 0; 02944 break; 02945 } 02946 } 02947 if (!ast_strlen_zero(confno)) { 02948 /* Check the validity of the conference */ 02949 cnf = find_conf(chan, confno, 1, dynamic, the_pin, 02950 sizeof(the_pin), 1, &confflags); 02951 if (!cnf) { 02952 cnf = find_conf_realtime(chan, confno, 1, dynamic, 02953 the_pin, sizeof(the_pin), 1, &confflags); 02954 } 02955 02956 if (!cnf) { 02957 res = ast_streamfile(chan, "conf-invalid", chan->language); 02958 if (!res) 02959 ast_waitstream(chan, ""); 02960 res = -1; 02961 if (allowretry) 02962 confno[0] = '\0'; 02963 } else { 02964 if (((!ast_strlen_zero(cnf->pin) && 02965 !ast_test_flag(&confflags, CONFFLAG_ADMIN)) || 02966 (!ast_strlen_zero(cnf->pinadmin) && 02967 ast_test_flag(&confflags, CONFFLAG_ADMIN)) || 02968 (!ast_strlen_zero(cnf->pin) && 02969 ast_strlen_zero(cnf->pinadmin) && 02970 ast_test_flag(&confflags, CONFFLAG_ADMIN))) && 02971 (!(cnf->users == 0 && cnf->isdynamic))) { 02972 char pin[MAX_PIN] = ""; 02973 int j; 02974 02975 /* Allow the pin to be retried up to 3 times */ 02976 for (j = 0; j < 3; j++) { 02977 if (*the_pin && (always_prompt == 0)) { 02978 ast_copy_string(pin, the_pin, sizeof(pin)); 02979 res = 0; 02980 } else { 02981 /* Prompt user for pin if pin is required */ 02982 res = ast_app_getdata(chan, "conf-getpin", pin + strlen(pin), sizeof(pin) - 1 - strlen(pin), 0); 02983 } 02984 if (res >= 0) { 02985 if ((!strcasecmp(pin, cnf->pin) && 02986 (ast_strlen_zero(cnf->pinadmin) || 02987 !ast_test_flag(&confflags, CONFFLAG_ADMIN))) || 02988 (!ast_strlen_zero(cnf->pinadmin) && 02989 !strcasecmp(pin, cnf->pinadmin))) { 02990 /* Pin correct */ 02991 allowretry = 0; 02992 if (!ast_strlen_zero(cnf->pinadmin) && !strcasecmp(pin, cnf->pinadmin)) 02993 ast_set_flag(&confflags, CONFFLAG_ADMIN); 02994 /* Run the conference */ 02995 res = conf_run(chan, cnf, confflags.flags, optargs); 02996 break; 02997 } else { 02998 /* Pin invalid */ 02999 if (!ast_streamfile(chan, "conf-invalidpin", chan->language)) { 03000 res = ast_waitstream(chan, AST_DIGIT_ANY); 03001 ast_stopstream(chan); 03002 } 03003 else { 03004 ast_log(LOG_WARNING, "Couldn't play invalid pin msg!\n"); 03005 break; 03006 } 03007 if (res < 0) 03008 break; 03009 pin[0] = res; 03010 pin[1] = '\0'; 03011 res = -1; 03012 if (allowretry) 03013 confno[0] = '\0'; 03014 } 03015 } else { 03016 /* failed when getting the pin */ 03017 res = -1; 03018 allowretry = 0; 03019 /* see if we need to get rid of the conference */ 03020 break; 03021 } 03022 03023 /* Don't retry pin with a static pin */ 03024 if (*the_pin && (always_prompt==0)) { 03025 break; 03026 } 03027 } 03028 } else { 03029 /* No pin required */ 03030 allowretry = 0; 03031 03032 /* Run the conference */ 03033 res = conf_run(chan, cnf, confflags.flags, optargs); 03034 } 03035 dispose_conf(cnf); 03036 cnf = NULL; 03037 } 03038 } 03039 } while (allowretry); 03040 03041 if (cnf) 03042 dispose_conf(cnf); 03043 03044 ast_module_user_remove(u); 03045 03046 return res; 03047 }
static void conf_flush | ( | int | fd, | |
struct ast_channel * | chan | |||
) | [static] |
Definition at line 1280 of file app_meetme.c.
References ast_frfree, ast_log(), ast_read(), ast_waitfor(), f, and LOG_WARNING.
Referenced by conf_run().
01281 { 01282 int x; 01283 01284 /* read any frames that may be waiting on the channel 01285 and throw them away 01286 */ 01287 if (chan) { 01288 struct ast_frame *f; 01289 01290 /* when no frames are available, this will wait 01291 for 1 millisecond maximum 01292 */ 01293 while (ast_waitfor(chan, 1)) { 01294 f = ast_read(chan); 01295 if (f) 01296 ast_frfree(f); 01297 else /* channel was hung up or something else happened */ 01298 break; 01299 } 01300 } 01301 01302 /* flush any data sitting in the pseudo channel */ 01303 x = DAHDI_FLUSH_ALL; 01304 if (ioctl(fd, DAHDI_FLUSH, &x)) 01305 ast_log(LOG_WARNING, "Error flushing channel\n"); 01306 01307 }
static int conf_free | ( | struct ast_conference * | conf | ) | [static] |
Definition at line 1311 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, announce_listitem::entry, MEETME_RECORD_ACTIVE, MEETME_RECORD_OFF, announce_listitem::namerecloc, ast_conference::transframe, and ast_conference::transpath.
Referenced by dispose_conf().
01312 { 01313 int x; 01314 struct announce_listitem *item; 01315 01316 AST_LIST_REMOVE(&confs, conf, list); 01317 01318 if (conf->recording == MEETME_RECORD_ACTIVE) { 01319 conf->recording = MEETME_RECORD_TERMINATE; 01320 AST_LIST_UNLOCK(&confs); 01321 while (1) { 01322 usleep(1); 01323 AST_LIST_LOCK(&confs); 01324 if (conf->recording == MEETME_RECORD_OFF) 01325 break; 01326 AST_LIST_UNLOCK(&confs); 01327 } 01328 } 01329 01330 for (x=0;x<AST_FRAME_BITS;x++) { 01331 if (conf->transframe[x]) 01332 ast_frfree(conf->transframe[x]); 01333 if (conf->transpath[x]) 01334 ast_translator_free_path(conf->transpath[x]); 01335 } 01336 if (conf->announcethread != AST_PTHREADT_NULL) { 01337 ast_mutex_lock(&conf->announcelistlock); 01338 conf->announcethread_stop = 1; 01339 ast_softhangup(conf->chan, AST_SOFTHANGUP_EXPLICIT); 01340 ast_cond_signal(&conf->announcelist_addition); 01341 ast_mutex_unlock(&conf->announcelistlock); 01342 pthread_join(conf->announcethread, NULL); 01343 01344 while ((item = AST_LIST_REMOVE_HEAD(&conf->announcelist, entry))) { 01345 ast_filedelete(item->namerecloc, NULL); 01346 ao2_ref(item, -1); 01347 } 01348 ast_mutex_destroy(&conf->announcelistlock); 01349 } 01350 if (conf->origframe) 01351 ast_frfree(conf->origframe); 01352 if (conf->lchan) 01353 ast_hangup(conf->lchan); 01354 if (conf->chan) 01355 ast_hangup(conf->chan); 01356 if (conf->fd >= 0) 01357 close(conf->fd); 01358 if (conf->usercontainer) { 01359 ao2_ref(conf->usercontainer, -1); 01360 } 01361 01362 ast_mutex_destroy(&conf->playlock); 01363 ast_mutex_destroy(&conf->listenlock); 01364 ast_mutex_destroy(&conf->recordthreadlock); 01365 ast_mutex_destroy(&conf->announcethreadlock); 01366 01367 free(conf); 01368 01369 return 0; 01370 }
static void conf_play | ( | struct ast_channel * | chan, | |
struct ast_conference * | conf, | |||
enum entrance_sound | sound | |||
) | [static] |
Definition at line 727 of file app_meetme.c.
References ast_channel::_softhangup, ast_autoservice_start(), ast_autoservice_stop(), AST_LIST_LOCK, AST_LIST_UNLOCK, careful_write(), enter, ENTER, ast_conference::fd, leave, and len().
Referenced by conf_run().
00728 { 00729 unsigned char *data; 00730 int len; 00731 int res = -1; 00732 00733 if (!chan->_softhangup) 00734 res = ast_autoservice_start(chan); 00735 00736 AST_LIST_LOCK(&confs); 00737 00738 switch(sound) { 00739 case ENTER: 00740 data = enter; 00741 len = sizeof(enter); 00742 break; 00743 case LEAVE: 00744 data = leave; 00745 len = sizeof(leave); 00746 break; 00747 default: 00748 data = NULL; 00749 len = 0; 00750 } 00751 if (data) { 00752 careful_write(conf->fd, data, len, 1); 00753 } 00754 00755 AST_LIST_UNLOCK(&confs); 00756 00757 if (!res) 00758 ast_autoservice_stop(chan); 00759 }
static void conf_queue_dtmf | ( | const struct ast_conference * | conf, | |
const struct ast_conf_user * | sender, | |||
struct ast_frame * | f | |||
) | [static] |
Definition at line 1372 of file app_meetme.c.
References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next(), ao2_ref(), ast_log(), ast_write(), ast_conf_user::chan, f, LOG_WARNING, ast_channel::name, and ast_conference::usercontainer.
Referenced by conf_run().
01374 { 01375 struct ast_conf_user *user; 01376 struct ao2_iterator user_iter; 01377 01378 user_iter = ao2_iterator_init(conf->usercontainer, 0); 01379 while ((user = ao2_iterator_next(&user_iter))) { 01380 if (user == sender) { 01381 ao2_ref(user, -1); 01382 continue; 01383 } 01384 if (ast_write(user->chan, f) < 0) 01385 ast_log(LOG_WARNING, "Error writing frame to channel %s\n", user->chan->name); 01386 ao2_ref(user, -1); 01387 } 01388 ao2_iterator_destroy(&user_iter); 01389 }
static int conf_run | ( | struct ast_channel * | chan, | |
struct ast_conference * | conf, | |||
int | confflags, | |||
char * | optargs[] | |||
) | [static] |
Definition at line 1586 of file app_meetme.c.
References ADMINFLAG_KICKME, ADMINFLAG_MUTED, ADMINFLAG_SELFMUTED, ast_conf_user::adminflags, announce_thread(), ast_conference::announcelist, ast_conference::announcelist_addition, ast_conference::announcelistlock, ast_conference::announcethread, ast_conference::announcethreadlock, ao2_alloc(), ao2_callback(), ao2_find(), ao2_lock(), ao2_ref(), ao2_unlock(), app, ast_channel_setoption(), ast_check_hangup(), ast_cond_signal(), ast_config_AST_SPOOL_DIR, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_HOLD, ast_copy_string(), ast_device_state_changed(), AST_DIGIT_ANY, ast_dsp_free(), ast_dsp_new(), ast_dsp_silence(), ast_exists_extension(), 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_frfree, AST_FRIENDLY_OFFSET, ast_goto_if_exists(), ast_hangup(), ast_indicate(), AST_LIST_HEAD_INIT_NOLOCK, AST_LIST_INSERT_TAIL, AST_LIST_NEXT, ast_log(), AST_MAX_CONTEXT, AST_MAX_EXTENSION, 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_PTHREADT_NULL, ast_read(), ast_read_noaudio(), ast_record_review(), ast_request(), ast_safe_sleep(), ast_say_number(), ast_set_read_format(), ast_set_write_format(), ast_stopstream(), ast_strdupa, ast_streamfile(), ast_strlen_zero(), ast_translate(), ast_translator_build_path(), ast_update_realtime(), ast_verbose(), ast_waitfor_nandfds(), ast_waitstream(), ast_write(), ast_conference::attr, audio_buffers, ast_channel::audiohooks, can_write(), careful_write(), ast_conf_user::chan, ast_conference::chan, conf_flush(), CONF_HASJOIN, conf_play(), conf_queue_dtmf(), CONF_SIZE, CONFFLAG_ADMIN, CONFFLAG_AGI, CONFFLAG_ANNOUNCEUSERCOUNT, CONFFLAG_EXIT_CONTEXT, CONFFLAG_INTROMSG, CONFFLAG_INTROUSER, CONFFLAG_INTROUSERNOREVIEW, CONFFLAG_MARKEDEXIT, CONFFLAG_MARKEDUSER, CONFFLAG_MOH, CONFFLAG_MONITOR, CONFFLAG_MONITORTALKER, CONFFLAG_NO_AUDIO_UNTIL_UP, CONFFLAG_NOONLYPERSON, CONFFLAG_OPTIMIZETALKER, CONFFLAG_PASS_DTMF, CONFFLAG_POUNDEXIT, CONFFLAG_QUIET, CONFFLAG_RECORDCONF, CONFFLAG_SLA_STATION, CONFFLAG_STARMENU, CONFFLAG_STARTMUTED, CONFFLAG_TALKER, CONFFLAG_WAITMARKED, ast_conference::confno, ast_channel::context, dahdi_chan_name, DAHDI_FILE_PSEUDO, 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_DEBUG, LOG_WARNING, ast_channel::macrocontext, manager_event(), ast_conference::markedusers, MEETME_DELAYDETECTENDTALK, MEETME_DELAYDETECTTALK, ast_channel::monitor, ast_channel::name, OPT_ARG_INTROMSG, OPT_ARG_WAITMARKED, option_debug, ast_conference::origframe, pbx_builtin_getvar_helper(), pbx_exec(), pbx_findapp(), ast_conference::playlock, ast_channel::rawwriteformat, ast_conference::recordingfilename, ast_conference::recordingformat, ast_conference::recordthread, ast_conference::recordthreadlock, s, set_talk_volume(), set_user_talking(), SLA_EVENT_HOLD, sla_queue_event_conf(), ast_channel::tech, ast_conference::transframe, ast_conference::transpath, tweak_listen_volume(), tweak_talk_volume(), ast_channel_tech::type, ast_channel::uniqueid, user_max_cmp(), ast_conference::usercontainer, ast_conf_user::userflags, ast_conference::users, VERBOSE_PREFIX_4, VOL_UP, and ast_conference::zapconf.
01587 { 01588 struct ast_conf_user *user = NULL; 01589 int fd; 01590 struct dahdi_confinfo ztc, ztc_empty; 01591 struct ast_frame *f; 01592 struct ast_channel *c; 01593 struct ast_frame fr; 01594 int outfd; 01595 int ms; 01596 int nfds; 01597 int res; 01598 int retryzap; 01599 int origfd; 01600 int musiconhold = 0, mohtempstopped = 0; 01601 int firstpass = 0; 01602 int lastmarked = 0; 01603 int currentmarked = 0; 01604 int ret = -1; 01605 int x; 01606 int menu_active = 0; 01607 int using_pseudo = 0; 01608 int duration=20; 01609 int hr, min, sec; 01610 int sent_event = 0; 01611 time_t now; 01612 struct ast_dsp *dsp=NULL; 01613 struct ast_app *app; 01614 const char *agifile; 01615 const char *agifiledefault = "conf-background.agi"; 01616 char meetmesecs[30] = ""; 01617 char exitcontext[AST_MAX_CONTEXT] = ""; 01618 char recordingtmp[AST_MAX_EXTENSION] = ""; 01619 char members[10] = ""; 01620 int dtmf, opt_waitmarked_timeout = 0; 01621 time_t timeout = 0; 01622 struct dahdi_bufferinfo bi; 01623 char __buf[CONF_SIZE + AST_FRIENDLY_OFFSET]; 01624 char *buf = __buf + AST_FRIENDLY_OFFSET; 01625 int setusercount = 0; 01626 int confsilence = 0, totalsilence = 0; 01627 01628 if (!(user = ao2_alloc(sizeof(*user), NULL))) { 01629 return ret; 01630 } 01631 01632 /* Possible timeout waiting for marked user */ 01633 if ((confflags & CONFFLAG_WAITMARKED) && 01634 !ast_strlen_zero(optargs[OPT_ARG_WAITMARKED]) && 01635 (sscanf(optargs[OPT_ARG_WAITMARKED], "%30d", &opt_waitmarked_timeout) == 1) && 01636 (opt_waitmarked_timeout > 0)) { 01637 timeout = time(NULL) + opt_waitmarked_timeout; 01638 } 01639 01640 if (confflags & CONFFLAG_RECORDCONF) { 01641 if (!conf->recordingfilename) { 01642 conf->recordingfilename = pbx_builtin_getvar_helper(chan, "MEETME_RECORDINGFILE"); 01643 if (!conf->recordingfilename) { 01644 snprintf(recordingtmp, sizeof(recordingtmp), "meetme-conf-rec-%s-%s", conf->confno, chan->uniqueid); 01645 conf->recordingfilename = ast_strdupa(recordingtmp); 01646 } 01647 conf->recordingformat = pbx_builtin_getvar_helper(chan, "MEETME_RECORDINGFORMAT"); 01648 if (!conf->recordingformat) { 01649 snprintf(recordingtmp, sizeof(recordingtmp), "wav"); 01650 conf->recordingformat = ast_strdupa(recordingtmp); 01651 } 01652 ast_verbose(VERBOSE_PREFIX_4 "Starting recording of MeetMe Conference %s into file %s.%s.\n", 01653 conf->confno, conf->recordingfilename, conf->recordingformat); 01654 } 01655 } 01656 01657 ast_mutex_lock(&conf->recordthreadlock); 01658 if ((conf->recordthread == AST_PTHREADT_NULL) && (confflags & CONFFLAG_RECORDCONF) && ((conf->lchan = ast_request(dahdi_chan_name, AST_FORMAT_SLINEAR, "pseudo", NULL)))) { 01659 ast_set_read_format(conf->lchan, AST_FORMAT_SLINEAR); 01660 ast_set_write_format(conf->lchan, AST_FORMAT_SLINEAR); 01661 ztc.chan = 0; 01662 ztc.confno = conf->zapconf; 01663 ztc.confmode = DAHDI_CONF_CONFANN | DAHDI_CONF_CONFANNMON; 01664 if (ioctl(conf->lchan->fds[0], DAHDI_SETCONF, &ztc)) { 01665 ast_log(LOG_WARNING, "Error starting listen channel\n"); 01666 ast_hangup(conf->lchan); 01667 conf->lchan = NULL; 01668 } else { 01669 pthread_attr_init(&conf->attr); 01670 pthread_attr_setdetachstate(&conf->attr, PTHREAD_CREATE_DETACHED); 01671 ast_pthread_create_background(&conf->recordthread, &conf->attr, recordthread, conf); 01672 pthread_attr_destroy(&conf->attr); 01673 } 01674 } 01675 ast_mutex_unlock(&conf->recordthreadlock); 01676 01677 ast_mutex_lock(&conf->announcethreadlock); 01678 if ((conf->announcethread == AST_PTHREADT_NULL) && !(confflags & CONFFLAG_QUIET) && ((confflags & CONFFLAG_INTROUSER) || (confflags & CONFFLAG_INTROUSERNOREVIEW))) { 01679 ast_mutex_init(&conf->announcelistlock); 01680 AST_LIST_HEAD_INIT_NOLOCK(&conf->announcelist); 01681 ast_pthread_create_background(&conf->announcethread, NULL, announce_thread, conf); 01682 } 01683 ast_mutex_unlock(&conf->announcethreadlock); 01684 01685 time(&user->jointime); 01686 01687 if (conf->locked && (!(confflags & CONFFLAG_ADMIN))) { 01688 /* Sorry, but this confernce is locked! */ 01689 if (!ast_streamfile(chan, "conf-locked", chan->language)) 01690 ast_waitstream(chan, ""); 01691 goto outrun; 01692 } 01693 01694 ast_mutex_lock(&conf->playlock); 01695 ao2_lock(conf->usercontainer); 01696 ao2_callback(conf->usercontainer, OBJ_NODATA, user_max_cmp, &user->user_no); 01697 user->user_no++; 01698 ao2_link(conf->usercontainer, user); 01699 ao2_unlock(conf->usercontainer); 01700 01701 user->chan = chan; 01702 user->userflags = confflags; 01703 user->adminflags = (confflags & CONFFLAG_STARTMUTED) ? ADMINFLAG_SELFMUTED : 0; 01704 user->talking = -1; 01705 01706 ast_mutex_unlock(&conf->playlock); 01707 01708 if (!(confflags & CONFFLAG_QUIET) && ((confflags & CONFFLAG_INTROUSER) || (confflags & CONFFLAG_INTROUSERNOREVIEW))) { 01709 char destdir[PATH_MAX]; 01710 01711 snprintf(destdir, sizeof(destdir), "%s/meetme", ast_config_AST_SPOOL_DIR); 01712 01713 if (mkdir(destdir, 0777) && errno != EEXIST) { 01714 ast_log(LOG_WARNING, "mkdir '%s' failed: %s\n", destdir, strerror(errno)); 01715 goto outrun; 01716 } 01717 01718 snprintf(user->namerecloc, sizeof(user->namerecloc), 01719 "%s/meetme-username-%s-%d", destdir, 01720 conf->confno, user->user_no); 01721 if (confflags & CONFFLAG_INTROUSERNOREVIEW) 01722 res = ast_play_and_record(chan, "vm-rec-name", user->namerecloc, 10, "sln", &duration, 128, 0, NULL); 01723 else 01724 res = ast_record_review(chan, "vm-rec-name", user->namerecloc, 10, "sln", &duration, NULL); 01725 if (res == -1) 01726 goto outrun; 01727 } 01728 01729 ast_mutex_lock(&conf->playlock); 01730 01731 if (confflags & CONFFLAG_MARKEDUSER) 01732 conf->markedusers++; 01733 conf->users++; 01734 /* Update table */ 01735 snprintf(members, sizeof(members), "%d", conf->users); 01736 ast_update_realtime("meetme", "confno", conf->confno, "members", members , NULL); 01737 setusercount = 1; 01738 01739 /* This device changed state now - if this is the first user */ 01740 if (conf->users == 1) 01741 ast_device_state_changed("meetme:%s", conf->confno); 01742 01743 ast_mutex_unlock(&conf->playlock); 01744 01745 if (confflags & CONFFLAG_EXIT_CONTEXT) { 01746 if ((agifile = pbx_builtin_getvar_helper(chan, "MEETME_EXIT_CONTEXT"))) 01747 ast_copy_string(exitcontext, agifile, sizeof(exitcontext)); 01748 else if (!ast_strlen_zero(chan->macrocontext)) 01749 ast_copy_string(exitcontext, chan->macrocontext, sizeof(exitcontext)); 01750 else 01751 ast_copy_string(exitcontext, chan->context, sizeof(exitcontext)); 01752 } 01753 01754 /* Playback artbitrary intro message */ 01755 if ((confflags & CONFFLAG_INTROMSG) && 01756 !ast_strlen_zero(optargs[OPT_ARG_INTROMSG])) { 01757 if (!ast_streamfile(chan, optargs[OPT_ARG_INTROMSG], chan->language)) 01758 ast_waitstream(chan, ""); 01759 } 01760 01761 if ( !(confflags & (CONFFLAG_QUIET | CONFFLAG_NOONLYPERSON)) ) { 01762 if (conf->users == 1 && !(confflags & CONFFLAG_WAITMARKED)) 01763 if (!ast_streamfile(chan, "conf-onlyperson", chan->language)) 01764 ast_waitstream(chan, ""); 01765 if ((confflags & CONFFLAG_WAITMARKED) && conf->markedusers == 0) 01766 if (!ast_streamfile(chan, "conf-waitforleader", chan->language)) 01767 ast_waitstream(chan, ""); 01768 } 01769 01770 if (!(confflags & CONFFLAG_QUIET) && (confflags & CONFFLAG_ANNOUNCEUSERCOUNT) && conf->users > 1) { 01771 int keepplaying = 1; 01772 01773 if (conf->users == 2) { 01774 if (!ast_streamfile(chan,"conf-onlyone",chan->language)) { 01775 res = ast_waitstream(chan, AST_DIGIT_ANY); 01776 ast_stopstream(chan); 01777 if (res > 0) 01778 keepplaying=0; 01779 else if (res == -1) 01780 goto outrun; 01781 } 01782 } else { 01783 if (!ast_streamfile(chan, "conf-thereare", chan->language)) { 01784 res = ast_waitstream(chan, AST_DIGIT_ANY); 01785 ast_stopstream(chan); 01786 if (res > 0) 01787 keepplaying=0; 01788 else if (res == -1) 01789 goto outrun; 01790 } 01791 if (keepplaying) { 01792 res = ast_say_number(chan, conf->users - 1, AST_DIGIT_ANY, chan->language, (char *) NULL); 01793 if (res > 0) 01794 keepplaying=0; 01795 else if (res == -1) 01796 goto outrun; 01797 } 01798 if (keepplaying && !ast_streamfile(chan, "conf-otherinparty", chan->language)) { 01799 res = ast_waitstream(chan, AST_DIGIT_ANY); 01800 ast_stopstream(chan); 01801 if (res > 0) 01802 keepplaying=0; 01803 else if (res == -1) 01804 goto outrun; 01805 } 01806 } 01807 } 01808 01809 if (!(confflags & CONFFLAG_NO_AUDIO_UNTIL_UP)) { 01810 /* We're leaving this alone until the state gets changed to up */ 01811 ast_indicate(chan, -1); 01812 } 01813 01814 if (ast_set_write_format(chan, AST_FORMAT_SLINEAR) < 0) { 01815 ast_log(LOG_WARNING, "Unable to set '%s' to write linear mode\n", chan->name); 01816 goto outrun; 01817 } 01818 01819 if (ast_set_read_format(chan, AST_FORMAT_SLINEAR) < 0) { 01820 ast_log(LOG_WARNING, "Unable to set '%s' to read linear mode\n", chan->name); 01821 goto outrun; 01822 } 01823 01824 retryzap = (strcasecmp(chan->tech->type, dahdi_chan_name) || (chan->audiohooks || chan->monitor) ? 1 : 0); 01825 user->zapchannel = !retryzap; 01826 01827 zapretry: 01828 origfd = chan->fds[0]; 01829 if (retryzap) { 01830 /* open pseudo in non-blocking mode */ 01831 fd = open(DAHDI_FILE_PSEUDO, O_RDWR | O_NONBLOCK); 01832 if (fd < 0) { 01833 ast_log(LOG_WARNING, "Unable to open DAHDI pseudo channel: %s\n", strerror(errno)); 01834 goto outrun; 01835 } 01836 using_pseudo = 1; 01837 /* Setup buffering information */ 01838 memset(&bi, 0, sizeof(bi)); 01839 bi.bufsize = CONF_SIZE/2; 01840 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE; 01841 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE; 01842 bi.numbufs = audio_buffers; 01843 if (ioctl(fd, DAHDI_SET_BUFINFO, &bi)) { 01844 ast_log(LOG_WARNING, "Unable to set buffering information: %s\n", strerror(errno)); 01845 close(fd); 01846 goto outrun; 01847 } 01848 x = 1; 01849 if (ioctl(fd, DAHDI_SETLINEAR, &x)) { 01850 ast_log(LOG_WARNING, "Unable to set linear mode: %s\n", strerror(errno)); 01851 close(fd); 01852 goto outrun; 01853 } 01854 nfds = 1; 01855 } else { 01856 /* XXX Make sure we're not running on a pseudo channel XXX */ 01857 fd = chan->fds[0]; 01858 nfds = 0; 01859 } 01860 memset(&ztc, 0, sizeof(ztc)); 01861 memset(&ztc_empty, 0, sizeof(ztc_empty)); 01862 /* Check to see if we're in a conference... */ 01863 ztc.chan = 0; 01864 if (ioctl(fd, DAHDI_GETCONF, &ztc)) { 01865 ast_log(LOG_WARNING, "Error getting conference\n"); 01866 close(fd); 01867 goto outrun; 01868 } 01869 if (ztc.confmode) { 01870 /* Whoa, already in a conference... Retry... */ 01871 if (!retryzap) { 01872 ast_log(LOG_DEBUG, "%s channel is in a conference already, retrying with pseudo\n", dahdi_chan_name); 01873 retryzap = 1; 01874 goto zapretry; 01875 } 01876 } 01877 memset(&ztc, 0, sizeof(ztc)); 01878 /* Add us to the conference */ 01879 ztc.chan = 0; 01880 ztc.confno = conf->zapconf; 01881 01882 if (!(confflags & CONFFLAG_QUIET) && ((confflags & CONFFLAG_INTROUSER) || (confflags & CONFFLAG_INTROUSERNOREVIEW)) && conf->users > 1) { 01883 struct announce_listitem *item; 01884 if (!(item = ao2_alloc(sizeof(*item), NULL))) 01885 goto outrun; 01886 ast_copy_string(item->namerecloc, user->namerecloc, sizeof(item->namerecloc)); 01887 ast_copy_string(item->language, chan->language, sizeof(item->language)); 01888 item->confchan = conf->chan; 01889 item->confusers = conf->users; 01890 item->announcetype = CONF_HASJOIN; 01891 ast_mutex_lock(&conf->announcelistlock); 01892 ao2_ref(item, +1); /* add one more so we can determine when announce_thread is done playing it */ 01893 AST_LIST_INSERT_TAIL(&conf->announcelist, item, entry); 01894 ast_cond_signal(&conf->announcelist_addition); 01895 ast_mutex_unlock(&conf->announcelistlock); 01896 01897 while (!ast_check_hangup(conf->chan) && ao2_ref(item, 0) == 2 && !ast_safe_sleep(chan, 1000)) { 01898 ; 01899 } 01900 ao2_ref(item, -1); 01901 } 01902 01903 if (confflags & CONFFLAG_WAITMARKED && !conf->markedusers) 01904 ztc.confmode = DAHDI_CONF_CONF; 01905 else if (confflags & CONFFLAG_MONITOR) 01906 ztc.confmode = DAHDI_CONF_CONFMON | DAHDI_CONF_LISTENER; 01907 else if (confflags & CONFFLAG_TALKER) 01908 ztc.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER; 01909 else 01910 ztc.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER; 01911 01912 if (ioctl(fd, DAHDI_SETCONF, &ztc)) { 01913 ast_log(LOG_WARNING, "Error setting conference\n"); 01914 close(fd); 01915 goto outrun; 01916 } 01917 if (option_debug) { 01918 ast_log(LOG_DEBUG, "Placed channel %s in %s conf %d\n", chan->name, dahdi_chan_name, conf->zapconf); 01919 } 01920 01921 if (!sent_event) { 01922 manager_event(EVENT_FLAG_CALL, "MeetmeJoin", 01923 "Channel: %s\r\n" 01924 "Uniqueid: %s\r\n" 01925 "Meetme: %s\r\n" 01926 "Usernum: %d\r\n", 01927 chan->name, chan->uniqueid, conf->confno, user->user_no); 01928 sent_event = 1; 01929 } 01930 01931 if (!firstpass && !(confflags & CONFFLAG_MONITOR) && !(confflags & CONFFLAG_ADMIN)) { 01932 firstpass = 1; 01933 if (!(confflags & CONFFLAG_QUIET)) 01934 if (!(confflags & CONFFLAG_WAITMARKED) || ((confflags & CONFFLAG_MARKEDUSER) && (conf->markedusers >= 1))) 01935 conf_play(chan, conf, ENTER); 01936 } 01937 01938 conf_flush(fd, chan); 01939 01940 if (dsp) 01941 ast_dsp_free(dsp); 01942 01943 if (!(dsp = ast_dsp_new())) { 01944 ast_log(LOG_WARNING, "Unable to allocate DSP!\n"); 01945 res = -1; 01946 } 01947 01948 if (confflags & CONFFLAG_AGI) { 01949 /* Get name of AGI file to run from $(MEETME_AGI_BACKGROUND) 01950 or use default filename of conf-background.agi */ 01951 01952 agifile = pbx_builtin_getvar_helper(chan, "MEETME_AGI_BACKGROUND"); 01953 if (!agifile) 01954 agifile = agifiledefault; 01955 01956 if (user->zapchannel) { 01957 /* Set CONFMUTE mode on Zap channel to mute DTMF tones */ 01958 x = 1; 01959 ast_channel_setoption(chan, AST_OPTION_TONE_VERIFY, &x, sizeof(char), 0); 01960 } 01961 /* Find a pointer to the agi app and execute the script */ 01962 app = pbx_findapp("agi"); 01963 if (app) { 01964 char *s = ast_strdupa(agifile); 01965 ret = pbx_exec(chan, app, s); 01966 } else { 01967 ast_log(LOG_WARNING, "Could not find application (agi)\n"); 01968 ret = -2; 01969 } 01970 if (user->zapchannel) { 01971 /* Remove CONFMUTE mode on Zap channel */ 01972 x = 0; 01973 ast_channel_setoption(chan, AST_OPTION_TONE_VERIFY, &x, sizeof(char), 0); 01974 } 01975 } else { 01976 if (user->zapchannel && (confflags & CONFFLAG_STARMENU)) { 01977 /* Set CONFMUTE mode on Zap channel to mute DTMF tones when the menu is enabled */ 01978 x = 1; 01979 ast_channel_setoption(chan, AST_OPTION_TONE_VERIFY, &x, sizeof(char), 0); 01980 } 01981 for(;;) { 01982 int menu_was_active = 0; 01983 01984 outfd = -1; 01985 ms = -1; 01986 01987 if (timeout && time(NULL) >= timeout) 01988 break; 01989 01990 /* if we have just exited from the menu, and the user had a channel-driver 01991 volume adjustment, restore it 01992 */ 01993 if (!menu_active && menu_was_active && user->listen.desired && !user->listen.actual) 01994 set_talk_volume(user, user->listen.desired); 01995 01996 menu_was_active = menu_active; 01997 01998 currentmarked = conf->markedusers; 01999 if (!(confflags & CONFFLAG_QUIET) && 02000 (confflags & CONFFLAG_MARKEDUSER) && 02001 (confflags & CONFFLAG_WAITMARKED) && 02002 lastmarked == 0) { 02003 if (currentmarked == 1 && conf->users > 1) { 02004 ast_say_number(chan, conf->users - 1, AST_DIGIT_ANY, chan->language, (char *) NULL); 02005 if (conf->users - 1 == 1) { 02006 if (!ast_streamfile(chan, "conf-userwilljoin", chan->language)) 02007 ast_waitstream(chan, ""); 02008 } else { 02009 if (!ast_streamfile(chan, "conf-userswilljoin", chan->language)) 02010 ast_waitstream(chan, ""); 02011 } 02012 } 02013 if (conf->users == 1 && ! (confflags & CONFFLAG_MARKEDUSER)) 02014 if (!ast_streamfile(chan, "conf-onlyperson", chan->language)) 02015 ast_waitstream(chan, ""); 02016 } 02017 02018 /* Update the struct with the actual confflags */ 02019 user->userflags = confflags; 02020 02021 if (confflags & CONFFLAG_WAITMARKED) { 02022 if(currentmarked == 0) { 02023 if (lastmarked != 0) { 02024 if (!(confflags & CONFFLAG_QUIET)) 02025 if (!ast_streamfile(chan, "conf-leaderhasleft", chan->language)) 02026 ast_waitstream(chan, ""); 02027 if(confflags & CONFFLAG_MARKEDEXIT) 02028 break; 02029 else { 02030 ztc.confmode = DAHDI_CONF_CONF; 02031 if (ioctl(fd, DAHDI_SETCONF, &ztc)) { 02032 ast_log(LOG_WARNING, "Error setting conference\n"); 02033 close(fd); 02034 goto outrun; 02035 } 02036 } 02037 } 02038 if (musiconhold == 0 && (confflags & CONFFLAG_MOH)) { 02039 ast_moh_start(chan, NULL, NULL); 02040 musiconhold = 1; 02041 } 02042 } else if(currentmarked >= 1 && lastmarked == 0) { 02043 /* Marked user entered, so cancel timeout */ 02044 timeout = 0; 02045 if (confflags & CONFFLAG_MONITOR) 02046 ztc.confmode = DAHDI_CONF_CONFMON | DAHDI_CONF_LISTENER; 02047 else if (confflags & CONFFLAG_TALKER) 02048 ztc.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER; 02049 else 02050 ztc.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER; 02051 if (ioctl(fd, DAHDI_SETCONF, &ztc)) { 02052 ast_log(LOG_WARNING, "Error setting conference\n"); 02053 close(fd); 02054 goto outrun; 02055 } 02056 if (musiconhold && (confflags & CONFFLAG_MOH)) { 02057 ast_moh_stop(chan); 02058 musiconhold = 0; 02059 } 02060 if ( !(confflags & CONFFLAG_QUIET) && !(confflags & CONFFLAG_MARKEDUSER)) { 02061 if (!ast_streamfile(chan, "conf-placeintoconf", chan->language)) 02062 ast_waitstream(chan, ""); 02063 conf_play(chan, conf, ENTER); 02064 } 02065 } 02066 } 02067 02068 /* trying to add moh for single person conf */ 02069 if ((confflags & CONFFLAG_MOH) && !(confflags & CONFFLAG_WAITMARKED)) { 02070 if (conf->users == 1) { 02071 if (musiconhold == 0) { 02072 ast_moh_start(chan, NULL, NULL); 02073 musiconhold = 1; 02074 } 02075 } else { 02076 if (musiconhold) { 02077 ast_moh_stop(chan); 02078 musiconhold = 0; 02079 } 02080 } 02081 } 02082 02083 /* Leave if the last marked user left */ 02084 if (currentmarked == 0 && lastmarked != 0 && (confflags & CONFFLAG_MARKEDEXIT)) { 02085 ret = -1; 02086 break; 02087 } 02088 02089 /* Check if my modes have changed */ 02090 02091 /* If I should be muted but am still talker, mute me */ 02092 if ((user->adminflags & (ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED)) && (ztc.confmode & DAHDI_CONF_TALKER)) { 02093 ztc.confmode ^= DAHDI_CONF_TALKER; 02094 if (ioctl(fd, DAHDI_SETCONF, &ztc)) { 02095 ast_log(LOG_WARNING, "Error setting conference - Un/Mute \n"); 02096 ret = -1; 02097 break; 02098 } 02099 02100 /* Indicate user is not talking anymore - change him to unmonitored state */ 02101 if ((confflags & (CONFFLAG_MONITORTALKER | CONFFLAG_OPTIMIZETALKER))) { 02102 set_user_talking(chan, conf, user, -1, confflags & CONFFLAG_MONITORTALKER); 02103 } 02104 02105 manager_event(EVENT_FLAG_CALL, "MeetmeMute", 02106 "Channel: %s\r\n" 02107 "Uniqueid: %s\r\n" 02108 "Meetme: %s\r\n" 02109 "Usernum: %i\r\n" 02110 "Status: on\r\n", 02111 chan->name, chan->uniqueid, conf->confno, user->user_no); 02112 } 02113 02114 /* If I should be un-muted but am not talker, un-mute me */ 02115 if (!(user->adminflags & (ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED)) && !(confflags & CONFFLAG_MONITOR) && !(ztc.confmode & DAHDI_CONF_TALKER)) { 02116 ztc.confmode |= DAHDI_CONF_TALKER; 02117 if (ioctl(fd, DAHDI_SETCONF, &ztc)) { 02118 ast_log(LOG_WARNING, "Error setting conference - Un/Mute \n"); 02119 ret = -1; 02120 break; 02121 } 02122 02123 manager_event(EVENT_FLAG_CALL, "MeetmeMute", 02124 "Channel: %s\r\n" 02125 "Uniqueid: %s\r\n" 02126 "Meetme: %s\r\n" 02127 "Usernum: %i\r\n" 02128 "Status: off\r\n", 02129 chan->name, chan->uniqueid, conf->confno, user->user_no); 02130 } 02131 02132 /* If I have been kicked, exit the conference */ 02133 if (user->adminflags & ADMINFLAG_KICKME) { 02134 //You have been kicked. 02135 if (!(confflags & CONFFLAG_QUIET) && 02136 !ast_streamfile(chan, "conf-kicked", chan->language)) { 02137 ast_waitstream(chan, ""); 02138 } 02139 ret = 0; 02140 break; 02141 } 02142 02143 c = ast_waitfor_nandfds(&chan, 1, &fd, nfds, NULL, &outfd, &ms); 02144 02145 if (c) { 02146 char dtmfstr[2] = ""; 02147 02148 if (c->fds[0] != origfd || (user->zapchannel && (c->audiohooks || c->monitor))) { 02149 if (using_pseudo) { 02150 /* Kill old pseudo */ 02151 close(fd); 02152 using_pseudo = 0; 02153 } 02154 ast_log(LOG_DEBUG, "Ooh, something swapped out under us, starting over\n"); 02155 retryzap = (strcasecmp(c->tech->type, dahdi_chan_name) || (c->audiohooks || c->monitor) ? 1 : 0); 02156 user->zapchannel = !retryzap; 02157 goto zapretry; 02158 } 02159 if ((confflags & CONFFLAG_MONITOR) || (user->adminflags & (ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED))) 02160 f = ast_read_noaudio(c); 02161 else 02162 f = ast_read(c); 02163 if (!f) 02164 break; 02165 if (f->frametype == AST_FRAME_DTMF) { 02166 dtmfstr[0] = f->subclass; 02167 dtmfstr[1] = '\0'; 02168 } 02169 02170 if ((f->frametype == AST_FRAME_VOICE) && (f->subclass == AST_FORMAT_SLINEAR)) { 02171 if (user->talk.actual) 02172 ast_frame_adjust_volume(f, user->talk.actual); 02173 02174 if (confflags & (CONFFLAG_MONITORTALKER | CONFFLAG_OPTIMIZETALKER)) { 02175 if (user->talking == -1) 02176 user->talking = 0; 02177 02178 res = ast_dsp_silence(dsp, f, &totalsilence); 02179 if (totalsilence < MEETME_DELAYDETECTTALK) { 02180 set_user_talking(chan, conf, user, 1, confflags & CONFFLAG_MONITORTALKER); 02181 } 02182 if (totalsilence > MEETME_DELAYDETECTENDTALK) { 02183 set_user_talking(chan, conf, user, 0, confflags & CONFFLAG_MONITORTALKER); 02184 } 02185 } 02186 if (using_pseudo) { 02187 /* Absolutely do _not_ use careful_write here... 02188 it is important that we read data from the channel 02189 as fast as it arrives, and feed it into the conference. 02190 The buffering in the pseudo channel will take care of any 02191 timing differences, unless they are so drastic as to lose 02192 audio frames (in which case carefully writing would only 02193 have delayed the audio even further). 02194 */ 02195 /* As it turns out, we do want to use careful write. We just 02196 don't want to block, but we do want to at least *try* 02197 to write out all the samples. 02198 */ 02199 if (user->talking || !(confflags & CONFFLAG_OPTIMIZETALKER)) 02200 careful_write(fd, f->data, f->datalen, 0); 02201 } 02202 } else if ((f->frametype == AST_FRAME_DTMF) && (f->subclass == '#') && (confflags & CONFFLAG_POUNDEXIT)) { 02203 if (confflags & CONFFLAG_PASS_DTMF) 02204 conf_queue_dtmf(conf, user, f); 02205 ret = 0; 02206 ast_frfree(f); 02207 break; 02208 } else if (((f->frametype == AST_FRAME_DTMF) && (f->subclass == '*') && (confflags & CONFFLAG_STARMENU)) || ((f->frametype == AST_FRAME_DTMF) && menu_active)) { 02209 if (confflags & CONFFLAG_PASS_DTMF) 02210 conf_queue_dtmf(conf, user, f); 02211 if (ioctl(fd, DAHDI_SETCONF, &ztc_empty)) { 02212 ast_log(LOG_WARNING, "Error setting conference\n"); 02213 close(fd); 02214 ast_frfree(f); 02215 goto outrun; 02216 } 02217 02218 /* if we are entering the menu, and the user has a channel-driver 02219 volume adjustment, clear it 02220 */ 02221 if (!menu_active && user->talk.desired && !user->talk.actual) 02222 set_talk_volume(user, 0); 02223 02224 if (musiconhold) { 02225 ast_moh_stop(chan); 02226 } 02227 if ((confflags & CONFFLAG_ADMIN)) { 02228 /* Admin menu */ 02229 if (!menu_active) { 02230 menu_active = 1; 02231 /* Record this sound! */ 02232 if (!ast_streamfile(chan, "conf-adminmenu", chan->language)) { 02233 dtmf = ast_waitstream(chan, AST_DIGIT_ANY); 02234 ast_stopstream(chan); 02235 } else 02236 dtmf = 0; 02237 } else 02238 dtmf = f->subclass; 02239 if (dtmf) { 02240 switch(dtmf) { 02241 case '1': /* Un/Mute */ 02242 menu_active = 0; 02243 02244 /* for admin, change both admin and use flags */ 02245 if (user->adminflags & (ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED)) 02246 user->adminflags &= ~(ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED); 02247 else 02248 user->adminflags |= (ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED); 02249 02250 if ((confflags & CONFFLAG_MONITOR) || (user->adminflags & (ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED))) { 02251 if (!ast_streamfile(chan, "conf-muted", chan->language)) 02252 ast_waitstream(chan, ""); 02253 } else { 02254 if (!ast_streamfile(chan, "conf-unmuted", chan->language)) 02255 ast_waitstream(chan, ""); 02256 } 02257 break; 02258 case '2': /* Un/Lock the Conference */ 02259 menu_active = 0; 02260 if (conf->locked) { 02261 conf->locked = 0; 02262 if (!ast_streamfile(chan, "conf-unlockednow", chan->language)) 02263 ast_waitstream(chan, ""); 02264 } else { 02265 conf->locked = 1; 02266 if (!ast_streamfile(chan, "conf-lockednow", chan->language)) 02267 ast_waitstream(chan, ""); 02268 } 02269 break; 02270 case '3': /* Eject last user */ 02271 { 02272 struct ast_conf_user *usr = NULL; 02273 int max_no = 0; 02274 ao2_callback(conf->usercontainer, OBJ_NODATA, user_max_cmp, &max_no); 02275 menu_active = 0; 02276 usr = ao2_find(conf->usercontainer, &max_no, 0); 02277 if ((usr->chan->name == chan->name)||(usr->userflags & CONFFLAG_ADMIN)) { 02278 if(!ast_streamfile(chan, "conf-errormenu", chan->language)) 02279 ast_waitstream(chan, ""); 02280 } else { 02281 usr->adminflags |= ADMINFLAG_KICKME; 02282 } 02283 ao2_ref(usr, -1); 02284 ast_stopstream(chan); 02285 break; 02286 } 02287 case '4': 02288 tweak_listen_volume(user, VOL_DOWN); 02289 break; 02290 case '6': 02291 tweak_listen_volume(user, VOL_UP); 02292 break; 02293 case '7': 02294 tweak_talk_volume(user, VOL_DOWN); 02295 break; 02296 case '8': 02297 menu_active = 0; 02298 break; 02299 case '9': 02300 tweak_talk_volume(user, VOL_UP); 02301 break; 02302 default: 02303 menu_active = 0; 02304 /* Play an error message! */ 02305 if (!ast_streamfile(chan, "conf-errormenu", chan->language)) 02306 ast_waitstream(chan, ""); 02307 break; 02308 } 02309 } 02310 } else { 02311 /* User menu */ 02312 if (!menu_active) { 02313 menu_active = 1; 02314 if (!ast_streamfile(chan, "conf-usermenu", chan->language)) { 02315 dtmf = ast_waitstream(chan, AST_DIGIT_ANY); 02316 ast_stopstream(chan); 02317 } else 02318 dtmf = 0; 02319 } else 02320 dtmf = f->subclass; 02321 if (dtmf) { 02322 switch(dtmf) { 02323 case '1': /* Un/Mute */ 02324 menu_active = 0; 02325 02326 /* user can only toggle the self-muted state */ 02327 user->adminflags ^= ADMINFLAG_SELFMUTED; 02328 02329 /* they can't override the admin mute state */ 02330 if ((confflags & CONFFLAG_MONITOR) || (user->adminflags & (ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED))) { 02331 if (!ast_streamfile(chan, "conf-muted", chan->language)) 02332 ast_waitstream(chan, ""); 02333 } else { 02334 if (!ast_streamfile(chan, "conf-unmuted", chan->language)) 02335 ast_waitstream(chan, ""); 02336 } 02337 break; 02338 case '4': 02339 tweak_listen_volume(user, VOL_DOWN); 02340 break; 02341 case '6': 02342 tweak_listen_volume(user, VOL_UP); 02343 break; 02344 case '7': 02345 tweak_talk_volume(user, VOL_DOWN); 02346 break; 02347 case '8': 02348 menu_active = 0; 02349 break; 02350 case '9': 02351 tweak_talk_volume(user, VOL_UP); 02352 break; 02353 default: 02354 menu_active = 0; 02355 if (!ast_streamfile(chan, "conf-errormenu", chan->language)) 02356 ast_waitstream(chan, ""); 02357 break; 02358 } 02359 } 02360 } 02361 if (musiconhold) { 02362 ast_moh_start(chan, NULL, NULL); 02363 } 02364 02365 if (ioctl(fd, DAHDI_SETCONF, &ztc)) { 02366 ast_log(LOG_WARNING, "Error setting conference\n"); 02367 close(fd); 02368 ast_frfree(f); 02369 goto outrun; 02370 } 02371 02372 conf_flush(fd, chan); 02373 /* Since this option could absorb dtmf for the previous, we have to check this one last */ 02374 } else if ((f->frametype == AST_FRAME_DTMF) && (confflags & CONFFLAG_EXIT_CONTEXT) && ast_exists_extension(chan, exitcontext, dtmfstr, 1, "")) { 02375 if (confflags & CONFFLAG_PASS_DTMF) 02376 conf_queue_dtmf(conf, user, f); 02377 02378 if (!ast_goto_if_exists(chan, exitcontext, dtmfstr, 1)) { 02379 ast_log(LOG_DEBUG, "Got DTMF %c, goto context %s\n", dtmfstr[0], exitcontext); 02380 ret = 0; 02381 ast_frfree(f); 02382 break; 02383 } else if (option_debug > 1) 02384 ast_log(LOG_DEBUG, "Exit by single digit did not work in meetme. Extension '%s' does not exist in context '%s'\n", dtmfstr, exitcontext); 02385 } else if ((f->frametype == AST_FRAME_DTMF_BEGIN || f->frametype == AST_FRAME_DTMF_END) 02386 && confflags & CONFFLAG_PASS_DTMF) { 02387 conf_queue_dtmf(conf, user, f); 02388 } else if ((confflags & CONFFLAG_SLA_STATION) && f->frametype == AST_FRAME_CONTROL) { 02389 switch (f->subclass) { 02390 case AST_CONTROL_HOLD: 02391 sla_queue_event_conf(SLA_EVENT_HOLD, chan, conf); 02392 break; 02393 default: 02394 break; 02395 } 02396 } else if (f->frametype == AST_FRAME_NULL) { 02397 /* Ignore NULL frames. It is perfectly normal to get these if the person is muted. */ 02398 } else if (f->frametype == AST_FRAME_CONTROL) { 02399 switch (f->subclass) { 02400 case AST_CONTROL_BUSY: 02401 case AST_CONTROL_CONGESTION: 02402 ast_frfree(f); 02403 goto outrun; 02404 break; 02405 default: 02406 if (option_debug) { 02407 ast_log(LOG_DEBUG, 02408 "Got ignored control frame on channel %s, f->frametype=%d,f->subclass=%d\n", 02409 chan->name, f->frametype, f->subclass); 02410 } 02411 } 02412 } else if (option_debug) { 02413 ast_log(LOG_DEBUG, 02414 "Got unrecognized frame on channel %s, f->frametype=%d,f->subclass=%d\n", 02415 chan->name, f->frametype, f->subclass); 02416 } 02417 ast_frfree(f); 02418 } else if (outfd > -1) { 02419 res = read(outfd, buf, CONF_SIZE); 02420 if (res > 0) { 02421 memset(&fr, 0, sizeof(fr)); 02422 fr.frametype = AST_FRAME_VOICE; 02423 fr.subclass = AST_FORMAT_SLINEAR; 02424 fr.datalen = res; 02425 fr.samples = res/2; 02426 fr.data = buf; 02427 fr.offset = AST_FRIENDLY_OFFSET; 02428 if (!user->listen.actual && 02429 ((confflags & CONFFLAG_MONITOR) || 02430 (user->adminflags & (ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED)) || 02431 (!user->talking && (confflags & CONFFLAG_OPTIMIZETALKER)) 02432 )) { 02433 int index; 02434 for (index=0;index<AST_FRAME_BITS;index++) 02435 if (chan->rawwriteformat & (1 << index)) 02436 break; 02437 if (index >= AST_FRAME_BITS) 02438 goto bailoutandtrynormal; 02439 ast_mutex_lock(&conf->listenlock); 02440 if (!conf->transframe[index]) { 02441 if (conf->origframe) { 02442 if (musiconhold && !ast_dsp_silence(dsp, conf->origframe, &confsilence) && confsilence < MEETME_DELAYDETECTTALK) { 02443 ast_moh_stop(chan); 02444 mohtempstopped = 1; 02445 } 02446 if (!conf->transpath[index]) 02447 conf->transpath[index] = ast_translator_build_path((1 << index), AST_FORMAT_SLINEAR); 02448 if (conf->transpath[index]) { 02449 conf->transframe[index] = ast_translate(conf->transpath[index], conf->origframe, 0); 02450 if (!conf->transframe[index]) 02451 conf->transframe[index] = &ast_null_frame; 02452 } 02453 } 02454 } 02455 if (conf->transframe[index]) { 02456 if ((conf->transframe[index]->frametype != AST_FRAME_NULL) && 02457 can_write(chan, confflags)) { 02458 struct ast_frame *cur; 02459 /* the translator may have returned a list of frames, so 02460 write each one onto the channel 02461 */ 02462 for (cur = conf->transframe[index]; cur; cur = AST_LIST_NEXT(cur, frame_list)) { 02463 if (ast_write(chan, cur)) { 02464 ast_log(LOG_WARNING, "Unable to write frame to channel %s\n", chan->name); 02465 break; 02466 } 02467 } 02468 if (musiconhold && mohtempstopped && confsilence > MEETME_DELAYDETECTENDTALK) { 02469 mohtempstopped = 0; 02470 ast_moh_start(chan, NULL, NULL); 02471 } 02472 } 02473 } else { 02474 ast_mutex_unlock(&conf->listenlock); 02475 goto bailoutandtrynormal; 02476 } 02477 ast_mutex_unlock(&conf->listenlock); 02478 } else { 02479 bailoutandtrynormal: 02480 if (musiconhold && !ast_dsp_silence(dsp, &fr, &confsilence) && confsilence < MEETME_DELAYDETECTTALK) { 02481 ast_moh_stop(chan); 02482 mohtempstopped = 1; 02483 } 02484 if (user->listen.actual) 02485 ast_frame_adjust_volume(&fr, user->listen.actual); 02486 if (can_write(chan, confflags) && ast_write(chan, &fr) < 0) { 02487 ast_log(LOG_WARNING, "Unable to write frame to channel %s\n", chan->name); 02488 } 02489 if (musiconhold && mohtempstopped && confsilence > MEETME_DELAYDETECTENDTALK) { 02490 mohtempstopped = 0; 02491 ast_moh_start(chan, NULL, NULL); 02492 } 02493 } 02494 } else 02495 ast_log(LOG_WARNING, "Failed to read frame: %s\n", strerror(errno)); 02496 } 02497 lastmarked = currentmarked; 02498 } 02499 } 02500 02501 if (musiconhold) { 02502 ast_moh_stop(chan); 02503 } 02504 02505 if (using_pseudo) 02506 close(fd); 02507 else { 02508 /* Take out of conference */ 02509 ztc.chan = 0; 02510 ztc.confno = 0; 02511 ztc.confmode = 0; 02512 if (ioctl(fd, DAHDI_SETCONF, &ztc)) { 02513 ast_log(LOG_WARNING, "Error setting conference\n"); 02514 } 02515 } 02516 02517 reset_volumes(user); 02518 02519 if (!(confflags & CONFFLAG_QUIET) && !(confflags & CONFFLAG_MONITOR) && !(confflags & CONFFLAG_ADMIN)) 02520 conf_play(chan, conf, LEAVE); 02521 02522 if (!(confflags & CONFFLAG_QUIET) && ((confflags & CONFFLAG_INTROUSER) || (confflags & CONFFLAG_INTROUSERNOREVIEW)) && conf->users > 1) { 02523 struct announce_listitem *item; 02524 if (!(item = ao2_alloc(sizeof(*item), NULL))) 02525 goto outrun; 02526 ast_copy_string(item->namerecloc, user->namerecloc, sizeof(item->namerecloc)); 02527 ast_copy_string(item->language, chan->language, sizeof(item->language)); 02528 item->confchan = conf->chan; 02529 item->confusers = conf->users; 02530 item->announcetype = CONF_HASLEFT; 02531 ast_mutex_lock(&conf->announcelistlock); 02532 AST_LIST_INSERT_TAIL(&conf->announcelist, item, entry); 02533 ast_cond_signal(&conf->announcelist_addition); 02534 ast_mutex_unlock(&conf->announcelistlock); 02535 } else if (!(confflags & CONFFLAG_QUIET) && ((confflags & CONFFLAG_INTROUSER) || (confflags & CONFFLAG_INTROUSERNOREVIEW)) && conf->users == 1) { 02536 /* Last person is leaving, so no reason to try and announce, but should delete the name recording */ 02537 ast_filedelete(user->namerecloc, NULL); 02538 } 02539 02540 outrun: 02541 AST_LIST_LOCK(&confs); 02542 02543 if (dsp) 02544 ast_dsp_free(dsp); 02545 02546 if (user->user_no) { 02547 /* Only cleanup users who really joined! */ 02548 now = time(NULL); 02549 hr = (now - user->jointime) / 3600; 02550 min = ((now - user->jointime) % 3600) / 60; 02551 sec = (now - user->jointime) % 60; 02552 02553 if (sent_event) { 02554 manager_event(EVENT_FLAG_CALL, "MeetmeLeave", 02555 "Channel: %s\r\n" 02556 "Uniqueid: %s\r\n" 02557 "Meetme: %s\r\n" 02558 "Usernum: %d\r\n" 02559 "CallerIDnum: %s\r\n" 02560 "CallerIDname: %s\r\n" 02561 "Duration: %ld\r\n", 02562 chan->name, chan->uniqueid, conf->confno, 02563 user->user_no, 02564 S_OR(user->chan->cid.cid_num, "<unknown>"), 02565 S_OR(user->chan->cid.cid_name, "<unknown>"), 02566 (long)(now - user->jointime)); 02567 } 02568 02569 if (setusercount) { 02570 conf->users--; 02571 /* Update table */ 02572 snprintf(members, sizeof(members), "%d", conf->users); 02573 ast_update_realtime("meetme", "confno", conf->confno, "members", members, NULL); 02574 if (confflags & CONFFLAG_MARKEDUSER) 02575 conf->markedusers--; 02576 } 02577 /* Remove ourselves from the container */ 02578 ao2_unlink(conf->usercontainer, user); 02579 02580 /* Change any states */ 02581 if (!conf->users) 02582 ast_device_state_changed("meetme:%s", conf->confno); 02583 02584 /* Return the number of seconds the user was in the conf */ 02585 snprintf(meetmesecs, sizeof(meetmesecs), "%d", (int) (time(NULL) - user->jointime)); 02586 pbx_builtin_setvar_helper(chan, "MEETMESECS", meetmesecs); 02587 } 02588 ao2_ref(user, -1); 02589 AST_LIST_UNLOCK(&confs); 02590 02591 return ret; 02592 }
static int count_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
The MeetmeCount application.
Definition at line 2747 of file app_meetme.c.
References ast_channel::_state, ast_answer(), AST_APP_ARG, AST_DECLARE_APP_ARGS, ast_log(), ast_module_user_add, ast_module_user_remove, ast_say_number(), AST_STANDARD_APP_ARGS, AST_STATE_UP, ast_strdupa, ast_strlen_zero(), ast_conference::chan, dispose_conf(), find_conf(), LOG_WARNING, pbx_builtin_setvar_helper(), and ast_conference::users.
Referenced by load_module().
02748 { 02749 struct ast_module_user *u; 02750 int res = 0; 02751 struct ast_conference *conf; 02752 int count; 02753 char *localdata; 02754 char val[80] = "0"; 02755 AST_DECLARE_APP_ARGS(args, 02756 AST_APP_ARG(confno); 02757 AST_APP_ARG(varname); 02758 ); 02759 02760 if (ast_strlen_zero(data)) { 02761 ast_log(LOG_WARNING, "MeetMeCount requires an argument (conference number)\n"); 02762 return -1; 02763 } 02764 02765 u = ast_module_user_add(chan); 02766 02767 if (!(localdata = ast_strdupa(data))) { 02768 ast_module_user_remove(u); 02769 return -1; 02770 } 02771 02772 AST_STANDARD_APP_ARGS(args, localdata); 02773 02774 conf = find_conf(chan, args.confno, 0, 0, NULL, 0, 1, NULL); 02775 02776 if (conf) { 02777 count = conf->users; 02778 dispose_conf(conf); 02779 conf = NULL; 02780 } else 02781 count = 0; 02782 02783 if (!ast_strlen_zero(args.varname)){ 02784 /* have var so load it and exit */ 02785 snprintf(val, sizeof(val), "%d",count); 02786 pbx_builtin_setvar_helper(chan, args.varname, val); 02787 } else { 02788 if (chan->_state != AST_STATE_UP) 02789 ast_answer(chan); 02790 res = ast_say_number(chan, count, "", chan->language, (char *) NULL); /* Needs gender */ 02791 } 02792 ast_module_user_remove(u); 02793 02794 return res; 02795 }
static struct sla_trunk_ref* create_trunk_ref | ( | struct sla_trunk * | trunk | ) | [static] |
Definition at line 4613 of file app_meetme.c.
References ast_calloc, and sla_trunk_ref::trunk.
Referenced by sla_add_trunk_to_station().
04614 { 04615 struct sla_trunk_ref *trunk_ref; 04616 04617 if (!(trunk_ref = ast_calloc(1, sizeof(*trunk_ref)))) 04618 return NULL; 04619 04620 trunk_ref->trunk = trunk; 04621 04622 return trunk_ref; 04623 }
static void destroy_station | ( | struct sla_station * | station | ) | [static] |
Definition at line 4781 of file app_meetme.c.
References ast_context_remove_extension(), 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, free, sla_trunk::name, sla_station::name, PRIORITY_HINT, sla_registrar, sla_trunk_ref::trunk, and sla_station::trunks.
Referenced by sla_destroy().
04782 { 04783 struct sla_trunk_ref *trunk_ref; 04784 04785 if (!ast_strlen_zero(station->autocontext)) { 04786 AST_RWLIST_RDLOCK(&sla_trunks); 04787 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) { 04788 char exten[AST_MAX_EXTENSION]; 04789 char hint[AST_MAX_APP]; 04790 snprintf(exten, sizeof(exten), "%s_%s", station->name, trunk_ref->trunk->name); 04791 snprintf(hint, sizeof(hint), "SLA:%s", exten); 04792 ast_context_remove_extension(station->autocontext, exten, 04793 1, sla_registrar); 04794 ast_context_remove_extension(station->autocontext, hint, 04795 PRIORITY_HINT, sla_registrar); 04796 } 04797 AST_RWLIST_UNLOCK(&sla_trunks); 04798 } 04799 04800 while ((trunk_ref = AST_LIST_REMOVE_HEAD(&station->trunks, entry))) 04801 free(trunk_ref); 04802 04803 ast_string_field_free_memory(station); 04804 free(station); 04805 }
static void destroy_trunk | ( | struct sla_trunk * | trunk | ) | [static] |
Definition at line 4767 of file app_meetme.c.
References ast_context_remove_extension(), AST_LIST_REMOVE_HEAD, ast_string_field_free_memory, ast_strlen_zero(), sla_trunk::autocontext, announce_listitem::entry, free, sla_registrar, and sla_trunk::stations.
Referenced by sla_destroy().
04768 { 04769 struct sla_station_ref *station_ref; 04770 04771 if (!ast_strlen_zero(trunk->autocontext)) 04772 ast_context_remove_extension(trunk->autocontext, "s", 1, sla_registrar); 04773 04774 while ((station_ref = AST_LIST_REMOVE_HEAD(&trunk->stations, entry))) 04775 free(station_ref); 04776 04777 ast_string_field_free_memory(trunk); 04778 free(trunk); 04779 }
static void* dial_trunk | ( | void * | data | ) | [static] |
Definition at line 4332 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_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, free, MAX_CONFNUM, sla, sla_trunk_ref::trunk, and dial_trunk_args::trunk_ref.
Referenced by sla_station_exec().
04333 { 04334 struct dial_trunk_args *args = data; 04335 struct ast_dial *dial; 04336 char *tech, *tech_data; 04337 enum ast_dial_result dial_res; 04338 char conf_name[MAX_CONFNUM]; 04339 struct ast_conference *conf; 04340 struct ast_flags conf_flags = { 0 }; 04341 struct sla_trunk_ref *trunk_ref = args->trunk_ref; 04342 const char *cid_name = NULL, *cid_num = NULL; 04343 04344 if (!(dial = ast_dial_create())) { 04345 ast_mutex_lock(args->cond_lock); 04346 ast_cond_signal(args->cond); 04347 ast_mutex_unlock(args->cond_lock); 04348 return NULL; 04349 } 04350 04351 tech_data = ast_strdupa(trunk_ref->trunk->device); 04352 tech = strsep(&tech_data, "/"); 04353 if (ast_dial_append(dial, tech, tech_data) == -1) { 04354 ast_mutex_lock(args->cond_lock); 04355 ast_cond_signal(args->cond); 04356 ast_mutex_unlock(args->cond_lock); 04357 ast_dial_destroy(dial); 04358 return NULL; 04359 } 04360 04361 if (!sla.attempt_callerid && !ast_strlen_zero(trunk_ref->chan->cid.cid_name)) { 04362 cid_name = ast_strdupa(trunk_ref->chan->cid.cid_name); 04363 free(trunk_ref->chan->cid.cid_name); 04364 trunk_ref->chan->cid.cid_name = NULL; 04365 } 04366 if (!sla.attempt_callerid && !ast_strlen_zero(trunk_ref->chan->cid.cid_num)) { 04367 cid_num = ast_strdupa(trunk_ref->chan->cid.cid_num); 04368 free(trunk_ref->chan->cid.cid_num); 04369 trunk_ref->chan->cid.cid_num = NULL; 04370 } 04371 04372 dial_res = ast_dial_run(dial, trunk_ref->chan, 1); 04373 04374 if (cid_name) 04375 trunk_ref->chan->cid.cid_name = ast_strdup(cid_name); 04376 if (cid_num) 04377 trunk_ref->chan->cid.cid_num = ast_strdup(cid_num); 04378 04379 if (dial_res != AST_DIAL_RESULT_TRYING) { 04380 ast_mutex_lock(args->cond_lock); 04381 ast_cond_signal(args->cond); 04382 ast_mutex_unlock(args->cond_lock); 04383 ast_dial_destroy(dial); 04384 return NULL; 04385 } 04386 04387 for (;;) { 04388 unsigned int done = 0; 04389 switch ((dial_res = ast_dial_state(dial))) { 04390 case AST_DIAL_RESULT_ANSWERED: 04391 trunk_ref->trunk->chan = ast_dial_answered(dial); 04392 case AST_DIAL_RESULT_HANGUP: 04393 case AST_DIAL_RESULT_INVALID: 04394 case AST_DIAL_RESULT_FAILED: 04395 case AST_DIAL_RESULT_TIMEOUT: 04396 case AST_DIAL_RESULT_UNANSWERED: 04397 done = 1; 04398 case AST_DIAL_RESULT_TRYING: 04399 case AST_DIAL_RESULT_RINGING: 04400 case AST_DIAL_RESULT_PROGRESS: 04401 case AST_DIAL_RESULT_PROCEEDING: 04402 break; 04403 } 04404 if (done) 04405 break; 04406 } 04407 04408 if (!trunk_ref->trunk->chan) { 04409 ast_mutex_lock(args->cond_lock); 04410 ast_cond_signal(args->cond); 04411 ast_mutex_unlock(args->cond_lock); 04412 ast_dial_join(dial); 04413 ast_dial_destroy(dial); 04414 return NULL; 04415 } 04416 04417 snprintf(conf_name, sizeof(conf_name), "SLA_%s", trunk_ref->trunk->name); 04418 ast_set_flag(&conf_flags, 04419 CONFFLAG_QUIET | CONFFLAG_MARKEDEXIT | CONFFLAG_MARKEDUSER | 04420 CONFFLAG_PASS_DTMF | CONFFLAG_SLA_TRUNK); 04421 conf = build_conf(conf_name, "", "", 1, 1, 1); 04422 04423 ast_mutex_lock(args->cond_lock); 04424 ast_cond_signal(args->cond); 04425 ast_mutex_unlock(args->cond_lock); 04426 04427 if (conf) { 04428 conf_run(trunk_ref->trunk->chan, conf, conf_flags.flags, NULL); 04429 dispose_conf(conf); 04430 conf = NULL; 04431 } 04432 04433 /* If the trunk is going away, it is definitely now IDLE. */ 04434 sla_change_trunk_state(trunk_ref->trunk, SLA_TRUNK_STATE_IDLE, ALL_TRUNK_REFS, NULL); 04435 04436 trunk_ref->trunk->chan = NULL; 04437 trunk_ref->trunk->on_hold = 0; 04438 04439 ast_dial_join(dial); 04440 ast_dial_destroy(dial); 04441 04442 return NULL; 04443 }
static int dispose_conf | ( | struct ast_conference * | conf | ) | [static] |
Definition at line 1463 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().
01464 { 01465 int res = 0; 01466 int confno_int = 0; 01467 01468 AST_LIST_LOCK(&confs); 01469 if (ast_atomic_dec_and_test(&conf->refcount)) { 01470 /* Take the conference room number out of an inuse state */ 01471 if ((sscanf(conf->confno, "%30d", &confno_int) == 1) && (confno_int >= 0 && confno_int < 1024)) 01472 conf_map[confno_int] = 0; 01473 conf_free(conf); 01474 res = 1; 01475 } 01476 AST_LIST_UNLOCK(&confs); 01477 01478 return res; 01479 }
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 2652 of file app_meetme.c.
References AST_APP_ARG, ast_app_getdata(), ast_config_destroy(), ast_config_load(), ast_copy_string(), AST_DECLARE_APP_ARGS, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), AST_NONSTANDARD_APP_ARGS, ast_variable_browse(), build_conf(), ast_conference::chan, CONFIG_FILE_NAME, ast_conference::confno, ast_conference::list, LOG_DEBUG, LOG_WARNING, MAX_SETTINGS, parse(), ast_conference::refcount, S_OR, and var.
Referenced by conf_exec(), and count_exec().
02654 { 02655 struct ast_config *cfg; 02656 struct ast_variable *var; 02657 struct ast_conference *cnf; 02658 AST_DECLARE_APP_ARGS(args, 02659 AST_APP_ARG(confno); 02660 AST_APP_ARG(pin); 02661 AST_APP_ARG(pinadmin); 02662 ); 02663 02664 /* Check first in the conference list */ 02665 AST_LIST_LOCK(&confs); 02666 AST_LIST_TRAVERSE(&confs, cnf, list) { 02667 if (!strcmp(confno, cnf->confno)) 02668 break; 02669 } 02670 if (cnf){ 02671 cnf->refcount += refcount; 02672 } 02673 AST_LIST_UNLOCK(&confs); 02674 02675 if (!cnf) { 02676 if (dynamic) { 02677 /* No need to parse meetme.conf */ 02678 ast_log(LOG_DEBUG, "Building dynamic conference '%s'\n", confno); 02679 if (dynamic_pin) { 02680 if (dynamic_pin[0] == 'q') { 02681 /* Query the user to enter a PIN */ 02682 if (ast_app_getdata(chan, "conf-getpin", dynamic_pin, pin_buf_len - 1, 0) < 0) 02683 return NULL; 02684 } 02685 cnf = build_conf(confno, dynamic_pin, "", make, dynamic, refcount); 02686 } else { 02687 cnf = build_conf(confno, "", "", make, dynamic, refcount); 02688 } 02689 } else { 02690 /* Check the config */ 02691 cfg = ast_config_load(CONFIG_FILE_NAME); 02692 if (!cfg) { 02693 ast_log(LOG_WARNING, "No %s file :(\n", CONFIG_FILE_NAME); 02694 return NULL; 02695 } 02696 02697 for (var = ast_variable_browse(cfg, "rooms"); var; var = var->next) { 02698 char parse[MAX_SETTINGS]; 02699 02700 if (strcasecmp(var->name, "conf")) 02701 continue; 02702 02703 ast_copy_string(parse, var->value, sizeof(parse)); 02704 02705 AST_NONSTANDARD_APP_ARGS(args, parse, ','); 02706 if (!strcasecmp(args.confno, confno)) { 02707 /* Bingo it's a valid conference */ 02708 cnf = build_conf(args.confno, 02709 S_OR(args.pin, ""), 02710 S_OR(args.pinadmin, ""), 02711 make, dynamic, refcount); 02712 break; 02713 } 02714 } 02715 if (!var) { 02716 ast_log(LOG_DEBUG, "%s isn't a valid conference\n", confno); 02717 } 02718 ast_config_destroy(cfg); 02719 } 02720 } else if (dynamic_pin) { 02721 /* Correct for the user selecting 'D' instead of 'd' to have 02722 someone join into a conference that has already been created 02723 with a pin. */ 02724 if (dynamic_pin[0] == 'q') 02725 dynamic_pin[0] = '\0'; 02726 } 02727 02728 if (cnf) { 02729 if (confflags && !cnf->chan && 02730 !ast_test_flag(confflags, CONFFLAG_QUIET) && 02731 ast_test_flag(confflags, CONFFLAG_INTROUSER | CONFFLAG_INTROUSERNOREVIEW)) { 02732 ast_log(LOG_WARNING, "No %s channel available for conference, user introduction disabled\n", dahdi_chan_name); 02733 ast_clear_flag(confflags, CONFFLAG_INTROUSER | CONFFLAG_INTROUSERNOREVIEW); 02734 } 02735 02736 if (confflags && !cnf->chan && 02737 ast_test_flag(confflags, CONFFLAG_RECORDCONF)) { 02738 ast_log(LOG_WARNING, "No %s channel available for conference, conference recording disabled\n", dahdi_chan_name); 02739 ast_clear_flag(confflags, CONFFLAG_RECORDCONF); 02740 } 02741 } 02742 02743 return cnf; 02744 }
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 | |||
) | [static] |
Definition at line 2594 of file app_meetme.c.
References ast_clear_flag, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_load_realtime(), ast_log(), ast_strdupa, ast_test_flag, ast_variables_destroy(), build_conf(), ast_conference::chan, CONFFLAG_RECORDCONF, ast_conference::confno, dahdi_chan_name, ast_conference::list, LOG_WARNING, ast_conference::refcount, and var.
Referenced by conf_exec().
02596 { 02597 struct ast_variable *var, *save; 02598 struct ast_conference *cnf; 02599 02600 /* Check first in the conference list */ 02601 AST_LIST_LOCK(&confs); 02602 AST_LIST_TRAVERSE(&confs, cnf, list) { 02603 if (!strcmp(confno, cnf->confno)) 02604 break; 02605 } 02606 if (cnf) { 02607 cnf->refcount += refcount; 02608 } 02609 AST_LIST_UNLOCK(&confs); 02610 02611 if (!cnf) { 02612 char *pin = NULL, *pinadmin = NULL; /* For temp use */ 02613 02614 var = ast_load_realtime("meetme", "confno", confno, NULL); 02615 02616 if (!var) 02617 return NULL; 02618 02619 save = var; 02620 while (var) { 02621 if (!strcasecmp(var->name, "pin")) { 02622 pin = ast_strdupa(var->value); 02623 } else if (!strcasecmp(var->name, "adminpin")) { 02624 pinadmin = ast_strdupa(var->value); 02625 } 02626 var = var->next; 02627 } 02628 ast_variables_destroy(save); 02629 02630 cnf = build_conf(confno, pin ? pin : "", pinadmin ? pinadmin : "", make, dynamic, refcount); 02631 } 02632 02633 if (cnf) { 02634 if (confflags && !cnf->chan && 02635 !ast_test_flag(confflags, CONFFLAG_QUIET) && 02636 ast_test_flag(confflags, CONFFLAG_INTROUSER | CONFFLAG_INTROUSERNOREVIEW)) { 02637 ast_log(LOG_WARNING, "No %s channel available for conference, user introduction disabled\n", dahdi_chan_name); 02638 ast_clear_flag(confflags, CONFFLAG_INTROUSER | CONFFLAG_INTROUSERNOREVIEW); 02639 } 02640 02641 if (confflags && !cnf->chan && 02642 ast_test_flag(confflags, CONFFLAG_RECORDCONF)) { 02643 ast_log(LOG_WARNING, "No %s channel available for conference, conference recording disabled\n", dahdi_chan_name); 02644 ast_clear_flag(confflags, CONFFLAG_RECORDCONF); 02645 } 02646 } 02647 02648 return cnf; 02649 }
static struct ast_conf_user* find_user | ( | struct ast_conference * | conf, | |
char * | callerident | |||
) | [static] |
Definition at line 3049 of file app_meetme.c.
References ao2_find(), and ast_conference::usercontainer.
03050 { 03051 struct ast_conf_user *user = NULL; 03052 int cid; 03053 03054 sscanf(callerident, "%30i", &cid); 03055 if (conf && callerident) { 03056 user = ao2_find(conf->usercontainer, &cid, 0); 03057 /* reference decremented later in admin_exec */ 03058 return user; 03059 } 03060 return NULL; 03061 }
static const char* get_announce_filename | ( | enum announcetypes | type | ) | [static] |
Definition at line 1481 of file app_meetme.c.
References CONF_HASJOIN.
Referenced by announce_thread().
01482 { 01483 switch (type) { 01484 case CONF_HASLEFT: 01485 return "conf-hasleft"; 01486 break; 01487 case CONF_HASJOIN: 01488 return "conf-hasjoin"; 01489 break; 01490 default: 01491 return ""; 01492 } 01493 }
static char* istalking | ( | int | x | ) | [static] |
Definition at line 599 of file app_meetme.c.
Referenced by meetme_cmd().
00600 { 00601 if (x > 0) 00602 return "(talking)"; 00603 else if (x < 0) 00604 return "(unmonitored)"; 00605 else 00606 return "(not talking)"; 00607 }
static int load_config | ( | int | reload | ) | [static] |
Definition at line 5136 of file app_meetme.c.
References load_config_meetme(), and sla_load_config().
05137 { 05138 int res = 0; 05139 05140 load_config_meetme(); 05141 if (!reload) 05142 res = sla_load_config(); 05143 05144 return res; 05145 }
static void load_config_meetme | ( | void | ) | [static] |
Definition at line 3414 of file app_meetme.c.
References ast_config_destroy(), ast_config_load(), ast_log(), ast_variable_retrieve(), audio_buffers, CONFIG_FILE_NAME, DEFAULT_AUDIO_BUFFERS, LOG_NOTICE, and LOG_WARNING.
Referenced by load_config().
03415 { 03416 struct ast_config *cfg; 03417 const char *val; 03418 03419 audio_buffers = DEFAULT_AUDIO_BUFFERS; 03420 03421 if (!(cfg = ast_config_load(CONFIG_FILE_NAME))) 03422 return; 03423 03424 if ((val = ast_variable_retrieve(cfg, "general", "audiobuffers"))) { 03425 if ((sscanf(val, "%30d", &audio_buffers) != 1)) { 03426 ast_log(LOG_WARNING, "audiobuffers setting must be a number, not '%s'\n", val); 03427 audio_buffers = DEFAULT_AUDIO_BUFFERS; 03428 } else if ((audio_buffers < DAHDI_DEFAULT_NUM_BUFS) || (audio_buffers > DAHDI_MAX_NUM_BUFS)) { 03429 ast_log(LOG_WARNING, "audiobuffers setting must be between %d and %d\n", 03430 DAHDI_DEFAULT_NUM_BUFS, DAHDI_MAX_NUM_BUFS); 03431 audio_buffers = DEFAULT_AUDIO_BUFFERS; 03432 } 03433 if (audio_buffers != DEFAULT_AUDIO_BUFFERS) 03434 ast_log(LOG_NOTICE, "Audio buffers per channel set to %d\n", audio_buffers); 03435 } 03436 03437 ast_config_destroy(cfg); 03438 }
static int load_module | ( | void | ) | [static] |
Definition at line 5170 of file app_meetme.c.
References action_meetmemute(), action_meetmeunmute(), admin_exec(), ARRAY_LEN, ast_cli_register_multiple(), ast_devstate_prov_add(), ast_manager_register, ast_register_application(), cli_meetme, conf_exec(), count_exec(), load_config(), meetmestate(), sla_state(), sla_station_exec(), and sla_trunk_exec().
05171 { 05172 int res = 0; 05173 05174 res |= load_config(0); 05175 05176 ast_cli_register_multiple(cli_meetme, ARRAY_LEN(cli_meetme)); 05177 res |= ast_manager_register("MeetmeMute", EVENT_FLAG_CALL, 05178 action_meetmemute, "Mute a Meetme user"); 05179 res |= ast_manager_register("MeetmeUnmute", EVENT_FLAG_CALL, 05180 action_meetmeunmute, "Unmute a Meetme user"); 05181 res |= ast_register_application(app3, admin_exec, synopsis3, descrip3); 05182 res |= ast_register_application(app2, count_exec, synopsis2, descrip2); 05183 res |= ast_register_application(app, conf_exec, synopsis, descrip); 05184 res |= ast_register_application(slastation_app, sla_station_exec, 05185 slastation_synopsis, slastation_desc); 05186 res |= ast_register_application(slatrunk_app, sla_trunk_exec, 05187 slatrunk_synopsis, slatrunk_desc); 05188 05189 res |= ast_devstate_prov_add("Meetme", meetmestate); 05190 res |= ast_devstate_prov_add("SLA", sla_state); 05191 05192 return res; 05193 }
static int meetme_cmd | ( | int | fd, | |
int | argc, | |||
char ** | argv | |||
) | [static] |
Definition at line 895 of file app_meetme.c.
References admin_exec(), ADMINFLAG_MUTED, ADMINFLAG_SELFMUTED, ast_conf_user::adminflags, ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next(), ao2_ref(), ast_cli(), ast_copy_string(), AST_LIST_EMPTY, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_conf_user::chan, ast_channel::cid, ast_callerid::cid_name, ast_callerid::cid_num, CONFFLAG_ADMIN, CONFFLAG_MONITOR, ast_conference::confno, ast_conference::isdynamic, istalking(), ast_conf_user::jointime, ast_conf_user::list, LOG_DEBUG, ast_conference::markedusers, ast_channel::name, RESULT_SHOWUSAGE, RESULT_SUCCESS, S_OR, ast_conference::start, ast_conf_user::talking, total, ast_conf_user::user_no, ast_conference::usercontainer, ast_conf_user::userflags, and ast_conference::users.
00896 { 00897 /* Process the command */ 00898 struct ast_conference *cnf; 00899 struct ast_conf_user *user; 00900 int hr, min, sec; 00901 int i = 0, total = 0; 00902 time_t now; 00903 char *header_format = "%-14s %-14s %-10s %-8s %-8s\n"; 00904 char *data_format = "%-12.12s %4.4d %4.4s %02d:%02d:%02d %-8s\n"; 00905 char cmdline[1024] = ""; 00906 00907 if (argc > 8) 00908 ast_cli(fd, "Invalid Arguments.\n"); 00909 /* Check for length so no buffer will overflow... */ 00910 for (i = 0; i < argc; i++) { 00911 if (strlen(argv[i]) > 100) 00912 ast_cli(fd, "Invalid Arguments.\n"); 00913 } 00914 if (argc == 1) { 00915 /* 'MeetMe': List all the conferences */ 00916 now = time(NULL); 00917 AST_LIST_LOCK(&confs); 00918 if (AST_LIST_EMPTY(&confs)) { 00919 ast_cli(fd, "No active MeetMe conferences.\n"); 00920 AST_LIST_UNLOCK(&confs); 00921 return RESULT_SUCCESS; 00922 } 00923 ast_cli(fd, header_format, "Conf Num", "Parties", "Marked", "Activity", "Creation"); 00924 AST_LIST_TRAVERSE(&confs, cnf, list) { 00925 if (cnf->markedusers == 0) 00926 strcpy(cmdline, "N/A "); 00927 else 00928 snprintf(cmdline, sizeof(cmdline), "%4.4d", cnf->markedusers); 00929 hr = (now - cnf->start) / 3600; 00930 min = ((now - cnf->start) % 3600) / 60; 00931 sec = (now - cnf->start) % 60; 00932 00933 ast_cli(fd, data_format, cnf->confno, cnf->users, cmdline, hr, min, sec, cnf->isdynamic ? "Dynamic" : "Static"); 00934 00935 total += cnf->users; 00936 } 00937 AST_LIST_UNLOCK(&confs); 00938 ast_cli(fd, "* Total number of MeetMe users: %d\n", total); 00939 return RESULT_SUCCESS; 00940 } 00941 if (argc < 3) 00942 return RESULT_SHOWUSAGE; 00943 ast_copy_string(cmdline, argv[2], sizeof(cmdline)); /* Argv 2: conference number */ 00944 if (strstr(argv[1], "lock")) { 00945 if (strcmp(argv[1], "lock") == 0) { 00946 /* Lock */ 00947 strncat(cmdline, "|L", sizeof(cmdline) - strlen(cmdline) - 1); 00948 } else { 00949 /* Unlock */ 00950 strncat(cmdline, "|l", sizeof(cmdline) - strlen(cmdline) - 1); 00951 } 00952 } else if (strstr(argv[1], "mute")) { 00953 if (argc < 4) 00954 return RESULT_SHOWUSAGE; 00955 if (strcmp(argv[1], "mute") == 0) { 00956 /* Mute */ 00957 if (strcmp(argv[3], "all") == 0) { 00958 strncat(cmdline, "|N", sizeof(cmdline) - strlen(cmdline) - 1); 00959 } else { 00960 strncat(cmdline, "|M|", sizeof(cmdline) - strlen(cmdline) - 1); 00961 strncat(cmdline, argv[3], sizeof(cmdline) - strlen(cmdline) - 1); 00962 } 00963 } else { 00964 /* Unmute */ 00965 if (strcmp(argv[3], "all") == 0) { 00966 strncat(cmdline, "|n", sizeof(cmdline) - strlen(cmdline) - 1); 00967 } else { 00968 strncat(cmdline, "|m|", sizeof(cmdline) - strlen(cmdline) - 1); 00969 strncat(cmdline, argv[3], sizeof(cmdline) - strlen(cmdline) - 1); 00970 } 00971 } 00972 } else if (strcmp(argv[1], "kick") == 0) { 00973 if (argc < 4) 00974 return RESULT_SHOWUSAGE; 00975 if (strcmp(argv[3], "all") == 0) { 00976 /* Kick all */ 00977 strncat(cmdline, "|K", sizeof(cmdline) - strlen(cmdline) - 1); 00978 } else { 00979 /* Kick a single user */ 00980 strncat(cmdline, "|k|", sizeof(cmdline) - strlen(cmdline) - 1); 00981 strncat(cmdline, argv[3], sizeof(cmdline) - strlen(cmdline) - 1); 00982 } 00983 } else if(strcmp(argv[1], "list") == 0) { 00984 struct ao2_iterator user_iter; 00985 int concise = ( 4 == argc && ( !strcasecmp(argv[3], "concise") ) ); 00986 /* List all the users in a conference */ 00987 if (AST_LIST_EMPTY(&confs)) { 00988 if ( !concise ) 00989 ast_cli(fd, "No active conferences.\n"); 00990 return RESULT_SUCCESS; 00991 } 00992 /* Find the right conference */ 00993 AST_LIST_LOCK(&confs); 00994 AST_LIST_TRAVERSE(&confs, cnf, list) { 00995 if (strcmp(cnf->confno, argv[2]) == 0) 00996 break; 00997 } 00998 if (!cnf) { 00999 if ( !concise ) 01000 ast_cli(fd, "No such conference: %s.\n",argv[2]); 01001 AST_LIST_UNLOCK(&confs); 01002 return RESULT_SUCCESS; 01003 } 01004 /* Show all the users */ 01005 time(&now); 01006 user_iter = ao2_iterator_init(cnf->usercontainer, 0); 01007 while((user = ao2_iterator_next(&user_iter))) { 01008 hr = (now - user->jointime) / 3600; 01009 min = ((now - user->jointime) % 3600) / 60; 01010 sec = (now - user->jointime) % 60; 01011 if (!concise) { 01012 ast_cli(fd, "User #: %-2.2d %12.12s %-20.20s Channel: %s %s %s %s %s %02d:%02d:%02d\n", 01013 user->user_no, 01014 S_OR(user->chan->cid.cid_num, "<unknown>"), 01015 S_OR(user->chan->cid.cid_name, "<no name>"), 01016 user->chan->name, 01017 user->userflags & CONFFLAG_ADMIN ? "(Admin)" : "", 01018 user->userflags & CONFFLAG_MONITOR ? "(Listen only)" : "", 01019 user->adminflags & ADMINFLAG_MUTED ? "(Admin Muted)" : user->adminflags & ADMINFLAG_SELFMUTED ? "(Muted)" : "", 01020 istalking(user->talking), hr, min, sec); 01021 } else { 01022 ast_cli(fd, "%d!%s!%s!%s!%s!%s!%s!%d!%02d:%02d:%02d\n", 01023 user->user_no, 01024 S_OR(user->chan->cid.cid_num, ""), 01025 S_OR(user->chan->cid.cid_name, ""), 01026 user->chan->name, 01027 user->userflags & CONFFLAG_ADMIN ? "1" : "", 01028 user->userflags & CONFFLAG_MONITOR ? "1" : "", 01029 user->adminflags & (ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED) ? "1" : "", 01030 user->talking, hr, min, sec); 01031 } 01032 ao2_ref(user, -1); 01033 } 01034 ao2_iterator_destroy(&user_iter); 01035 if ( !concise ) 01036 ast_cli(fd,"%d users in that conference.\n",cnf->users); 01037 AST_LIST_UNLOCK(&confs); 01038 return RESULT_SUCCESS; 01039 } else 01040 return RESULT_SHOWUSAGE; 01041 ast_log(LOG_DEBUG, "Cmdline: %s\n", cmdline); 01042 admin_exec(NULL, cmdline); 01043 01044 return 0; 01045 }
static int meetmemute | ( | struct mansession * | s, | |
const struct message * | m, | |||
int | mute | |||
) | [static] |
Definition at line 3257 of file app_meetme.c.
References ADMINFLAG_MUTED, ADMINFLAG_SELFMUTED, ast_conf_user::adminflags, ao2_find(), ao2_ref(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_strdupa, ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), ast_conf_user::chan, ast_conference::confno, ast_conf_user::list, LOG_NOTICE, ast_channel::name, s, ast_channel::uniqueid, ast_conf_user::user_no, and ast_conference::usercontainer.
Referenced by action_meetmemute(), and action_meetmeunmute().
03258 { 03259 struct ast_conference *conf; 03260 struct ast_conf_user *user; 03261 const char *confid = astman_get_header(m, "Meetme"); 03262 char *userid = ast_strdupa(astman_get_header(m, "Usernum")); 03263 int userno; 03264 03265 if (ast_strlen_zero(confid)) { 03266 astman_send_error(s, m, "Meetme conference not specified"); 03267 return 0; 03268 } 03269 03270 if (ast_strlen_zero(userid)) { 03271 astman_send_error(s, m, "Meetme user number not specified"); 03272 return 0; 03273 } 03274 03275 userno = strtoul(userid, &userid, 10); 03276 03277 if (*userid) { 03278 astman_send_error(s, m, "Invalid user number"); 03279 return 0; 03280 } 03281 03282 /* Look in the conference list */ 03283 AST_LIST_LOCK(&confs); 03284 AST_LIST_TRAVERSE(&confs, conf, list) { 03285 if (!strcmp(confid, conf->confno)) 03286 break; 03287 } 03288 03289 if (!conf) { 03290 AST_LIST_UNLOCK(&confs); 03291 astman_send_error(s, m, "Meetme conference does not exist"); 03292 return 0; 03293 } 03294 03295 user = ao2_find(conf->usercontainer, &userno, 0); 03296 03297 if (!user) { 03298 AST_LIST_UNLOCK(&confs); 03299 astman_send_error(s, m, "User number not found"); 03300 return 0; 03301 } 03302 03303 if (mute) 03304 user->adminflags |= ADMINFLAG_MUTED; /* request user muting */ 03305 else 03306 user->adminflags &= ~(ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED); /* request user unmuting */ 03307 03308 AST_LIST_UNLOCK(&confs); 03309 03310 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); 03311 03312 ao2_ref(user, -1); 03313 astman_send_ack(s, m, mute ? "User muted" : "User unmuted"); 03314 return 0; 03315 }
static int meetmestate | ( | const char * | data | ) | [static] |
Callback for devicestate providers.
Definition at line 3392 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().
03393 { 03394 struct ast_conference *conf; 03395 03396 /* Find conference */ 03397 AST_LIST_LOCK(&confs); 03398 AST_LIST_TRAVERSE(&confs, conf, list) { 03399 if (!strcmp(data, conf->confno)) 03400 break; 03401 } 03402 AST_LIST_UNLOCK(&confs); 03403 if (!conf) 03404 return AST_DEVICE_INVALID; 03405 03406 03407 /* SKREP to fill */ 03408 if (!conf->users) 03409 return AST_DEVICE_NOT_INUSE; 03410 03411 return AST_DEVICE_INUSE; 03412 }
static struct sla_ringing_trunk* queue_ringing_trunk | ( | struct sla_trunk * | trunk | ) | [static] |
Definition at line 4625 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().
04626 { 04627 struct sla_ringing_trunk *ringing_trunk; 04628 04629 if (!(ringing_trunk = ast_calloc(1, sizeof(*ringing_trunk)))) 04630 return NULL; 04631 04632 ringing_trunk->trunk = trunk; 04633 ringing_trunk->ring_begin = ast_tvnow(); 04634 04635 sla_change_trunk_state(trunk, SLA_TRUNK_STATE_RINGING, ALL_TRUNK_REFS, NULL); 04636 04637 ast_mutex_lock(&sla.lock); 04638 AST_LIST_INSERT_HEAD(&sla.ringing_trunks, ringing_trunk, entry); 04639 ast_mutex_unlock(&sla.lock); 04640 04641 sla_queue_event(SLA_EVENT_RINGING_TRUNK); 04642 04643 return ringing_trunk; 04644 }
static void * recordthread | ( | void * | args | ) | [static] |
Definition at line 3327 of file app_meetme.c.
References 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.
03328 { 03329 struct ast_conference *cnf = args; 03330 struct ast_frame *f=NULL; 03331 int flags; 03332 struct ast_filestream *s=NULL; 03333 int res=0; 03334 int x; 03335 const char *oldrecordingfilename = NULL; 03336 03337 if (!cnf || !cnf->lchan) { 03338 pthread_exit(0); 03339 } 03340 03341 ast_stopstream(cnf->lchan); 03342 flags = O_CREAT|O_TRUNC|O_WRONLY; 03343 03344 03345 cnf->recording = MEETME_RECORD_ACTIVE; 03346 while (ast_waitfor(cnf->lchan, -1) > -1) { 03347 if (cnf->recording == MEETME_RECORD_TERMINATE) { 03348 AST_LIST_LOCK(&confs); 03349 AST_LIST_UNLOCK(&confs); 03350 break; 03351 } 03352 if (!s && cnf->recordingfilename && (cnf->recordingfilename != oldrecordingfilename)) { 03353 s = ast_writefile(cnf->recordingfilename, cnf->recordingformat, NULL, flags, 0, 0644); 03354 oldrecordingfilename = cnf->recordingfilename; 03355 } 03356 03357 f = ast_read(cnf->lchan); 03358 if (!f) { 03359 res = -1; 03360 break; 03361 } 03362 if (f->frametype == AST_FRAME_VOICE) { 03363 ast_mutex_lock(&cnf->listenlock); 03364 for (x=0;x<AST_FRAME_BITS;x++) { 03365 /* Free any translations that have occured */ 03366 if (cnf->transframe[x]) { 03367 ast_frfree(cnf->transframe[x]); 03368 cnf->transframe[x] = NULL; 03369 } 03370 } 03371 if (cnf->origframe) 03372 ast_frfree(cnf->origframe); 03373 cnf->origframe = ast_frdup(f); 03374 ast_mutex_unlock(&cnf->listenlock); 03375 if (s) 03376 res = ast_writestream(s, f); 03377 if (res) { 03378 ast_frfree(f); 03379 break; 03380 } 03381 } 03382 ast_frfree(f); 03383 } 03384 cnf->recording = MEETME_RECORD_OFF; 03385 if (s) 03386 ast_closestream(s); 03387 03388 pthread_exit(0); 03389 }
static int reload | ( | void | ) | [static] |
Definition at line 5195 of file app_meetme.c.
References load_config().
05196 { 05197 return load_config(1); 05198 }
static void reset_volumes | ( | struct ast_conf_user * | user | ) | [static] |
Definition at line 719 of file app_meetme.c.
References ast_channel_setoption(), AST_OPTION_RXGAIN, AST_OPTION_TXGAIN, and ast_conf_user::chan.
Referenced by admin_exec(), and user_reset_vol_cb().
00720 { 00721 signed char zero_volume = 0; 00722 00723 ast_channel_setoption(user->chan, AST_OPTION_TXGAIN, &zero_volume, sizeof(zero_volume), 0); 00724 ast_channel_setoption(user->chan, AST_OPTION_RXGAIN, &zero_volume, sizeof(zero_volume), 0); 00725 }
static void* run_station | ( | void * | data | ) | [static] |
Definition at line 3579 of file app_meetme.c.
References sla_trunk::active_stations, admin_exec(), ALL_TRUNK_REFS, answer_trunk_chan(), ast_atomic_dec_and_test(), ast_atomic_fetchadd_int(), ast_cond_signal(), ast_dial_destroy(), ast_dial_join(), ast_mutex_lock(), ast_mutex_unlock(), ast_set_flag, build_conf(), sla_trunk_ref::chan, run_station_args::cond, run_station_args::cond_lock, conf_run(), CONFFLAG_MARKEDEXIT, CONFFLAG_PASS_DTMF, CONFFLAG_SLA_STATION, sla_station::dial, dispose_conf(), ast_flags::flags, sla_trunk::hold_stations, MAX_CONFNUM, sla_trunk::name, sla_change_trunk_state(), SLA_TRUNK_STATE_IDLE, SLA_TRUNK_STATE_ONHOLD_BYME, sla_trunk_ref::state, run_station_args::station, sla_trunk_ref::trunk, and run_station_args::trunk_ref.
Referenced by sla_handle_dial_state_event().
03580 { 03581 struct sla_station *station; 03582 struct sla_trunk_ref *trunk_ref; 03583 char conf_name[MAX_CONFNUM]; 03584 struct ast_flags conf_flags = { 0 }; 03585 struct ast_conference *conf; 03586 03587 { 03588 struct run_station_args *args = data; 03589 station = args->station; 03590 trunk_ref = args->trunk_ref; 03591 ast_mutex_lock(args->cond_lock); 03592 ast_cond_signal(args->cond); 03593 ast_mutex_unlock(args->cond_lock); 03594 /* args is no longer valid here. */ 03595 } 03596 03597 ast_atomic_fetchadd_int((int *) &trunk_ref->trunk->active_stations, 1); 03598 snprintf(conf_name, sizeof(conf_name), "SLA_%s", trunk_ref->trunk->name); 03599 ast_set_flag(&conf_flags, 03600 CONFFLAG_QUIET | CONFFLAG_MARKEDEXIT | CONFFLAG_PASS_DTMF | CONFFLAG_SLA_STATION); 03601 answer_trunk_chan(trunk_ref->chan); 03602 conf = build_conf(conf_name, "", "", 0, 0, 1); 03603 if (conf) { 03604 conf_run(trunk_ref->chan, conf, conf_flags.flags, NULL); 03605 dispose_conf(conf); 03606 conf = NULL; 03607 } 03608 trunk_ref->chan = NULL; 03609 if (ast_atomic_dec_and_test((int *) &trunk_ref->trunk->active_stations) && 03610 trunk_ref->state != SLA_TRUNK_STATE_ONHOLD_BYME) { 03611 strncat(conf_name, "|K", sizeof(conf_name) - strlen(conf_name) - 1); 03612 admin_exec(NULL, conf_name); 03613 trunk_ref->trunk->hold_stations = 0; 03614 sla_change_trunk_state(trunk_ref->trunk, SLA_TRUNK_STATE_IDLE, ALL_TRUNK_REFS, NULL); 03615 } 03616 03617 ast_dial_join(station->dial); 03618 ast_dial_destroy(station->dial); 03619 station->dial = NULL; 03620 03621 return NULL; 03622 }
static void send_talking_event | ( | struct ast_channel * | chan, | |
struct ast_conference * | conf, | |||
struct ast_conf_user * | user, | |||
int | talking | |||
) | [static] |
Definition at line 1557 of file app_meetme.c.
References ast_conference::chan, ast_conference::confno, EVENT_FLAG_CALL, manager_event(), ast_channel::name, ast_channel::uniqueid, and ast_conf_user::user_no.
Referenced by set_user_talking().
01558 { 01559 manager_event(EVENT_FLAG_CALL, "MeetmeTalking", 01560 "Channel: %s\r\n" 01561 "Uniqueid: %s\r\n" 01562 "Meetme: %s\r\n" 01563 "Usernum: %d\r\n" 01564 "Status: %s\r\n", 01565 chan->name, chan->uniqueid, conf->confno, user->user_no, talking ? "on" : "off"); 01566 }
static int set_listen_volume | ( | struct ast_conf_user * | user, | |
int | volume | |||
) | [static] |
Definition at line 648 of file app_meetme.c.
References ast_channel_setoption(), AST_OPTION_TXGAIN, and ast_conf_user::chan.
Referenced by tweak_listen_volume().
00649 { 00650 char gain_adjust; 00651 00652 /* attempt to make the adjustment in the channel driver; 00653 if successful, don't adjust in the frame reading routine 00654 */ 00655 gain_adjust = gain_map[volume + 5]; 00656 00657 return ast_channel_setoption(user->chan, AST_OPTION_TXGAIN, &gain_adjust, sizeof(gain_adjust), 0); 00658 }
static int set_talk_volume | ( | struct ast_conf_user * | user, | |
int | volume | |||
) | [static] |
Definition at line 636 of file app_meetme.c.
References ast_channel_setoption(), AST_OPTION_RXGAIN, and ast_conf_user::chan.
Referenced by conf_run(), and tweak_talk_volume().
00637 { 00638 char gain_adjust; 00639 00640 /* attempt to make the adjustment in the channel driver; 00641 if successful, don't adjust in the frame reading routine 00642 */ 00643 gain_adjust = gain_map[volume + 5]; 00644 00645 return ast_channel_setoption(user->chan, AST_OPTION_RXGAIN, &gain_adjust, sizeof(gain_adjust), 0); 00646 }
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 1568 of file app_meetme.c.
References ast_conference::chan, send_talking_event(), and ast_conf_user::talking.
Referenced by conf_run().
01569 { 01570 int last_talking = user->talking; 01571 if (last_talking == talking) 01572 return; 01573 01574 user->talking = talking; 01575 01576 if (monitor) { 01577 /* Check if talking state changed. Take care of -1 which means unmonitored */ 01578 int was_talking = (last_talking > 0); 01579 int now_talking = (talking > 0); 01580 if (was_talking != now_talking) { 01581 send_talking_event(chan, conf, user, now_talking); 01582 } 01583 } 01584 }
static void sla_add_trunk_to_station | ( | struct sla_station * | station, | |
struct ast_variable * | var | |||
) | [static] |
Definition at line 4928 of file app_meetme.c.
References ast_atomic_fetchadd_int(), AST_LIST_INSERT_TAIL, ast_log(), AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_strdupa, create_trunk_ref(), sla_station_ref::entry, free, 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, sla_station::trunks, and var.
Referenced by sla_build_station().
04929 { 04930 struct sla_trunk *trunk; 04931 struct sla_trunk_ref *trunk_ref; 04932 struct sla_station_ref *station_ref; 04933 char *trunk_name, *options, *cur; 04934 04935 options = ast_strdupa(var->value); 04936 trunk_name = strsep(&options, ","); 04937 04938 AST_RWLIST_RDLOCK(&sla_trunks); 04939 AST_RWLIST_TRAVERSE(&sla_trunks, trunk, entry) { 04940 if (!strcasecmp(trunk->name, trunk_name)) 04941 break; 04942 } 04943 04944 AST_RWLIST_UNLOCK(&sla_trunks); 04945 if (!trunk) { 04946 ast_log(LOG_ERROR, "Trunk '%s' not found!\n", var->value); 04947 return; 04948 } 04949 if (!(trunk_ref = create_trunk_ref(trunk))) 04950 return; 04951 trunk_ref->state = SLA_TRUNK_STATE_IDLE; 04952 04953 while ((cur = strsep(&options, ","))) { 04954 char *name, *value = cur; 04955 name = strsep(&value, "="); 04956 if (!strcasecmp(name, "ringtimeout")) { 04957 if (sscanf(value, "%30u", &trunk_ref->ring_timeout) != 1) { 04958 ast_log(LOG_WARNING, "Invalid ringtimeout value '%s' for " 04959 "trunk '%s' on station '%s'\n", value, trunk->name, station->name); 04960 trunk_ref->ring_timeout = 0; 04961 } 04962 } else if (!strcasecmp(name, "ringdelay")) { 04963 if (sscanf(value, "%30u", &trunk_ref->ring_delay) != 1) { 04964 ast_log(LOG_WARNING, "Invalid ringdelay value '%s' for " 04965 "trunk '%s' on station '%s'\n", value, trunk->name, station->name); 04966 trunk_ref->ring_delay = 0; 04967 } 04968 } else { 04969 ast_log(LOG_WARNING, "Invalid option '%s' for " 04970 "trunk '%s' on station '%s'\n", name, trunk->name, station->name); 04971 } 04972 } 04973 04974 if (!(station_ref = sla_create_station_ref(station))) { 04975 free(trunk_ref); 04976 return; 04977 } 04978 ast_atomic_fetchadd_int((int *) &trunk->num_stations, 1); 04979 AST_RWLIST_WRLOCK(&sla_trunks); 04980 AST_LIST_INSERT_TAIL(&trunk->stations, station_ref, entry); 04981 AST_RWLIST_UNLOCK(&sla_trunks); 04982 AST_LIST_INSERT_TAIL(&station->trunks, trunk_ref, entry); 04983 }
static int sla_build_station | ( | struct ast_config * | cfg, | |
const char * | cat | |||
) | [static] |
Definition at line 4985 of file app_meetme.c.
References ast_calloc, ast_log(), ast_string_field_init, ast_string_field_set, ast_variable_browse(), ast_variable_retrieve(), free, LOG_WARNING, sla_add_trunk_to_station(), and var.
Referenced by sla_load_config().
04986 { 04987 struct sla_station *station; 04988 struct ast_variable *var; 04989 const char *dev; 04990 04991 if (!(dev = ast_variable_retrieve(cfg, cat, "device"))) { 04992 ast_log(LOG_ERROR, "SLA Station '%s' defined with no device!\n", cat); 04993 return -1; 04994 } 04995 04996 if (!(station = ast_calloc(1, sizeof(*station)))) 04997 return -1; 04998 if (ast_string_field_init(station, 32)) { 04999 free(station); 05000 return -1; 05001 } 05002 05003 ast_string_field_set(station, name, cat); 05004 ast_string_field_set(station, device, dev); 05005 05006 for (var = ast_variable_browse(cfg, cat); var; var = var->next) { 05007 if (!strcasecmp(var->name, "trunk")) 05008 sla_add_trunk_to_station(station, var); 05009 else if (!strcasecmp(var->name, "autocontext")) 05010 ast_string_field_set(station, autocontext, var->value); 05011 else if (!strcasecmp(var->name, "ringtimeout")) { 05012 if (sscanf(var->value, "%30u", &station->ring_timeout) != 1) { 05013 ast_log(LOG_WARNING, "Invalid ringtimeout '%s' specified for station '%s'\n", 05014 var->value, station->name); 05015 station->ring_timeout = 0; 05016 } 05017 } else if (!strcasecmp(var->name, "ringdelay")) { 05018 if (sscanf(var->value, "%30u", &station->ring_delay) != 1) { 05019 ast_log(LOG_WARNING, "Invalid ringdelay '%s' specified for station '%s'\n", 05020 var->value, station->name); 05021 station->ring_delay = 0; 05022 } 05023 } else if (!strcasecmp(var->name, "hold")) { 05024 if (!strcasecmp(var->value, "private")) 05025 station->hold_access = SLA_HOLD_PRIVATE; 05026 else if (!strcasecmp(var->value, "open")) 05027 station->hold_access = SLA_HOLD_OPEN; 05028 else { 05029 ast_log(LOG_WARNING, "Invalid value '%s' for hold on station %s\n", 05030 var->value, station->name); 05031 } 05032 05033 } else if (strcasecmp(var->name, "type") && strcasecmp(var->name, "device")) { 05034 ast_log(LOG_ERROR, "Invalid option '%s' specified at line %d of %s!\n", 05035 var->name, var->lineno, SLA_CONFIG_FILE); 05036 } 05037 } 05038 05039 if (!ast_strlen_zero(station->autocontext)) { 05040 struct ast_context *context; 05041 struct sla_trunk_ref *trunk_ref; 05042 context = ast_context_find_or_create(NULL, station->autocontext, sla_registrar); 05043 if (!context) { 05044 ast_log(LOG_ERROR, "Failed to automatically find or create " 05045 "context '%s' for SLA!\n", station->autocontext); 05046 destroy_station(station); 05047 return -1; 05048 } 05049 /* The extension for when the handset goes off-hook. 05050 * exten => station1,1,SLAStation(station1) */ 05051 if (ast_add_extension2(context, 0 /* don't replace */, station->name, 1, 05052 NULL, NULL, slastation_app, ast_strdup(station->name), ast_free_ptr, sla_registrar)) { 05053 ast_log(LOG_ERROR, "Failed to automatically create extension " 05054 "for trunk '%s'!\n", station->name); 05055 destroy_station(station); 05056 return -1; 05057 } 05058 AST_RWLIST_RDLOCK(&sla_trunks); 05059 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) { 05060 char exten[AST_MAX_EXTENSION]; 05061 char hint[AST_MAX_APP]; 05062 snprintf(exten, sizeof(exten), "%s_%s", station->name, trunk_ref->trunk->name); 05063 snprintf(hint, sizeof(hint), "SLA:%s", exten); 05064 /* Extension for this line button 05065 * exten => station1_line1,1,SLAStation(station1_line1) */ 05066 if (ast_add_extension2(context, 0 /* don't replace */, exten, 1, 05067 NULL, NULL, slastation_app, ast_strdup(exten), ast_free_ptr, sla_registrar)) { 05068 ast_log(LOG_ERROR, "Failed to automatically create extension " 05069 "for trunk '%s'!\n", station->name); 05070 destroy_station(station); 05071 return -1; 05072 } 05073 /* Hint for this line button 05074 * exten => station1_line1,hint,SLA:station1_line1 */ 05075 if (ast_add_extension2(context, 0 /* don't replace */, exten, PRIORITY_HINT, 05076 NULL, NULL, hint, NULL, NULL, sla_registrar)) { 05077 ast_log(LOG_ERROR, "Failed to automatically create hint " 05078 "for trunk '%s'!\n", station->name); 05079 destroy_station(station); 05080 return -1; 05081 } 05082 } 05083 AST_RWLIST_UNLOCK(&sla_trunks); 05084 } 05085 05086 AST_RWLIST_WRLOCK(&sla_stations); 05087 AST_RWLIST_INSERT_TAIL(&sla_stations, station, entry); 05088 AST_RWLIST_UNLOCK(&sla_stations); 05089 05090 return 0; 05091 }
static int sla_build_trunk | ( | struct ast_config * | cfg, | |
const char * | cat | |||
) | [static] |
Definition at line 4850 of file app_meetme.c.
References ast_calloc, ast_log(), ast_string_field_init, ast_string_field_set, ast_variable_browse(), ast_variable_retrieve(), free, LOG_ERROR, LOG_WARNING, sla_check_device(), and var.
Referenced by sla_load_config().
04851 { 04852 struct sla_trunk *trunk; 04853 struct ast_variable *var; 04854 const char *dev; 04855 04856 if (!(dev = ast_variable_retrieve(cfg, cat, "device"))) { 04857 ast_log(LOG_ERROR, "SLA Trunk '%s' defined with no device!\n", cat); 04858 return -1; 04859 } 04860 04861 if (sla_check_device(dev)) { 04862 ast_log(LOG_ERROR, "SLA Trunk '%s' define with invalid device '%s'!\n", 04863 cat, dev); 04864 return -1; 04865 } 04866 04867 if (!(trunk = ast_calloc(1, sizeof(*trunk)))) 04868 return -1; 04869 if (ast_string_field_init(trunk, 32)) { 04870 free(trunk); 04871 return -1; 04872 } 04873 04874 ast_string_field_set(trunk, name, cat); 04875 ast_string_field_set(trunk, device, dev); 04876 04877 for (var = ast_variable_browse(cfg, cat); var; var = var->next) { 04878 if (!strcasecmp(var->name, "autocontext")) 04879 ast_string_field_set(trunk, autocontext, var->value); 04880 else if (!strcasecmp(var->name, "ringtimeout")) { 04881 if (sscanf(var->value, "%30u", &trunk->ring_timeout) != 1) { 04882 ast_log(LOG_WARNING, "Invalid ringtimeout '%s' specified for trunk '%s'\n", 04883 var->value, trunk->name); 04884 trunk->ring_timeout = 0; 04885 } 04886 } else if (!strcasecmp(var->name, "barge")) 04887 trunk->barge_disabled = ast_false(var->value); 04888 else if (!strcasecmp(var->name, "hold")) { 04889 if (!strcasecmp(var->value, "private")) 04890 trunk->hold_access = SLA_HOLD_PRIVATE; 04891 else if (!strcasecmp(var->value, "open")) 04892 trunk->hold_access = SLA_HOLD_OPEN; 04893 else { 04894 ast_log(LOG_WARNING, "Invalid value '%s' for hold on trunk %s\n", 04895 var->value, trunk->name); 04896 } 04897 } else if (strcasecmp(var->name, "type") && strcasecmp(var->name, "device")) { 04898 ast_log(LOG_ERROR, "Invalid option '%s' specified at line %d of %s!\n", 04899 var->name, var->lineno, SLA_CONFIG_FILE); 04900 } 04901 } 04902 04903 if (!ast_strlen_zero(trunk->autocontext)) { 04904 struct ast_context *context; 04905 context = ast_context_find_or_create(NULL, trunk->autocontext, sla_registrar); 04906 if (!context) { 04907 ast_log(LOG_ERROR, "Failed to automatically find or create " 04908 "context '%s' for SLA!\n", trunk->autocontext); 04909 destroy_trunk(trunk); 04910 return -1; 04911 } 04912 if (ast_add_extension2(context, 0 /* don't replace */, "s", 1, 04913 NULL, NULL, slatrunk_app, ast_strdup(trunk->name), ast_free_ptr, sla_registrar)) { 04914 ast_log(LOG_ERROR, "Failed to automatically create extension " 04915 "for trunk '%s'!\n", trunk->name); 04916 destroy_trunk(trunk); 04917 return -1; 04918 } 04919 } 04920 04921 AST_RWLIST_WRLOCK(&sla_trunks); 04922 AST_RWLIST_INSERT_TAIL(&sla_trunks, trunk, entry); 04923 AST_RWLIST_UNLOCK(&sla_trunks); 04924 04925 return 0; 04926 }
static int sla_calc_station_delays | ( | unsigned int * | timeout | ) | [static] |
Calculate the ring delay for a station.
Definition at line 4196 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().
04197 { 04198 struct sla_station *station; 04199 int res = 0; 04200 04201 AST_LIST_TRAVERSE(&sla_stations, station, entry) { 04202 struct sla_ringing_trunk *ringing_trunk; 04203 int time_left; 04204 04205 /* Ignore stations already ringing */ 04206 if (sla_check_ringing_station(station)) 04207 continue; 04208 04209 /* Ignore stations already on a call */ 04210 if (sla_check_inuse_station(station)) 04211 continue; 04212 04213 /* Ignore stations that don't have one of their trunks ringing */ 04214 if (!(ringing_trunk = sla_choose_ringing_trunk(station, NULL, 0))) 04215 continue; 04216 04217 if ((time_left = sla_check_station_delay(station, ringing_trunk)) == INT_MAX) 04218 continue; 04219 04220 /* If there is no time left, then the station needs to start ringing. 04221 * Return non-zero so that an event will be queued up an event to 04222 * make that happen. */ 04223 if (time_left <= 0) { 04224 res = 1; 04225 continue; 04226 } 04227 04228 if (time_left < *timeout) 04229 *timeout = time_left; 04230 } 04231 04232 return res; 04233 }
static int sla_calc_station_timeouts | ( | unsigned int * | timeout | ) | [static] |
Process station ring timeouts.
Definition at line 4113 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().
04114 { 04115 struct sla_ringing_trunk *ringing_trunk; 04116 struct sla_ringing_station *ringing_station; 04117 int res = 0; 04118 04119 AST_LIST_TRAVERSE_SAFE_BEGIN(&sla.ringing_stations, ringing_station, entry) { 04120 unsigned int ring_timeout = 0; 04121 int time_elapsed, time_left = INT_MAX, final_trunk_time_left = INT_MIN; 04122 struct sla_trunk_ref *trunk_ref; 04123 04124 /* If there are any ring timeouts specified for a specific trunk 04125 * on the station, then use the highest per-trunk ring timeout. 04126 * Otherwise, use the ring timeout set for the entire station. */ 04127 AST_LIST_TRAVERSE(&ringing_station->station->trunks, trunk_ref, entry) { 04128 struct sla_station_ref *station_ref; 04129 int trunk_time_elapsed, trunk_time_left; 04130 04131 AST_LIST_TRAVERSE(&sla.ringing_trunks, ringing_trunk, entry) { 04132 if (ringing_trunk->trunk == trunk_ref->trunk) 04133 break; 04134 } 04135 if (!ringing_trunk) 04136 continue; 04137 04138 /* If there is a trunk that is ringing without a timeout, then the 04139 * only timeout that could matter is a global station ring timeout. */ 04140 if (!trunk_ref->ring_timeout) 04141 break; 04142 04143 /* This trunk on this station is ringing and has a timeout. 04144 * However, make sure this trunk isn't still ringing from a 04145 * previous timeout. If so, don't consider it. */ 04146 AST_LIST_TRAVERSE(&ringing_trunk->timed_out_stations, station_ref, entry) { 04147 if (station_ref->station == ringing_station->station) 04148 break; 04149 } 04150 if (station_ref) 04151 continue; 04152 04153 trunk_time_elapsed = ast_tvdiff_ms(ast_tvnow(), ringing_trunk->ring_begin); 04154 trunk_time_left = (trunk_ref->ring_timeout * 1000) - trunk_time_elapsed; 04155 if (trunk_time_left > final_trunk_time_left) 04156 final_trunk_time_left = trunk_time_left; 04157 } 04158 04159 /* No timeout was found for ringing trunks, and no timeout for the entire station */ 04160 if (final_trunk_time_left == INT_MIN && !ringing_station->station->ring_timeout) 04161 continue; 04162 04163 /* Compute how much time is left for a global station timeout */ 04164 if (ringing_station->station->ring_timeout) { 04165 ring_timeout = ringing_station->station->ring_timeout; 04166 time_elapsed = ast_tvdiff_ms(ast_tvnow(), ringing_station->ring_begin); 04167 time_left = (ring_timeout * 1000) - time_elapsed; 04168 } 04169 04170 /* If the time left based on the per-trunk timeouts is smaller than the 04171 * global station ring timeout, use that. */ 04172 if (final_trunk_time_left > INT_MIN && final_trunk_time_left < time_left) 04173 time_left = final_trunk_time_left; 04174 04175 /* If there is no time left, the station needs to stop ringing */ 04176 if (time_left <= 0) { 04177 AST_LIST_REMOVE_CURRENT(&sla.ringing_stations, entry); 04178 sla_stop_ringing_station(ringing_station, SLA_STATION_HANGUP_TIMEOUT); 04179 res = 1; 04180 continue; 04181 } 04182 04183 /* There is still some time left for this station to ring, so save that 04184 * timeout if it is the first event scheduled to occur */ 04185 if (time_left < *timeout) 04186 *timeout = time_left; 04187 } 04188 AST_LIST_TRAVERSE_SAFE_END 04189 04190 return res; 04191 }
static int sla_calc_trunk_timeouts | ( | unsigned int * | timeout | ) | [static] |
Process trunk ring timeouts.
Definition at line 4083 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().
04084 { 04085 struct sla_ringing_trunk *ringing_trunk; 04086 int res = 0; 04087 04088 AST_LIST_TRAVERSE_SAFE_BEGIN(&sla.ringing_trunks, ringing_trunk, entry) { 04089 int time_left, time_elapsed; 04090 if (!ringing_trunk->trunk->ring_timeout) 04091 continue; 04092 time_elapsed = ast_tvdiff_ms(ast_tvnow(), ringing_trunk->ring_begin); 04093 time_left = (ringing_trunk->trunk->ring_timeout * 1000) - time_elapsed; 04094 if (time_left <= 0) { 04095 pbx_builtin_setvar_helper(ringing_trunk->trunk->chan, "SLATRUNK_STATUS", "RINGTIMEOUT"); 04096 AST_LIST_REMOVE_CURRENT(&sla.ringing_trunks, entry); 04097 sla_stop_ringing_trunk(ringing_trunk); 04098 res = 1; 04099 continue; 04100 } 04101 if (time_left < *timeout) 04102 *timeout = time_left; 04103 } 04104 AST_LIST_TRAVERSE_SAFE_END 04105 04106 return res; 04107 }
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 3548 of file app_meetme.c.
References ast_device_state_changed(), AST_LIST_TRAVERSE, sla_trunk_ref::chan, announce_listitem::entry, sla_trunk::name, sla_station::name, 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().
03550 { 03551 struct sla_station *station; 03552 struct sla_trunk_ref *trunk_ref; 03553 03554 AST_LIST_TRAVERSE(&sla_stations, station, entry) { 03555 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) { 03556 if (trunk_ref->trunk != trunk || (inactive_only ? trunk_ref->chan : 0) 03557 || trunk_ref == exclude) 03558 continue; 03559 trunk_ref->state = state; 03560 ast_device_state_changed("SLA:%s_%s", station->name, trunk->name); 03561 break; 03562 } 03563 } 03564 }
static int sla_check_device | ( | const char * | device | ) | [static] |
Definition at line 4837 of file app_meetme.c.
References ast_strdupa, and ast_strlen_zero().
Referenced by sla_build_trunk().
04838 { 04839 char *tech, *tech_data; 04840 04841 tech_data = ast_strdupa(device); 04842 tech = strsep(&tech_data, "/"); 04843 04844 if (ast_strlen_zero(tech) || ast_strlen_zero(tech_data)) 04845 return -1; 04846 04847 return 0; 04848 }
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 3831 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(), announce_listitem::entry, free, sla_failed_station::last_try, sla, and sla_failed_station::station.
Referenced by sla_ring_stations().
03832 { 03833 struct sla_failed_station *failed_station; 03834 int res = 0; 03835 03836 AST_LIST_TRAVERSE_SAFE_BEGIN(&sla.failed_stations, failed_station, entry) { 03837 if (station != failed_station->station) 03838 continue; 03839 if (ast_tvdiff_ms(ast_tvnow(), failed_station->last_try) > 1000) { 03840 AST_LIST_REMOVE_CURRENT(&sla.failed_stations, entry); 03841 free(failed_station); 03842 break; 03843 } 03844 res = 1; 03845 } 03846 AST_LIST_TRAVERSE_SAFE_END 03847 03848 return res; 03849 }
static int sla_check_inuse_station | ( | const struct sla_station * | station | ) | [static] |
Check to see if a station is in use.
Definition at line 3917 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().
03918 { 03919 struct sla_trunk_ref *trunk_ref; 03920 03921 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) { 03922 if (trunk_ref->chan) 03923 return 1; 03924 } 03925 03926 return 0; 03927 }
static int sla_check_ringing_station | ( | const struct sla_station * | station | ) | [static] |
Check to see if this station is already ringing.
Definition at line 3816 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().
03817 { 03818 struct sla_ringing_station *ringing_station; 03819 03820 AST_LIST_TRAVERSE(&sla.ringing_stations, ringing_station, entry) { 03821 if (station == ringing_station->station) 03822 return 1; 03823 } 03824 03825 return 0; 03826 }
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 | |
trunk | the trunk. If NULL, the highest priority ringing trunk will be used |
Definition at line 3947 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().
03949 { 03950 struct sla_trunk_ref *trunk_ref; 03951 unsigned int delay = UINT_MAX; 03952 int time_left, time_elapsed; 03953 03954 if (!ringing_trunk) 03955 ringing_trunk = sla_choose_ringing_trunk(station, &trunk_ref, 0); 03956 else 03957 trunk_ref = sla_find_trunk_ref(station, ringing_trunk->trunk); 03958 03959 if (!ringing_trunk || !trunk_ref) 03960 return delay; 03961 03962 /* If this station has a ring delay specific to the highest priority 03963 * ringing trunk, use that. Otherwise, use the ring delay specified 03964 * globally for the station. */ 03965 delay = trunk_ref->ring_delay; 03966 if (!delay) 03967 delay = station->ring_delay; 03968 if (!delay) 03969 return INT_MAX; 03970 03971 time_elapsed = ast_tvdiff_ms(ast_tvnow(), ringing_trunk->ring_begin); 03972 time_left = (delay * 1000) - time_elapsed; 03973 03974 return time_left; 03975 }
static int sla_check_station_hold_access | ( | const struct sla_trunk * | trunk, | |
const struct sla_station * | station | |||
) | [static] |
Definition at line 3470 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().
03472 { 03473 struct sla_station_ref *station_ref; 03474 struct sla_trunk_ref *trunk_ref; 03475 03476 /* For each station that has this call on hold, check for private hold. */ 03477 AST_LIST_TRAVERSE(&trunk->stations, station_ref, entry) { 03478 AST_LIST_TRAVERSE(&station_ref->station->trunks, trunk_ref, entry) { 03479 if (trunk_ref->trunk != trunk || station_ref->station == station) 03480 continue; 03481 if (trunk_ref->state == SLA_TRUNK_STATE_ONHOLD_BYME && 03482 station_ref->station->hold_access == SLA_HOLD_PRIVATE) 03483 return 1; 03484 return 0; 03485 } 03486 } 03487 03488 return 0; 03489 }
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 3682 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().
03684 { 03685 struct sla_station_ref *timed_out_station; 03686 03687 AST_LIST_TRAVERSE(&ringing_trunk->timed_out_stations, timed_out_station, entry) { 03688 if (station == timed_out_station->station) 03689 return 1; 03690 } 03691 03692 return 0; 03693 }
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 4447 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().
04448 { 04449 struct sla_trunk_ref *trunk_ref = NULL; 04450 04451 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) { 04452 if (trunk_ref->state == SLA_TRUNK_STATE_IDLE) 04453 break; 04454 } 04455 04456 return trunk_ref; 04457 }
static struct sla_ringing_trunk* sla_choose_ringing_trunk | ( | struct sla_station * | station, | |
struct sla_trunk_ref ** | trunk_ref, | |||
int | remove | |||
) | [static] |
Choose the highest priority ringing trunk for a station.
station | the station | |
remove | remove the ringing trunk once selected | |
trunk_ref | a place to store the pointer to this stations reference to the selected trunk |
Definition at line 3703 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().
03705 { 03706 struct sla_trunk_ref *s_trunk_ref; 03707 struct sla_ringing_trunk *ringing_trunk = NULL; 03708 03709 AST_LIST_TRAVERSE(&station->trunks, s_trunk_ref, entry) { 03710 AST_LIST_TRAVERSE_SAFE_BEGIN(&sla.ringing_trunks, ringing_trunk, entry) { 03711 /* Make sure this is the trunk we're looking for */ 03712 if (s_trunk_ref->trunk != ringing_trunk->trunk) 03713 continue; 03714 03715 /* This trunk on the station is ringing. But, make sure this station 03716 * didn't already time out while this trunk was ringing. */ 03717 if (sla_check_timed_out_station(ringing_trunk, station)) 03718 continue; 03719 03720 if (remove) 03721 AST_LIST_REMOVE_CURRENT(&sla.ringing_trunks, entry); 03722 03723 if (trunk_ref) 03724 *trunk_ref = s_trunk_ref; 03725 03726 break; 03727 } 03728 AST_LIST_TRAVERSE_SAFE_END 03729 03730 if (ringing_trunk) 03731 break; 03732 } 03733 03734 return ringing_trunk; 03735 }
static struct sla_ringing_station* sla_create_ringing_station | ( | struct sla_station * | station | ) | [static] |
Definition at line 3535 of file app_meetme.c.
References ast_calloc, ast_tvnow(), and sla_ringing_station::station.
Referenced by sla_ring_station().
03536 { 03537 struct sla_ringing_station *ringing_station; 03538 03539 if (!(ringing_station = ast_calloc(1, sizeof(*ringing_station)))) 03540 return NULL; 03541 03542 ringing_station->station = station; 03543 ringing_station->ring_begin = ast_tvnow(); 03544 03545 return ringing_station; 03546 }
static struct sla_station_ref* sla_create_station_ref | ( | struct sla_station * | station | ) | [static] |
Definition at line 3523 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().
03524 { 03525 struct sla_station_ref *station_ref; 03526 03527 if (!(station_ref = ast_calloc(1, sizeof(*station_ref)))) 03528 return NULL; 03529 03530 station_ref->station = station; 03531 03532 return station_ref; 03533 }
static void sla_destroy | ( | void | ) | [static] |
Definition at line 4807 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().
04808 { 04809 struct sla_trunk *trunk; 04810 struct sla_station *station; 04811 04812 AST_RWLIST_WRLOCK(&sla_trunks); 04813 while ((trunk = AST_RWLIST_REMOVE_HEAD(&sla_trunks, entry))) 04814 destroy_trunk(trunk); 04815 AST_RWLIST_UNLOCK(&sla_trunks); 04816 04817 AST_RWLIST_WRLOCK(&sla_stations); 04818 while ((station = AST_RWLIST_REMOVE_HEAD(&sla_stations, entry))) 04819 destroy_station(station); 04820 AST_RWLIST_UNLOCK(&sla_stations); 04821 04822 if (sla.thread != AST_PTHREADT_NULL) { 04823 ast_mutex_lock(&sla.lock); 04824 sla.stop = 1; 04825 ast_cond_signal(&sla.cond); 04826 ast_mutex_unlock(&sla.lock); 04827 pthread_join(sla.thread, NULL); 04828 } 04829 04830 /* Drop any created contexts from the dialplan */ 04831 ast_context_destroy(NULL, sla_registrar); 04832 04833 ast_mutex_destroy(&sla.lock); 04834 ast_cond_destroy(&sla.cond); 04835 }
static void sla_dial_state_callback | ( | struct ast_dial * | dial | ) | [static] |
Definition at line 3674 of file app_meetme.c.
References SLA_EVENT_DIAL_STATE, and sla_queue_event().
Referenced by sla_ring_station().
03675 { 03676 sla_queue_event(SLA_EVENT_DIAL_STATE); 03677 }
static struct sla_station* sla_find_station | ( | const char * | name | ) | [static] |
Find an SLA station by name.
Definition at line 3458 of file app_meetme.c.
References AST_RWLIST_TRAVERSE, announce_listitem::entry, and sla_station::name.
Referenced by sla_station_exec().
03459 { 03460 struct sla_station *station = NULL; 03461 03462 AST_RWLIST_TRAVERSE(&sla_stations, station, entry) { 03463 if (!strcasecmp(station->name, name)) 03464 break; 03465 } 03466 03467 return station; 03468 }
static struct sla_trunk* sla_find_trunk | ( | const char * | name | ) | [static] |
Find an SLA trunk by name.
Definition at line 3443 of file app_meetme.c.
References AST_RWLIST_TRAVERSE, announce_listitem::entry, and sla_trunk::name.
Referenced by sla_trunk_exec().
03444 { 03445 struct sla_trunk *trunk = NULL; 03446 03447 AST_RWLIST_TRAVERSE(&sla_trunks, trunk, entry) { 03448 if (!strcasecmp(trunk->name, name)) 03449 break; 03450 } 03451 03452 return trunk; 03453 }
static struct sla_trunk_ref* sla_find_trunk_ref | ( | const struct sla_station * | station, | |
const struct sla_trunk * | trunk | |||
) | [static] |
Definition at line 3929 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().
03931 { 03932 struct sla_trunk_ref *trunk_ref = NULL; 03933 03934 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) { 03935 if (trunk_ref->trunk == trunk) 03936 break; 03937 } 03938 03939 return trunk_ref; 03940 }
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 3498 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().
03500 { 03501 struct sla_trunk_ref *trunk_ref = NULL; 03502 03503 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) { 03504 if (strcasecmp(trunk_ref->trunk->name, name)) 03505 continue; 03506 03507 if ( (trunk_ref->trunk->barge_disabled 03508 && trunk_ref->state == SLA_TRUNK_STATE_UP) || 03509 (trunk_ref->trunk->hold_stations 03510 && trunk_ref->trunk->hold_access == SLA_HOLD_PRIVATE 03511 && trunk_ref->state != SLA_TRUNK_STATE_ONHOLD_BYME) || 03512 sla_check_station_hold_access(trunk_ref->trunk, station) ) 03513 { 03514 trunk_ref = NULL; 03515 } 03516 03517 break; 03518 } 03519 03520 return trunk_ref; 03521 }
static void sla_handle_dial_state_event | ( | void | ) | [static] |
Definition at line 3737 of file app_meetme.c.
References ALL_TRUNK_REFS, answer_trunk_chan(), ast_cond_destroy(), ast_cond_init(), ast_cond_wait(), 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_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_background, sla_trunk::chan, sla_trunk_ref::chan, run_station_args::cond, cond, run_station_args::cond_lock, sla_station::dial, announce_listitem::entry, free, LOG_DEBUG, 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().
03738 { 03739 struct sla_ringing_station *ringing_station; 03740 03741 AST_LIST_TRAVERSE_SAFE_BEGIN(&sla.ringing_stations, ringing_station, entry) { 03742 struct sla_trunk_ref *s_trunk_ref = NULL; 03743 struct sla_ringing_trunk *ringing_trunk = NULL; 03744 struct run_station_args args; 03745 enum ast_dial_result dial_res; 03746 pthread_attr_t attr; 03747 pthread_t dont_care; 03748 ast_mutex_t cond_lock; 03749 ast_cond_t cond; 03750 03751 switch ((dial_res = ast_dial_state(ringing_station->station->dial))) { 03752 case AST_DIAL_RESULT_HANGUP: 03753 case AST_DIAL_RESULT_INVALID: 03754 case AST_DIAL_RESULT_FAILED: 03755 case AST_DIAL_RESULT_TIMEOUT: 03756 case AST_DIAL_RESULT_UNANSWERED: 03757 AST_LIST_REMOVE_CURRENT(&sla.ringing_stations, entry); 03758 sla_stop_ringing_station(ringing_station, SLA_STATION_HANGUP_NORMAL); 03759 break; 03760 case AST_DIAL_RESULT_ANSWERED: 03761 AST_LIST_REMOVE_CURRENT(&sla.ringing_stations, entry); 03762 /* Find the appropriate trunk to answer. */ 03763 ast_mutex_lock(&sla.lock); 03764 ringing_trunk = sla_choose_ringing_trunk(ringing_station->station, &s_trunk_ref, 1); 03765 ast_mutex_unlock(&sla.lock); 03766 if (!ringing_trunk) { 03767 ast_log(LOG_DEBUG, "Found no ringing trunk for station '%s' to answer!\n", 03768 ringing_station->station->name); 03769 break; 03770 } 03771 /* Track the channel that answered this trunk */ 03772 s_trunk_ref->chan = ast_dial_answered(ringing_station->station->dial); 03773 /* Actually answer the trunk */ 03774 answer_trunk_chan(ringing_trunk->trunk->chan); 03775 sla_change_trunk_state(ringing_trunk->trunk, SLA_TRUNK_STATE_UP, ALL_TRUNK_REFS, NULL); 03776 /* Now, start a thread that will connect this station to the trunk. The rest of 03777 * the code here sets up the thread and ensures that it is able to save the arguments 03778 * before they are no longer valid since they are allocated on the stack. */ 03779 args.trunk_ref = s_trunk_ref; 03780 args.station = ringing_station->station; 03781 args.cond = &cond; 03782 args.cond_lock = &cond_lock; 03783 free(ringing_trunk); 03784 free(ringing_station); 03785 ast_mutex_init(&cond_lock); 03786 ast_cond_init(&cond, NULL); 03787 pthread_attr_init(&attr); 03788 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 03789 ast_mutex_lock(&cond_lock); 03790 ast_pthread_create_background(&dont_care, &attr, run_station, &args); 03791 ast_cond_wait(&cond, &cond_lock); 03792 ast_mutex_unlock(&cond_lock); 03793 ast_mutex_destroy(&cond_lock); 03794 ast_cond_destroy(&cond); 03795 pthread_attr_destroy(&attr); 03796 break; 03797 case AST_DIAL_RESULT_TRYING: 03798 case AST_DIAL_RESULT_RINGING: 03799 case AST_DIAL_RESULT_PROGRESS: 03800 case AST_DIAL_RESULT_PROCEEDING: 03801 break; 03802 } 03803 if (dial_res == AST_DIAL_RESULT_ANSWERED) { 03804 /* Queue up reprocessing ringing trunks, and then ringing stations again */ 03805 sla_queue_event(SLA_EVENT_RINGING_TRUNK); 03806 sla_queue_event(SLA_EVENT_DIAL_STATE); 03807 break; 03808 } 03809 } 03810 AST_LIST_TRAVERSE_SAFE_END 03811 }
static void sla_handle_hold_event | ( | struct sla_event * | event | ) | [static] |
Definition at line 4059 of file app_meetme.c.
References sla_trunk::active_stations, ast_atomic_fetchadd_int(), AST_CONTROL_HOLD, ast_device_state_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().
04060 { 04061 ast_atomic_fetchadd_int((int *) &event->trunk_ref->trunk->hold_stations, 1); 04062 event->trunk_ref->state = SLA_TRUNK_STATE_ONHOLD_BYME; 04063 ast_device_state_changed("SLA:%s_%s", 04064 event->station->name, event->trunk_ref->trunk->name); 04065 sla_change_trunk_state(event->trunk_ref->trunk, SLA_TRUNK_STATE_ONHOLD, 04066 INACTIVE_TRUNK_REFS, event->trunk_ref); 04067 04068 if (event->trunk_ref->trunk->active_stations == 1) { 04069 /* The station putting it on hold is the only one on the call, so start 04070 * Music on hold to the trunk. */ 04071 event->trunk_ref->trunk->on_hold = 1; 04072 ast_indicate(event->trunk_ref->trunk->chan, AST_CONTROL_HOLD); 04073 } 04074 04075 ast_softhangup(event->trunk_ref->chan, AST_SOFTHANGUP_DEV); 04076 event->trunk_ref->chan = NULL; 04077 }
static void sla_handle_ringing_trunk_event | ( | void | ) | [static] |
Definition at line 4049 of file app_meetme.c.
References ast_mutex_lock(), ast_mutex_unlock(), sla, sla_hangup_stations(), and sla_ring_stations().
Referenced by sla_thread().
04050 { 04051 ast_mutex_lock(&sla.lock); 04052 sla_ring_stations(); 04053 ast_mutex_unlock(&sla.lock); 04054 04055 /* Find stations that shouldn't be ringing anymore. */ 04056 sla_hangup_stations(); 04057 }
static void sla_hangup_stations | ( | void | ) | [static] |
Definition at line 4021 of file app_meetme.c.
References ast_dial_destroy(), ast_dial_join(), 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, free, sla, sla_ringing_station::station, sla_ringing_trunk::trunk, sla_trunk_ref::trunk, and sla_station::trunks.
Referenced by sla_handle_ringing_trunk_event().
04022 { 04023 struct sla_trunk_ref *trunk_ref; 04024 struct sla_ringing_station *ringing_station; 04025 04026 AST_LIST_TRAVERSE_SAFE_BEGIN(&sla.ringing_stations, ringing_station, entry) { 04027 AST_LIST_TRAVERSE(&ringing_station->station->trunks, trunk_ref, entry) { 04028 struct sla_ringing_trunk *ringing_trunk; 04029 ast_mutex_lock(&sla.lock); 04030 AST_LIST_TRAVERSE(&sla.ringing_trunks, ringing_trunk, entry) { 04031 if (trunk_ref->trunk == ringing_trunk->trunk) 04032 break; 04033 } 04034 ast_mutex_unlock(&sla.lock); 04035 if (ringing_trunk) 04036 break; 04037 } 04038 if (!trunk_ref) { 04039 AST_LIST_REMOVE_CURRENT(&sla.ringing_stations, entry); 04040 ast_dial_join(ringing_station->station->dial); 04041 ast_dial_destroy(ringing_station->station->dial); 04042 ringing_station->station->dial = NULL; 04043 free(ringing_station); 04044 } 04045 } 04046 AST_LIST_TRAVERSE_SAFE_END 04047 }
static const char* sla_hold_str | ( | unsigned int | hold_access | ) | [static] |
Definition at line 1120 of file app_meetme.c.
References SLA_HOLD_OPEN, and SLA_HOLD_PRIVATE.
Referenced by sla_show_stations(), and sla_show_trunks().
01121 { 01122 const char *hold = "Unknown"; 01123 01124 switch (hold_access) { 01125 case SLA_HOLD_OPEN: 01126 hold = "Open"; 01127 break; 01128 case SLA_HOLD_PRIVATE: 01129 hold = "Private"; 01130 default: 01131 break; 01132 } 01133 01134 return hold; 01135 }
static int sla_load_config | ( | void | ) | [static] |
Definition at line 5093 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(), LOG_WARNING, sla, sla_build_station(), sla_build_trunk(), SLA_CONFIG_FILE, sla_thread(), and type.
Referenced by load_config().
05094 { 05095 struct ast_config *cfg; 05096 const char *cat = NULL; 05097 int res = 0; 05098 const char *val; 05099 05100 ast_mutex_init(&sla.lock); 05101 ast_cond_init(&sla.cond, NULL); 05102 05103 if (!(cfg = ast_config_load(SLA_CONFIG_FILE))) 05104 return 0; /* Treat no config as normal */ 05105 05106 if ((val = ast_variable_retrieve(cfg, "general", "attemptcallerid"))) 05107 sla.attempt_callerid = ast_true(val); 05108 05109 while ((cat = ast_category_browse(cfg, cat)) && !res) { 05110 const char *type; 05111 if (!strcasecmp(cat, "general")) 05112 continue; 05113 if (!(type = ast_variable_retrieve(cfg, cat, "type"))) { 05114 ast_log(LOG_WARNING, "Invalid entry in %s defined with no type!\n", 05115 SLA_CONFIG_FILE); 05116 continue; 05117 } 05118 if (!strcasecmp(type, "trunk")) 05119 res = sla_build_trunk(cfg, cat); 05120 else if (!strcasecmp(type, "station")) 05121 res = sla_build_station(cfg, cat); 05122 else { 05123 ast_log(LOG_WARNING, "Entry in %s defined with invalid type '%s'!\n", 05124 SLA_CONFIG_FILE, type); 05125 } 05126 } 05127 05128 ast_config_destroy(cfg); 05129 05130 if (!AST_LIST_EMPTY(&sla_stations) || !AST_LIST_EMPTY(&sla_stations)) 05131 ast_pthread_create(&sla.thread, NULL, sla_thread, NULL); 05132 05133 return res; 05134 }
static int sla_process_timers | ( | struct timespec * | ts | ) | [static] |
Calculate the time until the next known event.
Definition at line 4237 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().
04238 { 04239 unsigned int timeout = UINT_MAX; 04240 struct timeval tv; 04241 unsigned int change_made = 0; 04242 04243 /* Check for ring timeouts on ringing trunks */ 04244 if (sla_calc_trunk_timeouts(&timeout)) 04245 change_made = 1; 04246 04247 /* Check for ring timeouts on ringing stations */ 04248 if (sla_calc_station_timeouts(&timeout)) 04249 change_made = 1; 04250 04251 /* Check for station ring delays */ 04252 if (sla_calc_station_delays(&timeout)) 04253 change_made = 1; 04254 04255 /* queue reprocessing of ringing trunks */ 04256 if (change_made) 04257 sla_queue_event_nolock(SLA_EVENT_RINGING_TRUNK); 04258 04259 /* No timeout */ 04260 if (timeout == UINT_MAX) 04261 return 0; 04262 04263 if (ts) { 04264 tv = ast_tvadd(ast_tvnow(), ast_samp2tv(timeout, 1000)); 04265 ts->tv_sec = tv.tv_sec; 04266 ts->tv_nsec = tv.tv_usec * 1000; 04267 } 04268 04269 return 1; 04270 }
static void sla_queue_event | ( | enum sla_event_type | type | ) | [static] |
Definition at line 1423 of file app_meetme.c.
References sla_queue_event_full().
Referenced by queue_ringing_trunk(), sla_dial_state_callback(), sla_handle_dial_state_event(), sla_station_exec(), and sla_trunk_exec().
01424 { 01425 sla_queue_event_full(type, NULL, NULL, 1); 01426 }
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 1429 of file app_meetme.c.
References AST_LIST_TRAVERSE, ast_log(), AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_strdupa, ast_strlen_zero(), sla_trunk_ref::chan, ast_conference::confno, announce_listitem::entry, LOG_DEBUG, LOG_ERROR, sla_trunk::name, sla_queue_event_full(), sla_trunk_ref::trunk, and sla_station::trunks.
Referenced by conf_run().
01431 { 01432 struct sla_station *station; 01433 struct sla_trunk_ref *trunk_ref = NULL; 01434 char *trunk_name; 01435 01436 trunk_name = ast_strdupa(conf->confno); 01437 strsep(&trunk_name, "_"); 01438 if (ast_strlen_zero(trunk_name)) { 01439 ast_log(LOG_ERROR, "Invalid conference name for SLA - '%s'!\n", conf->confno); 01440 return; 01441 } 01442 01443 AST_RWLIST_RDLOCK(&sla_stations); 01444 AST_RWLIST_TRAVERSE(&sla_stations, station, entry) { 01445 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) { 01446 if (trunk_ref->chan == chan && !strcmp(trunk_ref->trunk->name, trunk_name)) 01447 break; 01448 } 01449 if (trunk_ref) 01450 break; 01451 } 01452 AST_RWLIST_UNLOCK(&sla_stations); 01453 01454 if (!trunk_ref) { 01455 ast_log(LOG_DEBUG, "Trunk not found for event!\n"); 01456 return; 01457 } 01458 01459 sla_queue_event_full(type, trunk_ref, station, 1); 01460 }
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 1391 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().
01393 { 01394 struct sla_event *event; 01395 01396 if (sla.thread == AST_PTHREADT_NULL) { 01397 return; 01398 } 01399 01400 if (!(event = ast_calloc(1, sizeof(*event)))) 01401 return; 01402 01403 event->type = type; 01404 event->trunk_ref = trunk_ref; 01405 event->station = station; 01406 01407 if (!lock) { 01408 AST_LIST_INSERT_TAIL(&sla.event_q, event, entry); 01409 return; 01410 } 01411 01412 ast_mutex_lock(&sla.lock); 01413 AST_LIST_INSERT_TAIL(&sla.event_q, event, entry); 01414 ast_cond_signal(&sla.cond); 01415 ast_mutex_unlock(&sla.lock); 01416 }
static void sla_queue_event_nolock | ( | enum sla_event_type | type | ) | [static] |
Definition at line 1418 of file app_meetme.c.
References sla_queue_event_full().
Referenced by sla_process_timers().
01419 { 01420 sla_queue_event_full(type, NULL, NULL, 0); 01421 }
static int sla_ring_station | ( | struct sla_ringing_trunk * | ringing_trunk, | |
struct sla_station * | station | |||
) | [static] |
Ring a station.
Definition at line 3854 of file app_meetme.c.
References ast_calloc, ast_dial_append(), ast_dial_create(), ast_dial_destroy(), ast_dial_join(), AST_DIAL_RESULT_TRYING, ast_dial_run(), ast_dial_set_state_callback(), AST_LIST_INSERT_HEAD, ast_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, free, sla, sla_create_ringing_station(), sla_dial_state_callback(), sla_failed_station::station, sla_ringing_station::station, and sla_ringing_trunk::trunk.
Referenced by sla_ring_stations().
03855 { 03856 char *tech, *tech_data; 03857 struct ast_dial *dial; 03858 struct sla_ringing_station *ringing_station; 03859 const char *cid_name = NULL, *cid_num = NULL; 03860 enum ast_dial_result res; 03861 03862 if (!(dial = ast_dial_create())) 03863 return -1; 03864 03865 ast_dial_set_state_callback(dial, sla_dial_state_callback); 03866 tech_data = ast_strdupa(station->device); 03867 tech = strsep(&tech_data, "/"); 03868 03869 if (ast_dial_append(dial, tech, tech_data) == -1) { 03870 ast_dial_destroy(dial); 03871 return -1; 03872 } 03873 03874 if (!sla.attempt_callerid && !ast_strlen_zero(ringing_trunk->trunk->chan->cid.cid_name)) { 03875 cid_name = ast_strdupa(ringing_trunk->trunk->chan->cid.cid_name); 03876 free(ringing_trunk->trunk->chan->cid.cid_name); 03877 ringing_trunk->trunk->chan->cid.cid_name = NULL; 03878 } 03879 if (!sla.attempt_callerid && !ast_strlen_zero(ringing_trunk->trunk->chan->cid.cid_num)) { 03880 cid_num = ast_strdupa(ringing_trunk->trunk->chan->cid.cid_num); 03881 free(ringing_trunk->trunk->chan->cid.cid_num); 03882 ringing_trunk->trunk->chan->cid.cid_num = NULL; 03883 } 03884 03885 res = ast_dial_run(dial, ringing_trunk->trunk->chan, 1); 03886 03887 if (cid_name) 03888 ringing_trunk->trunk->chan->cid.cid_name = ast_strdup(cid_name); 03889 if (cid_num) 03890 ringing_trunk->trunk->chan->cid.cid_num = ast_strdup(cid_num); 03891 03892 if (res != AST_DIAL_RESULT_TRYING) { 03893 struct sla_failed_station *failed_station; 03894 ast_dial_destroy(dial); 03895 if (!(failed_station = ast_calloc(1, sizeof(*failed_station)))) 03896 return -1; 03897 failed_station->station = station; 03898 failed_station->last_try = ast_tvnow(); 03899 AST_LIST_INSERT_HEAD(&sla.failed_stations, failed_station, entry); 03900 return -1; 03901 } 03902 if (!(ringing_station = sla_create_ringing_station(station))) { 03903 ast_dial_join(dial); 03904 ast_dial_destroy(dial); 03905 return -1; 03906 } 03907 03908 station->dial = dial; 03909 03910 AST_LIST_INSERT_HEAD(&sla.ringing_stations, ringing_station, entry); 03911 03912 return 0; 03913 }
static void sla_ring_stations | ( | void | ) | [static] |
Ring stations based on current set of ringing trunks.
Definition at line 3980 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().
03981 { 03982 struct sla_station_ref *station_ref; 03983 struct sla_ringing_trunk *ringing_trunk; 03984 03985 /* Make sure that every station that uses at least one of the ringing 03986 * trunks, is ringing. */ 03987 AST_LIST_TRAVERSE(&sla.ringing_trunks, ringing_trunk, entry) { 03988 AST_LIST_TRAVERSE(&ringing_trunk->trunk->stations, station_ref, entry) { 03989 int time_left; 03990 03991 /* Is this station already ringing? */ 03992 if (sla_check_ringing_station(station_ref->station)) 03993 continue; 03994 03995 /* Is this station already in a call? */ 03996 if (sla_check_inuse_station(station_ref->station)) 03997 continue; 03998 03999 /* Did we fail to dial this station earlier? If so, has it been 04000 * a minute since we tried? */ 04001 if (sla_check_failed_station(station_ref->station)) 04002 continue; 04003 04004 /* If this station already timed out while this trunk was ringing, 04005 * do not dial it again for this ringing trunk. */ 04006 if (sla_check_timed_out_station(ringing_trunk, station_ref->station)) 04007 continue; 04008 04009 /* Check for a ring delay in progress */ 04010 time_left = sla_check_station_delay(station_ref->station, ringing_trunk); 04011 if (time_left != INT_MAX && time_left > 0) 04012 continue; 04013 04014 /* It is time to make this station begin to ring. Do it! */ 04015 sla_ring_station(ringing_trunk, station_ref->station); 04016 } 04017 } 04018 /* Now, all of the stations that should be ringing, are ringing. */ 04019 }
static int sla_show_stations | ( | int | fd, | |
int | argc, | |||
char ** | argv | |||
) | [static] |
Definition at line 1197 of file app_meetme.c.
References ast_cli(), AST_LIST_TRAVERSE, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, sla_station::autocontext, sla_station::device, announce_listitem::entry, sla_station::hold_access, sla_trunk::name, sla_station::name, RESULT_SUCCESS, 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, and trunkstate2str().
01198 { 01199 const struct sla_station *station; 01200 01201 ast_cli(fd, "\n" 01202 "=============================================================\n" 01203 "=== Configured SLA Stations =================================\n" 01204 "=============================================================\n" 01205 "===\n"); 01206 AST_RWLIST_RDLOCK(&sla_stations); 01207 AST_RWLIST_TRAVERSE(&sla_stations, station, entry) { 01208 struct sla_trunk_ref *trunk_ref; 01209 char ring_timeout[16] = "(none)"; 01210 char ring_delay[16] = "(none)"; 01211 if (station->ring_timeout) { 01212 snprintf(ring_timeout, sizeof(ring_timeout), 01213 "%u", station->ring_timeout); 01214 } 01215 if (station->ring_delay) { 01216 snprintf(ring_delay, sizeof(ring_delay), 01217 "%u", station->ring_delay); 01218 } 01219 ast_cli(fd, "=== ---------------------------------------------------------\n" 01220 "=== Station Name: %s\n" 01221 "=== ==> Device: %s\n" 01222 "=== ==> AutoContext: %s\n" 01223 "=== ==> RingTimeout: %s\n" 01224 "=== ==> RingDelay: %s\n" 01225 "=== ==> HoldAccess: %s\n" 01226 "=== ==> Trunks ...\n", 01227 station->name, station->device, 01228 S_OR(station->autocontext, "(none)"), 01229 ring_timeout, ring_delay, 01230 sla_hold_str(station->hold_access)); 01231 AST_RWLIST_RDLOCK(&sla_trunks); 01232 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) { 01233 if (trunk_ref->ring_timeout) { 01234 snprintf(ring_timeout, sizeof(ring_timeout), 01235 "%u", trunk_ref->ring_timeout); 01236 } else 01237 strcpy(ring_timeout, "(none)"); 01238 if (trunk_ref->ring_delay) { 01239 snprintf(ring_delay, sizeof(ring_delay), 01240 "%u", trunk_ref->ring_delay); 01241 } else 01242 strcpy(ring_delay, "(none)"); 01243 ast_cli(fd, "=== ==> Trunk Name: %s\n" 01244 "=== ==> State: %s\n" 01245 "=== ==> RingTimeout: %s\n" 01246 "=== ==> RingDelay: %s\n", 01247 trunk_ref->trunk->name, 01248 trunkstate2str(trunk_ref->state), 01249 ring_timeout, ring_delay); 01250 } 01251 AST_RWLIST_UNLOCK(&sla_trunks); 01252 ast_cli(fd, "=== ---------------------------------------------------------\n" 01253 "===\n"); 01254 } 01255 AST_RWLIST_UNLOCK(&sla_stations); 01256 ast_cli(fd, "============================================================\n" 01257 "\n"); 01258 01259 return RESULT_SUCCESS; 01260 }
static int sla_show_trunks | ( | int | fd, | |
int | argc, | |||
char ** | argv | |||
) | [static] |
Definition at line 1137 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, sla_trunk::device, announce_listitem::entry, sla_trunk::hold_access, sla_station::name, sla_trunk::name, RESULT_SUCCESS, sla_trunk::ring_timeout, S_OR, sla_hold_str(), sla_station_ref::station, and sla_trunk::stations.
01138 { 01139 const struct sla_trunk *trunk; 01140 01141 ast_cli(fd, "\n" 01142 "=============================================================\n" 01143 "=== Configured SLA Trunks ===================================\n" 01144 "=============================================================\n" 01145 "===\n"); 01146 AST_RWLIST_RDLOCK(&sla_trunks); 01147 AST_RWLIST_TRAVERSE(&sla_trunks, trunk, entry) { 01148 struct sla_station_ref *station_ref; 01149 char ring_timeout[16] = "(none)"; 01150 if (trunk->ring_timeout) 01151 snprintf(ring_timeout, sizeof(ring_timeout), "%u Seconds", trunk->ring_timeout); 01152 ast_cli(fd, "=== ---------------------------------------------------------\n" 01153 "=== Trunk Name: %s\n" 01154 "=== ==> Device: %s\n" 01155 "=== ==> AutoContext: %s\n" 01156 "=== ==> RingTimeout: %s\n" 01157 "=== ==> BargeAllowed: %s\n" 01158 "=== ==> HoldAccess: %s\n" 01159 "=== ==> Stations ...\n", 01160 trunk->name, trunk->device, 01161 S_OR(trunk->autocontext, "(none)"), 01162 ring_timeout, 01163 trunk->barge_disabled ? "No" : "Yes", 01164 sla_hold_str(trunk->hold_access)); 01165 AST_RWLIST_RDLOCK(&sla_stations); 01166 AST_LIST_TRAVERSE(&trunk->stations, station_ref, entry) 01167 ast_cli(fd, "=== ==> Station name: %s\n", station_ref->station->name); 01168 AST_RWLIST_UNLOCK(&sla_stations); 01169 ast_cli(fd, "=== ---------------------------------------------------------\n" 01170 "===\n"); 01171 } 01172 AST_RWLIST_UNLOCK(&sla_trunks); 01173 ast_cli(fd, "=============================================================\n" 01174 "\n"); 01175 01176 return RESULT_SUCCESS; 01177 }
static int sla_state | ( | const char * | data | ) | [static] |
Definition at line 4717 of file app_meetme.c.
References AST_DEVICE_INUSE, AST_DEVICE_INVALID, AST_DEVICE_NOT_INUSE, AST_DEVICE_ONHOLD, AST_DEVICE_RINGING, AST_LIST_TRAVERSE, ast_log(), AST_RWLIST_RDLOCK, AST_RWLIST_UNLOCK, ast_strdupa, announce_listitem::entry, LOG_ERROR, sla_trunk::name, sla_station::name, SLA_TRUNK_STATE_IDLE, SLA_TRUNK_STATE_ONHOLD, SLA_TRUNK_STATE_ONHOLD_BYME, SLA_TRUNK_STATE_RINGING, SLA_TRUNK_STATE_UP, sla_trunk_ref::state, sla_trunk_ref::trunk, and sla_station::trunks.
Referenced by load_module().
04718 { 04719 char *buf, *station_name, *trunk_name; 04720 struct sla_station *station; 04721 struct sla_trunk_ref *trunk_ref; 04722 int res = AST_DEVICE_INVALID; 04723 04724 trunk_name = buf = ast_strdupa(data); 04725 station_name = strsep(&trunk_name, "_"); 04726 04727 AST_RWLIST_RDLOCK(&sla_stations); 04728 AST_LIST_TRAVERSE(&sla_stations, station, entry) { 04729 if (strcasecmp(station_name, station->name)) 04730 continue; 04731 AST_RWLIST_RDLOCK(&sla_trunks); 04732 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) { 04733 if (!strcasecmp(trunk_name, trunk_ref->trunk->name)) 04734 break; 04735 } 04736 if (!trunk_ref) { 04737 AST_RWLIST_UNLOCK(&sla_trunks); 04738 break; 04739 } 04740 switch (trunk_ref->state) { 04741 case SLA_TRUNK_STATE_IDLE: 04742 res = AST_DEVICE_NOT_INUSE; 04743 break; 04744 case SLA_TRUNK_STATE_RINGING: 04745 res = AST_DEVICE_RINGING; 04746 break; 04747 case SLA_TRUNK_STATE_UP: 04748 res = AST_DEVICE_INUSE; 04749 break; 04750 case SLA_TRUNK_STATE_ONHOLD: 04751 case SLA_TRUNK_STATE_ONHOLD_BYME: 04752 res = AST_DEVICE_ONHOLD; 04753 break; 04754 } 04755 AST_RWLIST_UNLOCK(&sla_trunks); 04756 } 04757 AST_RWLIST_UNLOCK(&sla_stations); 04758 04759 if (res == AST_DEVICE_INVALID) { 04760 ast_log(LOG_ERROR, "Could not determine state for trunk %s on station %s!\n", 04761 trunk_name, station_name); 04762 } 04763 04764 return res; 04765 }
static int sla_station_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Definition at line 4459 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_device_state_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_background, AST_RWLIST_RDLOCK, AST_RWLIST_UNLOCK, ast_set_flag, ast_strdupa, ast_strlen_zero(), build_conf(), sla_trunk_ref::chan, sla_trunk::chan, ast_conference::chan, cond, conf_run(), CONFFLAG_MARKEDEXIT, CONFFLAG_PASS_DTMF, CONFFLAG_SLA_STATION, dial_trunk(), dispose_conf(), announce_listitem::entry, ast_flags::flags, free, sla_trunk::hold_stations, LOG_DEBUG, LOG_NOTICE, LOG_WARNING, MAX_CONFNUM, sla_trunk::name, sla_station::name, sla_trunk::on_hold, pbx_builtin_setvar_helper(), sla, sla_change_trunk_state(), sla_choose_idle_trunk(), 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, sla_ringing_trunk::trunk, sla_trunk_ref::trunk, and dial_trunk_args::trunk_ref.
Referenced by load_module().
04460 { 04461 char *station_name, *trunk_name; 04462 struct sla_station *station; 04463 struct sla_trunk_ref *trunk_ref = NULL; 04464 char conf_name[MAX_CONFNUM]; 04465 struct ast_flags conf_flags = { 0 }; 04466 struct ast_conference *conf; 04467 04468 if (ast_strlen_zero(data)) { 04469 ast_log(LOG_WARNING, "Invalid Arguments to SLAStation!\n"); 04470 pbx_builtin_setvar_helper(chan, "SLASTATION_STATUS", "FAILURE"); 04471 return 0; 04472 } 04473 04474 trunk_name = ast_strdupa(data); 04475 station_name = strsep(&trunk_name, "_"); 04476 04477 if (ast_strlen_zero(station_name)) { 04478 ast_log(LOG_WARNING, "Invalid Arguments to SLAStation!\n"); 04479 pbx_builtin_setvar_helper(chan, "SLASTATION_STATUS", "FAILURE"); 04480 return 0; 04481 } 04482 04483 AST_RWLIST_RDLOCK(&sla_stations); 04484 station = sla_find_station(station_name); 04485 AST_RWLIST_UNLOCK(&sla_stations); 04486 04487 if (!station) { 04488 ast_log(LOG_WARNING, "Station '%s' not found!\n", station_name); 04489 pbx_builtin_setvar_helper(chan, "SLASTATION_STATUS", "FAILURE"); 04490 return 0; 04491 } 04492 04493 AST_RWLIST_RDLOCK(&sla_trunks); 04494 if (!ast_strlen_zero(trunk_name)) { 04495 trunk_ref = sla_find_trunk_ref_byname(station, trunk_name); 04496 } else 04497 trunk_ref = sla_choose_idle_trunk(station); 04498 AST_RWLIST_UNLOCK(&sla_trunks); 04499 04500 if (!trunk_ref) { 04501 if (ast_strlen_zero(trunk_name)) 04502 ast_log(LOG_NOTICE, "No trunks available for call.\n"); 04503 else { 04504 ast_log(LOG_NOTICE, "Can't join existing call on trunk " 04505 "'%s' due to access controls.\n", trunk_name); 04506 } 04507 pbx_builtin_setvar_helper(chan, "SLASTATION_STATUS", "CONGESTION"); 04508 return 0; 04509 } 04510 04511 if (trunk_ref->state == SLA_TRUNK_STATE_ONHOLD_BYME) { 04512 if (ast_atomic_dec_and_test((int *) &trunk_ref->trunk->hold_stations) == 1) 04513 sla_change_trunk_state(trunk_ref->trunk, SLA_TRUNK_STATE_UP, ALL_TRUNK_REFS, NULL); 04514 else { 04515 trunk_ref->state = SLA_TRUNK_STATE_UP; 04516 ast_device_state_changed("SLA:%s_%s", station->name, trunk_ref->trunk->name); 04517 } 04518 } else if (trunk_ref->state == SLA_TRUNK_STATE_RINGING) { 04519 struct sla_ringing_trunk *ringing_trunk; 04520 04521 ast_mutex_lock(&sla.lock); 04522 AST_LIST_TRAVERSE_SAFE_BEGIN(&sla.ringing_trunks, ringing_trunk, entry) { 04523 if (ringing_trunk->trunk == trunk_ref->trunk) { 04524 AST_LIST_REMOVE_CURRENT(&sla.ringing_trunks, entry); 04525 break; 04526 } 04527 } 04528 AST_LIST_TRAVERSE_SAFE_END 04529 ast_mutex_unlock(&sla.lock); 04530 04531 if (ringing_trunk) { 04532 answer_trunk_chan(ringing_trunk->trunk->chan); 04533 sla_change_trunk_state(ringing_trunk->trunk, SLA_TRUNK_STATE_UP, ALL_TRUNK_REFS, NULL); 04534 04535 free(ringing_trunk); 04536 04537 /* Queue up reprocessing ringing trunks, and then ringing stations again */ 04538 sla_queue_event(SLA_EVENT_RINGING_TRUNK); 04539 sla_queue_event(SLA_EVENT_DIAL_STATE); 04540 } 04541 } 04542 04543 trunk_ref->chan = chan; 04544 04545 if (!trunk_ref->trunk->chan) { 04546 ast_mutex_t cond_lock; 04547 ast_cond_t cond; 04548 pthread_t dont_care; 04549 pthread_attr_t attr; 04550 struct dial_trunk_args args = { 04551 .trunk_ref = trunk_ref, 04552 .station = station, 04553 .cond_lock = &cond_lock, 04554 .cond = &cond, 04555 }; 04556 sla_change_trunk_state(trunk_ref->trunk, SLA_TRUNK_STATE_UP, ALL_TRUNK_REFS, NULL); 04557 /* Create a thread to dial the trunk and dump it into the conference. 04558 * However, we want to wait until the trunk has been dialed and the 04559 * conference is created before continuing on here. */ 04560 ast_autoservice_start(chan); 04561 ast_mutex_init(&cond_lock); 04562 ast_cond_init(&cond, NULL); 04563 pthread_attr_init(&attr); 04564 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 04565 ast_mutex_lock(&cond_lock); 04566 ast_pthread_create_background(&dont_care, &attr, dial_trunk, &args); 04567 ast_cond_wait(&cond, &cond_lock); 04568 ast_mutex_unlock(&cond_lock); 04569 ast_mutex_destroy(&cond_lock); 04570 ast_cond_destroy(&cond); 04571 pthread_attr_destroy(&attr); 04572 ast_autoservice_stop(chan); 04573 if (!trunk_ref->trunk->chan) { 04574 ast_log(LOG_DEBUG, "Trunk didn't get created. chan: %lx\n", (long) trunk_ref->trunk->chan); 04575 pbx_builtin_setvar_helper(chan, "SLASTATION_STATUS", "CONGESTION"); 04576 sla_change_trunk_state(trunk_ref->trunk, SLA_TRUNK_STATE_IDLE, ALL_TRUNK_REFS, NULL); 04577 trunk_ref->chan = NULL; 04578 return 0; 04579 } 04580 } 04581 04582 if (ast_atomic_fetchadd_int((int *) &trunk_ref->trunk->active_stations, 1) == 0 && 04583 trunk_ref->trunk->on_hold) { 04584 trunk_ref->trunk->on_hold = 0; 04585 ast_indicate(trunk_ref->trunk->chan, AST_CONTROL_UNHOLD); 04586 sla_change_trunk_state(trunk_ref->trunk, SLA_TRUNK_STATE_UP, ALL_TRUNK_REFS, NULL); 04587 } 04588 04589 snprintf(conf_name, sizeof(conf_name), "SLA_%s", trunk_ref->trunk->name); 04590 ast_set_flag(&conf_flags, 04591 CONFFLAG_QUIET | CONFFLAG_MARKEDEXIT | CONFFLAG_PASS_DTMF | CONFFLAG_SLA_STATION); 04592 ast_answer(chan); 04593 conf = build_conf(conf_name, "", "", 0, 0, 1); 04594 if (conf) { 04595 conf_run(chan, conf, conf_flags.flags, NULL); 04596 dispose_conf(conf); 04597 conf = NULL; 04598 } 04599 trunk_ref->chan = NULL; 04600 if (ast_atomic_dec_and_test((int *) &trunk_ref->trunk->active_stations) && 04601 trunk_ref->state != SLA_TRUNK_STATE_ONHOLD_BYME) { 04602 strncat(conf_name, "|K", sizeof(conf_name) - strlen(conf_name) - 1); 04603 admin_exec(NULL, conf_name); 04604 trunk_ref->trunk->hold_stations = 0; 04605 sla_change_trunk_state(trunk_ref->trunk, SLA_TRUNK_STATE_IDLE, ALL_TRUNK_REFS, NULL); 04606 } 04607 04608 pbx_builtin_setvar_helper(chan, "SLASTATION_STATUS", "SUCCESS"); 04609 04610 return 0; 04611 }
static void sla_stop_ringing_station | ( | struct sla_ringing_station * | ringing_station, | |
enum sla_station_hangup | hangup | |||
) | [static] |
Definition at line 3639 of file app_meetme.c.
References ast_dial_destroy(), ast_dial_join(), AST_LIST_INSERT_TAIL, AST_LIST_TRAVERSE, sla_station::dial, announce_listitem::entry, free, 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().
03641 { 03642 struct sla_ringing_trunk *ringing_trunk; 03643 struct sla_trunk_ref *trunk_ref; 03644 struct sla_station_ref *station_ref; 03645 03646 ast_dial_join(ringing_station->station->dial); 03647 ast_dial_destroy(ringing_station->station->dial); 03648 ringing_station->station->dial = NULL; 03649 03650 if (hangup == SLA_STATION_HANGUP_NORMAL) 03651 goto done; 03652 03653 /* If the station is being hung up because of a timeout, then add it to the 03654 * list of timed out stations on each of the ringing trunks. This is so 03655 * that when doing further processing to figure out which stations should be 03656 * ringing, which trunk to answer, determining timeouts, etc., we know which 03657 * ringing trunks we should ignore. */ 03658 AST_LIST_TRAVERSE(&sla.ringing_trunks, ringing_trunk, entry) { 03659 AST_LIST_TRAVERSE(&ringing_station->station->trunks, trunk_ref, entry) { 03660 if (ringing_trunk->trunk == trunk_ref->trunk) 03661 break; 03662 } 03663 if (!trunk_ref) 03664 continue; 03665 if (!(station_ref = sla_create_station_ref(ringing_station->station))) 03666 continue; 03667 AST_LIST_INSERT_TAIL(&ringing_trunk->timed_out_stations, station_ref, entry); 03668 } 03669 03670 done: 03671 free(ringing_station); 03672 }
static void sla_stop_ringing_trunk | ( | struct sla_ringing_trunk * | ringing_trunk | ) | [static] |
Definition at line 3624 of file app_meetme.c.
References admin_exec(), ALL_TRUNK_REFS, AST_LIST_REMOVE_HEAD, announce_listitem::entry, free, 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().
03625 { 03626 char buf[80]; 03627 struct sla_station_ref *station_ref; 03628 03629 snprintf(buf, sizeof(buf), "SLA_%s|K", ringing_trunk->trunk->name); 03630 admin_exec(NULL, buf); 03631 sla_change_trunk_state(ringing_trunk->trunk, SLA_TRUNK_STATE_IDLE, ALL_TRUNK_REFS, NULL); 03632 03633 while ((station_ref = AST_LIST_REMOVE_HEAD(&ringing_trunk->timed_out_stations, entry))) 03634 free(station_ref); 03635 03636 free(ringing_trunk); 03637 }
static void* sla_thread | ( | void * | data | ) | [static] |
Definition at line 4272 of file app_meetme.c.
References ast_cond_timedwait(), ast_cond_wait(), AST_LIST_EMPTY, AST_LIST_REMOVE_HEAD, ast_mutex_lock(), ast_mutex_unlock(), announce_listitem::entry, free, sla, SLA_EVENT_DIAL_STATE, SLA_EVENT_HOLD, 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().
04273 { 04274 struct sla_failed_station *failed_station; 04275 struct sla_ringing_station *ringing_station; 04276 04277 ast_mutex_lock(&sla.lock); 04278 04279 while (!sla.stop) { 04280 struct sla_event *event; 04281 struct timespec ts = { 0, }; 04282 unsigned int have_timeout = 0; 04283 04284 if (AST_LIST_EMPTY(&sla.event_q)) { 04285 if ((have_timeout = sla_process_timers(&ts))) 04286 ast_cond_timedwait(&sla.cond, &sla.lock, &ts); 04287 else 04288 ast_cond_wait(&sla.cond, &sla.lock); 04289 if (sla.stop) 04290 break; 04291 } 04292 04293 if (have_timeout) 04294 sla_process_timers(NULL); 04295 04296 while ((event = AST_LIST_REMOVE_HEAD(&sla.event_q, entry))) { 04297 ast_mutex_unlock(&sla.lock); 04298 switch (event->type) { 04299 case SLA_EVENT_HOLD: 04300 sla_handle_hold_event(event); 04301 break; 04302 case SLA_EVENT_DIAL_STATE: 04303 sla_handle_dial_state_event(); 04304 break; 04305 case SLA_EVENT_RINGING_TRUNK: 04306 sla_handle_ringing_trunk_event(); 04307 break; 04308 } 04309 free(event); 04310 ast_mutex_lock(&sla.lock); 04311 } 04312 } 04313 04314 ast_mutex_unlock(&sla.lock); 04315 04316 while ((ringing_station = AST_LIST_REMOVE_HEAD(&sla.ringing_stations, entry))) 04317 free(ringing_station); 04318 04319 while ((failed_station = AST_LIST_REMOVE_HEAD(&sla.failed_stations, entry))) 04320 free(failed_station); 04321 04322 return NULL; 04323 }
static int sla_trunk_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Definition at line 4646 of file app_meetme.c.
References ALL_TRUNK_REFS, AST_CONTROL_RINGING, 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, build_conf(), sla_trunk::chan, conf_run(), CONFFLAG_MARKEDEXIT, CONFFLAG_MARKEDUSER, CONFFLAG_NO_AUDIO_UNTIL_UP, CONFFLAG_PASS_DTMF, dispose_conf(), announce_listitem::entry, ast_flags::flags, free, LOG_ERROR, MAX_CONFNUM, sla_trunk::on_hold, pbx_builtin_getvar_helper(), pbx_builtin_setvar_helper(), queue_ringing_trunk(), sla, sla_change_trunk_state(), SLA_EVENT_RINGING_TRUNK, sla_find_trunk(), sla_queue_event(), SLA_TRUNK_STATE_IDLE, and sla_ringing_trunk::trunk.
Referenced by load_module().
04647 { 04648 const char *trunk_name = data; 04649 char conf_name[MAX_CONFNUM]; 04650 struct ast_conference *conf; 04651 struct ast_flags conf_flags = { 0 }; 04652 struct sla_trunk *trunk; 04653 struct sla_ringing_trunk *ringing_trunk; 04654 04655 AST_RWLIST_RDLOCK(&sla_trunks); 04656 trunk = sla_find_trunk(trunk_name); 04657 AST_RWLIST_UNLOCK(&sla_trunks); 04658 if (!trunk) { 04659 ast_log(LOG_ERROR, "SLA Trunk '%s' not found!\n", trunk_name); 04660 pbx_builtin_setvar_helper(chan, "SLATRUNK_STATUS", "FAILURE"); 04661 return 0; 04662 } 04663 if (trunk->chan) { 04664 ast_log(LOG_ERROR, "Call came in on %s, but the trunk is already in use!\n", 04665 trunk_name); 04666 pbx_builtin_setvar_helper(chan, "SLATRUNK_STATUS", "FAILURE"); 04667 return 0; 04668 } 04669 trunk->chan = chan; 04670 04671 if (!(ringing_trunk = queue_ringing_trunk(trunk))) { 04672 pbx_builtin_setvar_helper(chan, "SLATRUNK_STATUS", "FAILURE"); 04673 return 0; 04674 } 04675 04676 snprintf(conf_name, sizeof(conf_name), "SLA_%s", trunk_name); 04677 conf = build_conf(conf_name, "", "", 1, 1, 1); 04678 if (!conf) { 04679 pbx_builtin_setvar_helper(chan, "SLATRUNK_STATUS", "FAILURE"); 04680 return 0; 04681 } 04682 ast_set_flag(&conf_flags, 04683 CONFFLAG_QUIET | CONFFLAG_MARKEDEXIT | CONFFLAG_MARKEDUSER | CONFFLAG_PASS_DTMF | CONFFLAG_NO_AUDIO_UNTIL_UP); 04684 ast_indicate(chan, AST_CONTROL_RINGING); 04685 conf_run(chan, conf, conf_flags.flags, NULL); 04686 dispose_conf(conf); 04687 conf = NULL; 04688 trunk->chan = NULL; 04689 trunk->on_hold = 0; 04690 04691 sla_change_trunk_state(trunk, SLA_TRUNK_STATE_IDLE, ALL_TRUNK_REFS, NULL); 04692 04693 if (!pbx_builtin_getvar_helper(chan, "SLATRUNK_STATUS")) 04694 pbx_builtin_setvar_helper(chan, "SLATRUNK_STATUS", "SUCCESS"); 04695 04696 /* Remove the entry from the list of ringing trunks if it is still there. */ 04697 ast_mutex_lock(&sla.lock); 04698 AST_LIST_TRAVERSE_SAFE_BEGIN(&sla.ringing_trunks, ringing_trunk, entry) { 04699 if (ringing_trunk->trunk == trunk) { 04700 AST_LIST_REMOVE_CURRENT(&sla.ringing_trunks, entry); 04701 break; 04702 } 04703 } 04704 AST_LIST_TRAVERSE_SAFE_END 04705 ast_mutex_unlock(&sla.lock); 04706 if (ringing_trunk) { 04707 free(ringing_trunk); 04708 pbx_builtin_setvar_helper(chan, "SLATRUNK_STATUS", "UNANSWERED"); 04709 /* Queue reprocessing of ringing trunks to make stations stop ringing 04710 * that shouldn't be ringing after this trunk stopped. */ 04711 sla_queue_event(SLA_EVENT_RINGING_TRUNK); 04712 } 04713 04714 return 0; 04715 }
static const char* trunkstate2str | ( | enum sla_trunk_state | state | ) | [static] |
Definition at line 1179 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().
01180 { 01181 #define S(e) case e: return # e; 01182 switch (state) { 01183 S(SLA_TRUNK_STATE_IDLE) 01184 S(SLA_TRUNK_STATE_RINGING) 01185 S(SLA_TRUNK_STATE_UP) 01186 S(SLA_TRUNK_STATE_ONHOLD) 01187 S(SLA_TRUNK_STATE_ONHOLD_BYME) 01188 } 01189 return "Uknown State"; 01190 #undef S 01191 }
static void tweak_listen_volume | ( | struct ast_conf_user * | user, | |
enum volume_action | action | |||
) | [static] |
Definition at line 707 of file app_meetme.c.
References volume::actual, volume::desired, ast_conf_user::listen, set_listen_volume(), and tweak_volume().
Referenced by admin_exec(), conf_run(), user_listen_voldown_cb(), and user_listen_volup_cb().
00708 { 00709 tweak_volume(&user->listen, action); 00710 /* attempt to make the adjustment in the channel driver; 00711 if successful, don't adjust in the frame reading routine 00712 */ 00713 if (!set_listen_volume(user, user->listen.desired)) 00714 user->listen.actual = 0; 00715 else 00716 user->listen.actual = user->listen.desired; 00717 }
static void tweak_talk_volume | ( | struct ast_conf_user * | user, | |
enum volume_action | action | |||
) | [static] |
Definition at line 695 of file app_meetme.c.
References volume::actual, volume::desired, set_talk_volume(), ast_conf_user::talk, and tweak_volume().
Referenced by admin_exec(), conf_run(), user_talk_voldown_cb(), and user_talk_volup_cb().
00696 { 00697 tweak_volume(&user->talk, action); 00698 /* attempt to make the adjustment in the channel driver; 00699 if successful, don't adjust in the frame reading routine 00700 */ 00701 if (!set_talk_volume(user, user->talk.desired)) 00702 user->talk.actual = 0; 00703 else 00704 user->talk.actual = user->talk.desired; 00705 }
static void tweak_volume | ( | struct volume * | vol, | |
enum volume_action | action | |||
) | [static] |
Definition at line 660 of file app_meetme.c.
References volume::desired, and VOL_UP.
Referenced by tweak_listen_volume(), and tweak_talk_volume().
00661 { 00662 switch (action) { 00663 case VOL_UP: 00664 switch (vol->desired) { 00665 case 5: 00666 break; 00667 case 0: 00668 vol->desired = 2; 00669 break; 00670 case -2: 00671 vol->desired = 0; 00672 break; 00673 default: 00674 vol->desired++; 00675 break; 00676 } 00677 break; 00678 case VOL_DOWN: 00679 switch (vol->desired) { 00680 case -5: 00681 break; 00682 case 2: 00683 vol->desired = 0; 00684 break; 00685 case 0: 00686 vol->desired = -2; 00687 break; 00688 default: 00689 vol->desired--; 00690 break; 00691 } 00692 } 00693 }
static int unload_module | ( | void | ) | [static] |
Definition at line 5147 of file app_meetme.c.
References ARRAY_LEN, ast_cli_unregister_multiple(), ast_devstate_prov_del(), ast_manager_unregister(), ast_module_user_hangup_all, ast_unregister_application(), cli_meetme, and sla_destroy().
05148 { 05149 int res = 0; 05150 05151 ast_cli_unregister_multiple(cli_meetme, ARRAY_LEN(cli_meetme)); 05152 res = ast_manager_unregister("MeetmeMute"); 05153 res |= ast_manager_unregister("MeetmeUnmute"); 05154 res |= ast_unregister_application(app3); 05155 res |= ast_unregister_application(app2); 05156 res |= ast_unregister_application(app); 05157 res |= ast_unregister_application(slastation_app); 05158 res |= ast_unregister_application(slatrunk_app); 05159 05160 ast_devstate_prov_del("Meetme"); 05161 ast_devstate_prov_del("SLA"); 05162 05163 ast_module_user_hangup_all(); 05164 05165 sla_destroy(); 05166 05167 return res; 05168 }
static int user_listen_voldown_cb | ( | void * | obj, | |
void * | unused, | |||
int | flags | |||
) | [static] |
Definition at line 3093 of file app_meetme.c.
References tweak_listen_volume().
Referenced by admin_exec().
03094 { 03095 struct ast_conf_user *user = obj; 03096 tweak_listen_volume(user, VOL_DOWN); 03097 return 0; 03098 }
static int user_listen_volup_cb | ( | void * | obj, | |
void * | unused, | |||
int | flags | |||
) | [static] |
Definition at line 3086 of file app_meetme.c.
References tweak_listen_volume(), and VOL_UP.
Referenced by admin_exec().
03087 { 03088 struct ast_conf_user *user = obj; 03089 tweak_listen_volume(user, VOL_UP); 03090 return 0; 03091 }
static int user_max_cmp | ( | void * | obj, | |
void * | arg, | |||
int | flags | |||
) | [static] |
Definition at line 773 of file app_meetme.c.
References ast_conf_user::user_no.
Referenced by admin_exec(), and conf_run().
00774 { 00775 struct ast_conf_user *user = obj; 00776 int *max_no = arg; 00777 00778 if (user->user_no > *max_no) { 00779 *max_no = user->user_no; 00780 } 00781 00782 return 0; 00783 }
static int user_no_cmp | ( | void * | obj, | |
void * | arg, | |||
int | flags | |||
) | [static] |
Definition at line 761 of file app_meetme.c.
References ast_conf_user::user_no.
Referenced by build_conf().
00762 { 00763 struct ast_conf_user *user = obj; 00764 int *user_no = arg; 00765 00766 if (user->user_no == *user_no) { 00767 return (CMP_MATCH | CMP_STOP); 00768 } 00769 00770 return 0; 00771 }
static int user_reset_vol_cb | ( | void * | obj, | |
void * | unused, | |||
int | flags | |||
) | [static] |
Definition at line 3114 of file app_meetme.c.
References reset_volumes().
Referenced by admin_exec().
03115 { 03116 struct ast_conf_user *user = obj; 03117 reset_volumes(user); 03118 return 0; 03119 }
static int user_set_kickme_cb | ( | void * | obj, | |
void * | unused, | |||
int | flags | |||
) | [static] |
Definition at line 3063 of file app_meetme.c.
References ADMINFLAG_KICKME, and ast_conf_user::adminflags.
Referenced by admin_exec().
03064 { 03065 struct ast_conf_user *user = obj; 03066 user->adminflags |= ADMINFLAG_KICKME; 03067 return 0; 03068 }
static int user_set_muted_cb | ( | void * | obj, | |
void * | unused, | |||
int | flags | |||
) | [static] |
Definition at line 3070 of file app_meetme.c.
References ADMINFLAG_MUTED, ast_conf_user::adminflags, and ast_conf_user::userflags.
Referenced by admin_exec().
03071 { 03072 struct ast_conf_user *user = obj; 03073 if (!(user->userflags & CONFFLAG_ADMIN)) { 03074 user->adminflags |= ADMINFLAG_MUTED; 03075 } 03076 return 0; 03077 }
static int user_set_unmuted_cb | ( | void * | obj, | |
void * | unused, | |||
int | flags | |||
) | [static] |
Definition at line 3079 of file app_meetme.c.
References ADMINFLAG_MUTED, ADMINFLAG_SELFMUTED, and ast_conf_user::adminflags.
Referenced by admin_exec().
03080 { 03081 struct ast_conf_user *user = obj; 03082 user->adminflags &= ~(ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED); 03083 return 0; 03084 }
static int user_talk_voldown_cb | ( | void * | obj, | |
void * | unused, | |||
int | flags | |||
) | [static] |
Definition at line 3107 of file app_meetme.c.
References tweak_talk_volume().
Referenced by admin_exec().
03108 { 03109 struct ast_conf_user *user = obj; 03110 tweak_talk_volume(user, VOL_DOWN); 03111 return 0; 03112 }
static int user_talk_volup_cb | ( | void * | obj, | |
void * | unused, | |||
int | flags | |||
) | [static] |
Definition at line 3100 of file app_meetme.c.
References tweak_talk_volume(), and VOL_UP.
Referenced by admin_exec().
03101 { 03102 struct ast_conf_user *user = obj; 03103 tweak_talk_volume(user, VOL_UP); 03104 return 0; 03105 }
struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT | AST_MODFLAG_BUILDSUM, .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 = "361d7bb937402d51e4658efb5b4d76e4" , .load = load_module, .unload = unload_module, .reload = reload, } [static] |
Definition at line 5204 of file app_meetme.c.
const char* app = "MeetMe" [static] |
Definition at line 210 of file app_meetme.c.
const char* app2 = "MeetMeCount" [static] |
Definition at line 211 of file app_meetme.c.
const char* app3 = "MeetMeAdmin" [static] |
Definition at line 212 of file app_meetme.c.
const struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 5204 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 566 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 573 of file app_meetme.c.
Referenced by conf_run(), and load_config_meetme().
struct ast_cli_entry cli_meetme[] [static] |
Definition at line 557 of file app_meetme.c.
Referenced by _macro_exec(), sla_handle_dial_state_event(), sla_station_exec(), and smdi_message_wait().
unsigned int conf_map[1024] = {0, } [static] |
Definition at line 384 of file app_meetme.c.
Referenced by build_conf(), conf_exec(), and dispose_conf().
const char* descrip [static] |
Definition at line 222 of file app_meetme.c.
const char* descrip2 [static] |
Definition at line 272 of file app_meetme.c.
const char* descrip3 [static] |
Definition at line 279 of file app_meetme.c.
struct { ... } event_q |
struct { ... } failed_stations |
Definition at line 562 of file app_meetme.c.
struct sla_failed_station* first |
Definition at line 561 of file app_meetme.c.
struct sla_ringing_station* first |
Definition at line 560 of file app_meetme.c.
struct sla_ringing_trunk* first |
Definition at line 559 of file app_meetme.c.
Referenced by ast_format_str_reduce(), ast_print_group(), ast_rtp_new_with_bindaddr(), check_goto(), get_goto_target(), and misdn_lib_init().
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 581 of file app_meetme.c.
Definition at line 562 of file app_meetme.c.
struct sla_failed_station* last |
Definition at line 561 of file app_meetme.c.
struct sla_ringing_station* last |
Definition at line 560 of file app_meetme.c.
struct sla_ringing_trunk* last |
Definition at line 559 of file app_meetme.c.
Referenced by add_extensions(), aji_handle_presence(), ao2_callback(), apply_outgoing(), ast_config_engine_deregister(), ast_db_freetree(), ast_db_gettree(), config_odbc(), config_pgsql(), crypto_load(), directory_exec(), do_monitor(), gtalk_free_candidates(), load_password(), next_channel(), node_lookup(), scan_thread(), and try_firmware().
Definition at line 558 of file app_meetme.c.
struct ast_app_option meetme_opts[128] = { [ 'A' ] = { .flag = CONFFLAG_MARKEDUSER }, [ 'a' ] = { .flag = CONFFLAG_ADMIN }, [ 'b' ] = { .flag = CONFFLAG_AGI }, [ 'c' ] = { .flag = CONFFLAG_ANNOUNCEUSERCOUNT }, [ 'D' ] = { .flag = CONFFLAG_DYNAMICPIN }, [ 'd' ] = { .flag = CONFFLAG_DYNAMIC }, [ 'E' ] = { .flag = CONFFLAG_EMPTYNOPIN }, [ 'e' ] = { .flag = CONFFLAG_EMPTY }, [ 'F' ] = { .flag = CONFFLAG_PASS_DTMF }, [ 'G' ] = { .flag = CONFFLAG_INTROMSG , .arg_index = OPT_ARG_INTROMSG + 1 }, [ 'i' ] = { .flag = CONFFLAG_INTROUSER }, [ 'I' ] = { .flag = CONFFLAG_INTROUSERNOREVIEW }, [ 'M' ] = { .flag = CONFFLAG_MOH }, [ 'm' ] = { .flag = CONFFLAG_STARTMUTED }, [ 'o' ] = { .flag = CONFFLAG_OPTIMIZETALKER }, [ 'P' ] = { .flag = CONFFLAG_ALWAYSPROMPT }, [ 'p' ] = { .flag = CONFFLAG_POUNDEXIT }, [ '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 }, } [static] |
char meetme_usage[] [static] |
Initial value:
"Usage: meetme (un)lock|(un)mute|kick|list [concise] <confno> <usernumber>\n" " Executes a command for the conference or on a conferee\n"
Definition at line 1116 of file app_meetme.c.
struct { ... } ringing_stations |
struct { ... } ringing_trunks |
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_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 502 of file app_meetme.c.
Referenced by destroy_station(), destroy_trunk(), and sla_destroy().
const char sla_show_stations_usage[] [static] |
Initial value:
"Usage: sla show stations\n" " This will list all stations defined in sla.conf\n"
Definition at line 1262 of file app_meetme.c.
const char sla_show_trunks_usage[] [static] |
Initial value:
"Usage: sla show trunks\n" " This will list all trunks defined in sla.conf\n"
Definition at line 1193 of file app_meetme.c.
const char* slastation_app = "SLAStation" [static] |
Definition at line 213 of file app_meetme.c.
const char* slastation_desc [static] |
Definition at line 302 of file app_meetme.c.
const char* slastation_synopsis = "Shared Line Appearance Station" [static] |
Definition at line 219 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 315 of file app_meetme.c.
const char* slatrunk_synopsis = "Shared Line Appearance Trunk" [static] |
Definition at line 220 of file app_meetme.c.
unsigned int stop |
Definition at line 563 of file app_meetme.c.
Referenced by 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.
pthread_t thread |
The SLA thread ID
Definition at line 556 of file app_meetme.c.
Referenced by __schedule_action(), __unload_module(), ast_bridge_call_thread_launch(), find_idle_thread(), handle_deferred_full_frames(), iax2_process_thread(), iax2_process_thread_cleanup(), iax2_show_threads(), insert_idle_thread(), launch_monitor_thread(), load_module(), socket_process(), socket_read(), and start_network_thread().