#include "asterisk.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <zaptel/zaptel.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/devicestate.h"
#include "asterisk/dial.h"
#include "asterisk/causes.h"
#include "enter.h"
#include "leave.h"
Go to the source code of this file.
Data Structures | |
struct | ast_conf_user |
struct | ast_conference |
The MeetMe Conference object. More... | |
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_trunk |
struct | sla_trunk_ref |
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 | 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) } |
enum | { OPT_ARG_WAITMARKED = 0, OPT_ARG_ARRAY_SIZE = 1 } |
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 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. | |
AST_APP_OPTIONS (meetme_opts, BEGIN_OPTIONS AST_APP_OPTION('A', CONFFLAG_MARKEDUSER), AST_APP_OPTION('a', CONFFLAG_ADMIN), AST_APP_OPTION('b', CONFFLAG_AGI), AST_APP_OPTION('c', CONFFLAG_ANNOUNCEUSERCOUNT), AST_APP_OPTION('D', CONFFLAG_DYNAMICPIN), AST_APP_OPTION('d', CONFFLAG_DYNAMIC), AST_APP_OPTION('E', CONFFLAG_EMPTYNOPIN), AST_APP_OPTION('e', CONFFLAG_EMPTY), AST_APP_OPTION('F', CONFFLAG_PASS_DTMF), AST_APP_OPTION('i', CONFFLAG_INTROUSER), AST_APP_OPTION('I', CONFFLAG_INTROUSERNOREVIEW), AST_APP_OPTION('M', CONFFLAG_MOH), AST_APP_OPTION('m', CONFFLAG_STARTMUTED), AST_APP_OPTION('o', CONFFLAG_OPTIMIZETALKER), AST_APP_OPTION('P', CONFFLAG_ALWAYSPROMPT), AST_APP_OPTION('p', CONFFLAG_POUNDEXIT), AST_APP_OPTION('q', CONFFLAG_QUIET), AST_APP_OPTION('r', CONFFLAG_RECORDCONF), AST_APP_OPTION('s', CONFFLAG_STARMENU), AST_APP_OPTION('T', CONFFLAG_MONITORTALKER), AST_APP_OPTION('l', CONFFLAG_MONITOR), AST_APP_OPTION('t', CONFFLAG_TALKER), AST_APP_OPTION_ARG('w', CONFFLAG_WAITMARKED, OPT_ARG_WAITMARKED), AST_APP_OPTION('X', CONFFLAG_EXIT_CONTEXT), AST_APP_OPTION('x', CONFFLAG_MARKEDEXIT), AST_APP_OPTION('1', CONFFLAG_NOONLYPERSON), END_OPTIONS) | |
static | AST_LIST_HEAD_STATIC (confs, ast_conference) |
AST_MODULE_INFO (ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT,"MeetMe conference bridge",.load=load_module,.unload=unload_module,.reload=reload,) | |
static | AST_RWLIST_HEAD_STATIC (sla_trunks, sla_trunk) |
static | AST_RWLIST_HEAD_STATIC (sla_stations, sla_station) |
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 | 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 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 int | set_listen_volume (struct ast_conf_user *user, int volume) |
static int | set_talk_volume (struct ast_conf_user *user, int volume) |
static void | sla_add_trunk_to_station (struct sla_station *station, struct ast_variable *var) |
static int | sla_build_station (struct ast_config *cfg, const char *cat) |
static int | sla_build_trunk (struct ast_config *cfg, const char *cat) |
static int | sla_calc_station_delays (unsigned int *timeout) |
Calculate the ring delay for a station. | |
static int | sla_calc_station_timeouts (unsigned int *timeout) |
Process station ring timeouts. | |
static int | sla_calc_trunk_timeouts (unsigned int *timeout) |
Process trunk ring timeouts. | |
static void | sla_change_trunk_state (const struct sla_trunk *trunk, enum sla_trunk_state state, enum sla_which_trunk_refs inactive_only, const struct sla_trunk_ref *exclude) |
static int | sla_check_device (const char *device) |
static int | sla_check_failed_station (const struct sla_station *station) |
Check to see if this station has failed to be dialed in the past minute. | |
static int | sla_check_inuse_station (const struct sla_station *station) |
Check to see if a station is in use. | |
static 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) |
Variables | |
static const char * | app = "MeetMe" |
static const char * | app2 = "MeetMeCount" |
static const char * | app3 = "MeetMeAdmin" |
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 char | meetme_usage [] |
struct { | |
ast_cond_t cond | |
ast_mutex_t lock | |
pthread_t thread | |
} | sla |
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" |
Definition in file app_meetme.c.
#define AST_FRAME_BITS 32 |
Definition at line 88 of file app_meetme.c.
Referenced by conf_free(), conf_run(), and recordthread().
#define CONF_SIZE 320 |
#define CONFIG_FILE_NAME "meetme.conf" |
Definition at line 73 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 77 of file app_meetme.c.
Referenced by load_config_meetme().
#define MAX_CONFNUM 80 |
Definition at line 314 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 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" |
Definition at line 74 of file app_meetme.c.
Referenced by sla_build_station(), sla_build_trunk(), and sla_load_config().
anonymous enum |
ADMINFLAG_MUTED | User is muted |
ADMINFLAG_SELFMUTED | User muted self |
ADMINFLAG_KICKME | User has been kicked |
Definition at line 79 of file app_meetme.c.
00079 { 00080 ADMINFLAG_MUTED = (1 << 1), /*!< User is muted */ 00081 ADMINFLAG_SELFMUTED = (1 << 2), /*!< User muted self */ 00082 ADMINFLAG_KICKME = (1 << 3) /*!< User has been kicked */ 00083 };
anonymous enum |
CONFFLAG_ADMIN | user has admin access on the conference |
CONFFLAG_MONITOR | If set the user can only receive audio from the conference |
CONFFLAG_POUNDEXIT | If set asterisk will exit conference when '#' is pressed |
CONFFLAG_STARMENU | If set asterisk will provide a menu to the user when '*' is pressed |
CONFFLAG_TALKER | If set the use can only send audio to the conference |
CONFFLAG_QUIET | If set there will be no enter or leave sounds |
CONFFLAG_ANNOUNCEUSERCOUNT | If set, when user joins the conference, they will be told the number of users that are already in |
CONFFLAG_AGI | Set to run AGI Script in Background |
CONFFLAG_MOH | Set to have music on hold when user is alone in conference |
CONFFLAG_MARKEDEXIT | If set the MeetMe will return if all marked with this flag left |
CONFFLAG_WAITMARKED | If set, the MeetMe will wait until a marked user enters |
CONFFLAG_EXIT_CONTEXT | If set, the MeetMe will exit to the specified context |
CONFFLAG_MARKEDUSER | If set, the user will be marked |
CONFFLAG_INTROUSER | If set, user will be ask record name on entry of conference |
CONFFLAG_RECORDCONF | If set, the MeetMe will be recorded |
CONFFLAG_MONITORTALKER | If set, the user will be monitored if the user is talking or not |
CONFFLAG_DYNAMIC | |
CONFFLAG_DYNAMICPIN | |
CONFFLAG_EMPTY | |
CONFFLAG_EMPTYNOPIN | |
CONFFLAG_ALWAYSPROMPT | |
CONFFLAG_OPTIMIZETALKER | If set, treats talking users as muted users |
CONFFLAG_NOONLYPERSON | If set, won't speak the extra prompt when the first person enters the conference |
CONFFLAG_INTROUSERNOREVIEW | If set, user will be asked to record name on entry of conference without review |
CONFFLAG_STARTMUTED | If set, the user will be initially self-muted |
CONFFLAG_PASS_DTMF | Pass DTMF through the conference |
CONFFLAG_SLA_STATION | This is a SLA station. (Only for use by the SLA applications.) |
CONFFLAG_SLA_TRUNK | This is a SLA trunk. (Only for use by the SLA applications.) |
Definition at line 109 of file app_meetme.c.
00109 { 00110 /*! user has admin access on the conference */ 00111 CONFFLAG_ADMIN = (1 << 0), 00112 /*! If set the user can only receive audio from the conference */ 00113 CONFFLAG_MONITOR = (1 << 1), 00114 /*! If set asterisk will exit conference when '#' is pressed */ 00115 CONFFLAG_POUNDEXIT = (1 << 2), 00116 /*! If set asterisk will provide a menu to the user when '*' is pressed */ 00117 CONFFLAG_STARMENU = (1 << 3), 00118 /*! If set the use can only send audio to the conference */ 00119 CONFFLAG_TALKER = (1 << 4), 00120 /*! If set there will be no enter or leave sounds */ 00121 CONFFLAG_QUIET = (1 << 5), 00122 /*! If set, when user joins the conference, they will be told the number 00123 * of users that are already in */ 00124 CONFFLAG_ANNOUNCEUSERCOUNT = (1 << 6), 00125 /*! Set to run AGI Script in Background */ 00126 CONFFLAG_AGI = (1 << 7), 00127 /*! Set to have music on hold when user is alone in conference */ 00128 CONFFLAG_MOH = (1 << 8), 00129 /*! If set the MeetMe will return if all marked with this flag left */ 00130 CONFFLAG_MARKEDEXIT = (1 << 9), 00131 /*! If set, the MeetMe will wait until a marked user enters */ 00132 CONFFLAG_WAITMARKED = (1 << 10), 00133 /*! If set, the MeetMe will exit to the specified context */ 00134 CONFFLAG_EXIT_CONTEXT = (1 << 11), 00135 /*! If set, the user will be marked */ 00136 CONFFLAG_MARKEDUSER = (1 << 12), 00137 /*! If set, user will be ask record name on entry of conference */ 00138 CONFFLAG_INTROUSER = (1 << 13), 00139 /*! If set, the MeetMe will be recorded */ 00140 CONFFLAG_RECORDCONF = (1<< 14), 00141 /*! If set, the user will be monitored if the user is talking or not */ 00142 CONFFLAG_MONITORTALKER = (1 << 15), 00143 CONFFLAG_DYNAMIC = (1 << 16), 00144 CONFFLAG_DYNAMICPIN = (1 << 17), 00145 CONFFLAG_EMPTY = (1 << 18), 00146 CONFFLAG_EMPTYNOPIN = (1 << 19), 00147 CONFFLAG_ALWAYSPROMPT = (1 << 20), 00148 /*! If set, treats talking users as muted users */ 00149 CONFFLAG_OPTIMIZETALKER = (1 << 21), 00150 /*! If set, won't speak the extra prompt when the first person 00151 * enters the conference */ 00152 CONFFLAG_NOONLYPERSON = (1 << 22), 00153 /*! If set, user will be asked to record name on entry of conference 00154 * without review */ 00155 CONFFLAG_INTROUSERNOREVIEW = (1 << 23), 00156 /*! If set, the user will be initially self-muted */ 00157 CONFFLAG_STARTMUTED = (1 << 24), 00158 /*! Pass DTMF through the conference */ 00159 CONFFLAG_PASS_DTMF = (1 << 25), 00160 /*! This is a SLA station. (Only for use by the SLA applications.) */ 00161 CONFFLAG_SLA_STATION = (1 << 26), 00162 /*! This is a SLA trunk. (Only for use by the SLA applications.) */ 00163 CONFFLAG_SLA_TRUNK = (1 << 27), 00164 };
anonymous enum |
Definition at line 166 of file app_meetme.c.
00166 { 00167 OPT_ARG_WAITMARKED = 0, 00168 OPT_ARG_ARRAY_SIZE = 1, 00169 };
enum entrance_sound |
enum recording_state |
Definition at line 100 of file app_meetme.c.
00100 { 00101 MEETME_RECORD_OFF, 00102 MEETME_RECORD_STARTED, 00103 MEETME_RECORD_ACTIVE, 00104 MEETME_RECORD_TERMINATE 00105 };
enum sla_event_type |
Event types that can be queued up for the SLA thread.
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 470 of file app_meetme.c.
00470 { 00471 /*! A station has put the call on hold */ 00472 SLA_EVENT_HOLD, 00473 /*! The state of a dial has changed */ 00474 SLA_EVENT_DIAL_STATE, 00475 /*! The state of a ringing trunk has changed */ 00476 SLA_EVENT_RINGING_TRUNK, 00477 };
enum sla_hold_access |
Definition at line 384 of file app_meetme.c.
00384 { 00385 /*! This means that any station can put it on hold, and any station 00386 * can retrieve the call from hold. */ 00387 SLA_HOLD_OPEN, 00388 /*! This means that only the station that put the call on hold may 00389 * retrieve it from hold. */ 00390 SLA_HOLD_PRIVATE, 00391 };
enum sla_station_hangup |
Definition at line 503 of file app_meetme.c.
00503 { 00504 SLA_STATION_HANGUP_NORMAL, 00505 SLA_STATION_HANGUP_TIMEOUT, 00506 };
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 376 of file app_meetme.c.
00376 { 00377 SLA_TRUNK_STATE_IDLE, 00378 SLA_TRUNK_STATE_RINGING, 00379 SLA_TRUNK_STATE_UP, 00380 SLA_TRUNK_STATE_ONHOLD, 00381 SLA_TRUNK_STATE_ONHOLD_BYME, 00382 };
enum sla_which_trunk_refs |
Definition at line 371 of file app_meetme.c.
00371 { 00372 ALL_TRUNK_REFS, 00373 INACTIVE_TRUNK_REFS, 00374 };
enum volume_action |
static int action_meetmemute | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 2996 of file app_meetme.c.
References meetmemute().
Referenced by load_module().
02997 { 02998 return meetmemute(s, m, 1); 02999 }
static int action_meetmeunmute | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 3001 of file app_meetme.c.
References meetmemute().
Referenced by load_module().
03002 { 03003 return meetmemute(s, m, 0); 03004 }
static int admin_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
The MeetMeadmin application.
Definition at line 2782 of file app_meetme.c.
References ADMINFLAG_KICKME, ADMINFLAG_MUTED, ADMINFLAG_SELFMUTED, ast_conf_user::adminflags, AST_APP_ARG, AST_DECLARE_APP_ARGS, AST_LIST_LAST, 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(), CONFFLAG_ADMIN, 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(), ast_conf_user::userflags, VOL_DOWN, and VOL_UP.
Referenced by load_module(), meetme_cmd(), run_station(), sla_station_exec(), and sla_stop_ringing_trunk().
02782 { 02783 char *params; 02784 struct ast_conference *cnf; 02785 struct ast_conf_user *user = NULL; 02786 struct ast_module_user *u; 02787 AST_DECLARE_APP_ARGS(args, 02788 AST_APP_ARG(confno); 02789 AST_APP_ARG(command); 02790 AST_APP_ARG(user); 02791 ); 02792 02793 if (ast_strlen_zero(data)) { 02794 ast_log(LOG_WARNING, "MeetMeAdmin requires an argument!\n"); 02795 return -1; 02796 } 02797 02798 u = ast_module_user_add(chan); 02799 02800 AST_LIST_LOCK(&confs); 02801 02802 params = ast_strdupa(data); 02803 AST_STANDARD_APP_ARGS(args, params); 02804 02805 if (!args.command) { 02806 ast_log(LOG_WARNING, "MeetmeAdmin requires a command!\n"); 02807 AST_LIST_UNLOCK(&confs); 02808 ast_module_user_remove(u); 02809 return -1; 02810 } 02811 AST_LIST_TRAVERSE(&confs, cnf, list) { 02812 if (!strcmp(cnf->confno, args.confno)) 02813 break; 02814 } 02815 02816 if (!cnf) { 02817 ast_log(LOG_WARNING, "Conference number '%s' not found!\n", args.confno); 02818 AST_LIST_UNLOCK(&confs); 02819 ast_module_user_remove(u); 02820 return 0; 02821 } 02822 02823 ast_atomic_fetchadd_int(&cnf->refcount, 1); 02824 02825 if (args.user) 02826 user = find_user(cnf, args.user); 02827 02828 switch (*args.command) { 02829 case 76: /* L: Lock */ 02830 cnf->locked = 1; 02831 break; 02832 case 108: /* l: Unlock */ 02833 cnf->locked = 0; 02834 break; 02835 case 75: /* K: kick all users */ 02836 AST_LIST_TRAVERSE(&cnf->userlist, user, list) 02837 user->adminflags |= ADMINFLAG_KICKME; 02838 break; 02839 case 101: /* e: Eject last user*/ 02840 user = AST_LIST_LAST(&cnf->userlist); 02841 if (!(user->userflags & CONFFLAG_ADMIN)) 02842 user->adminflags |= ADMINFLAG_KICKME; 02843 else 02844 ast_log(LOG_NOTICE, "Not kicking last user, is an Admin!\n"); 02845 break; 02846 case 77: /* M: Mute */ 02847 if (user) { 02848 user->adminflags |= ADMINFLAG_MUTED; 02849 } else 02850 ast_log(LOG_NOTICE, "Specified User not found!\n"); 02851 break; 02852 case 78: /* N: Mute all (non-admin) users */ 02853 AST_LIST_TRAVERSE(&cnf->userlist, user, list) { 02854 if (!(user->userflags & CONFFLAG_ADMIN)) 02855 user->adminflags |= ADMINFLAG_MUTED; 02856 } 02857 break; 02858 case 109: /* m: Unmute */ 02859 if (user) { 02860 user->adminflags &= ~(ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED); 02861 } else 02862 ast_log(LOG_NOTICE, "Specified User not found!\n"); 02863 break; 02864 case 110: /* n: Unmute all users */ 02865 AST_LIST_TRAVERSE(&cnf->userlist, user, list) 02866 user->adminflags &= ~(ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED); 02867 break; 02868 case 107: /* k: Kick user */ 02869 if (user) 02870 user->adminflags |= ADMINFLAG_KICKME; 02871 else 02872 ast_log(LOG_NOTICE, "Specified User not found!\n"); 02873 break; 02874 case 118: /* v: Lower all users listen volume */ 02875 AST_LIST_TRAVERSE(&cnf->userlist, user, list) 02876 tweak_listen_volume(user, VOL_DOWN); 02877 break; 02878 case 86: /* V: Raise all users listen volume */ 02879 AST_LIST_TRAVERSE(&cnf->userlist, user, list) 02880 tweak_listen_volume(user, VOL_UP); 02881 break; 02882 case 115: /* s: Lower all users speaking volume */ 02883 AST_LIST_TRAVERSE(&cnf->userlist, user, list) 02884 tweak_talk_volume(user, VOL_DOWN); 02885 break; 02886 case 83: /* S: Raise all users speaking volume */ 02887 AST_LIST_TRAVERSE(&cnf->userlist, user, list) 02888 tweak_talk_volume(user, VOL_UP); 02889 break; 02890 case 82: /* R: Reset all volume levels */ 02891 AST_LIST_TRAVERSE(&cnf->userlist, user, list) 02892 reset_volumes(user); 02893 break; 02894 case 114: /* r: Reset user's volume level */ 02895 if (user) 02896 reset_volumes(user); 02897 else 02898 ast_log(LOG_NOTICE, "Specified User not found!\n"); 02899 break; 02900 case 85: /* U: Raise user's listen volume */ 02901 if (user) 02902 tweak_listen_volume(user, VOL_UP); 02903 else 02904 ast_log(LOG_NOTICE, "Specified User not found!\n"); 02905 break; 02906 case 117: /* u: Lower user's listen volume */ 02907 if (user) 02908 tweak_listen_volume(user, VOL_DOWN); 02909 else 02910 ast_log(LOG_NOTICE, "Specified User not found!\n"); 02911 break; 02912 case 84: /* T: Raise user's talk volume */ 02913 if (user) 02914 tweak_talk_volume(user, VOL_UP); 02915 else 02916 ast_log(LOG_NOTICE, "Specified User not found!\n"); 02917 break; 02918 case 116: /* t: Lower user's talk volume */ 02919 if (user) 02920 tweak_talk_volume(user, VOL_DOWN); 02921 else 02922 ast_log(LOG_NOTICE, "Specified User not found!\n"); 02923 break; 02924 } 02925 02926 AST_LIST_UNLOCK(&confs); 02927 02928 dispose_conf(cnf); 02929 02930 ast_module_user_remove(u); 02931 02932 return 0; 02933 }
AST_APP_OPTIONS | ( | meetme_opts | , | |
BEGIN_OPTIONS | AST_APP_OPTION'A', CONFFLAG_MARKEDUSER, | |||
AST_APP_OPTION('a', CONFFLAG_ADMIN) | , | |||
AST_APP_OPTION('b', CONFFLAG_AGI) | , | |||
AST_APP_OPTION('c', CONFFLAG_ANNOUNCEUSERCOUNT) | , | |||
AST_APP_OPTION('D', CONFFLAG_DYNAMICPIN) | , | |||
AST_APP_OPTION('d', CONFFLAG_DYNAMIC) | , | |||
AST_APP_OPTION('E', CONFFLAG_EMPTYNOPIN) | , | |||
AST_APP_OPTION('e', CONFFLAG_EMPTY) | , | |||
AST_APP_OPTION('F', CONFFLAG_PASS_DTMF) | , | |||
AST_APP_OPTION('i', CONFFLAG_INTROUSER) | , | |||
AST_APP_OPTION('I', CONFFLAG_INTROUSERNOREVIEW) | , | |||
AST_APP_OPTION('M', CONFFLAG_MOH) | , | |||
AST_APP_OPTION('m', CONFFLAG_STARTMUTED) | , | |||
AST_APP_OPTION('o', CONFFLAG_OPTIMIZETALKER) | , | |||
AST_APP_OPTION('P', CONFFLAG_ALWAYSPROMPT) | , | |||
AST_APP_OPTION('p', CONFFLAG_POUNDEXIT) | , | |||
AST_APP_OPTION('q', CONFFLAG_QUIET) | , | |||
AST_APP_OPTION('r', CONFFLAG_RECORDCONF) | , | |||
AST_APP_OPTION('s', CONFFLAG_STARMENU) | , | |||
AST_APP_OPTION('T', CONFFLAG_MONITORTALKER) | , | |||
AST_APP_OPTION('l', CONFFLAG_MONITOR) | , | |||
AST_APP_OPTION('t', CONFFLAG_TALKER) | , | |||
AST_APP_OPTION_ARG('w', CONFFLAG_WAITMARKED, OPT_ARG_WAITMARKED) | , | |||
AST_APP_OPTION('X', CONFFLAG_EXIT_CONTEXT) | , | |||
AST_APP_OPTION('x', CONFFLAG_MARKEDEXIT) | , | |||
AST_APP_OPTION('1', CONFFLAG_NOONLYPERSON) | , | |||
END_OPTIONS | ||||
) |
static AST_LIST_HEAD_STATIC | ( | confs | , | |
ast_conference | ||||
) | [static] |
AST_MODULE_INFO | ( | ASTERISK_GPL_KEY | , | |
AST_MODFLAG_DEFAULT | , | |||
"MeetMe conference bridge" | , | |||
. | load = load_module , |
|||
. | unload = unload_module , |
|||
. | reload = reload | |||
) |
static AST_RWLIST_HEAD_STATIC | ( | sla_trunks | , | |
sla_trunk | ||||
) | [static] |
static AST_RWLIST_HEAD_STATIC | ( | sla_stations | , | |
sla_station | ||||
) | [static] |
static struct ast_conference* build_conf | ( | char * | confno, | |
char * | pin, | |||
char * | pinadmin, | |||
int | make, | |||
int | dynamic, | |||
int | refcount | |||
) | [static, read] |
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 739 of file app_meetme.c.
References ast_calloc, AST_FORMAT_SLINEAR, ast_hangup(), AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_mutex_init(), AST_PTHREADT_NULL, ast_request(), ast_set_read_format(), ast_set_write_format(), ast_verbose(), ast_conference::chan, conf_map, ast_conference::confno, ast_conference::fd, ast_channel::fds, free, ast_conference::isdynamic, ast_conference::listenlock, LOG_WARNING, option_verbose, ast_conference::pin, ast_conference::pinadmin, ast_conference::playlock, ast_conference::recordthread, ast_conference::recordthreadlock, ast_conference::refcount, ast_conference::start, VERBOSE_PREFIX_3, and ast_conference::zapconf.
Referenced by dial_trunk(), find_conf(), find_conf_realtime(), run_station(), sla_station_exec(), and sla_trunk_exec().
00740 { 00741 struct ast_conference *cnf; 00742 struct zt_confinfo ztc = { 0, }; 00743 int confno_int = 0; 00744 00745 AST_LIST_LOCK(&confs); 00746 00747 AST_LIST_TRAVERSE(&confs, cnf, list) { 00748 if (!strcmp(confno, cnf->confno)) 00749 break; 00750 } 00751 00752 if (cnf || (!make && !dynamic)) 00753 goto cnfout; 00754 00755 /* Make a new one */ 00756 if (!(cnf = ast_calloc(1, sizeof(*cnf)))) 00757 goto cnfout; 00758 00759 ast_mutex_init(&cnf->playlock); 00760 ast_mutex_init(&cnf->listenlock); 00761 cnf->recordthread = AST_PTHREADT_NULL; 00762 ast_mutex_init(&cnf->recordthreadlock); 00763 ast_copy_string(cnf->confno, confno, sizeof(cnf->confno)); 00764 ast_copy_string(cnf->pin, pin, sizeof(cnf->pin)); 00765 ast_copy_string(cnf->pinadmin, pinadmin, sizeof(cnf->pinadmin)); 00766 00767 /* Setup a new zap conference */ 00768 ztc.confno = -1; 00769 ztc.confmode = ZT_CONF_CONFANN | ZT_CONF_CONFANNMON; 00770 cnf->fd = open("/dev/zap/pseudo", O_RDWR); 00771 if (cnf->fd < 0 || ioctl(cnf->fd, ZT_SETCONF, &ztc)) { 00772 ast_log(LOG_WARNING, "Unable to open pseudo device\n"); 00773 if (cnf->fd >= 0) 00774 close(cnf->fd); 00775 free(cnf); 00776 cnf = NULL; 00777 goto cnfout; 00778 } 00779 00780 cnf->zapconf = ztc.confno; 00781 00782 /* Setup a new channel for playback of audio files */ 00783 cnf->chan = ast_request("zap", AST_FORMAT_SLINEAR, "pseudo", NULL); 00784 if (cnf->chan) { 00785 ast_set_read_format(cnf->chan, AST_FORMAT_SLINEAR); 00786 ast_set_write_format(cnf->chan, AST_FORMAT_SLINEAR); 00787 ztc.chan = 0; 00788 ztc.confno = cnf->zapconf; 00789 ztc.confmode = ZT_CONF_CONFANN | ZT_CONF_CONFANNMON; 00790 if (ioctl(cnf->chan->fds[0], ZT_SETCONF, &ztc)) { 00791 ast_log(LOG_WARNING, "Error setting conference\n"); 00792 if (cnf->chan) 00793 ast_hangup(cnf->chan); 00794 else 00795 close(cnf->fd); 00796 free(cnf); 00797 cnf = NULL; 00798 goto cnfout; 00799 } 00800 } 00801 00802 /* Fill the conference struct */ 00803 cnf->start = time(NULL); 00804 cnf->isdynamic = dynamic ? 1 : 0; 00805 if (option_verbose > 2) 00806 ast_verbose(VERBOSE_PREFIX_3 "Created MeetMe conference %d for conference '%s'\n", cnf->zapconf, cnf->confno); 00807 AST_LIST_INSERT_HEAD(&confs, cnf, list); 00808 00809 /* Reserve conference number in map */ 00810 if ((sscanf(cnf->confno, "%d", &confno_int) == 1) && (confno_int >= 0 && confno_int < 1024)) 00811 conf_map[confno_int] = 1; 00812 00813 cnfout: 00814 if (cnf) 00815 ast_atomic_fetchadd_int(&cnf->refcount, refcount); 00816 00817 AST_LIST_UNLOCK(&confs); 00818 00819 return cnf; 00820 }
static int careful_write | ( | int | fd, | |
unsigned char * | data, | |||
int | len, | |||
int | block | |||
) | [static] |
Definition at line 574 of file app_meetme.c.
References ast_log(), errno, and LOG_WARNING.
Referenced by conf_play(), and conf_run().
00575 { 00576 int res; 00577 int x; 00578 00579 while (len) { 00580 if (block) { 00581 x = ZT_IOMUX_WRITE | ZT_IOMUX_SIGEVENT; 00582 res = ioctl(fd, ZT_IOMUX, &x); 00583 } else 00584 res = 0; 00585 if (res >= 0) 00586 res = write(fd, data, len); 00587 if (res < 1) { 00588 if (errno != EAGAIN) { 00589 ast_log(LOG_WARNING, "Failed to write audio data to conference: %s\n", strerror(errno)); 00590 return -1; 00591 } else 00592 return 0; 00593 } 00594 len -= res; 00595 data += res; 00596 } 00597 00598 return 0; 00599 }
static char* complete_meetmecmd | ( | const char * | line, | |
const char * | word, | |||
int | pos, | |||
int | state | |||
) | [static] |
Definition at line 970 of file app_meetme.c.
References ast_cli_complete(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_strdup, ast_strdupa, ast_conference::confno, len, strdup, strsep(), and ast_conf_user::user_no.
00971 { 00972 static char *cmds[] = {"lock", "unlock", "mute", "unmute", "kick", "list", NULL}; 00973 00974 int len = strlen(word); 00975 int which = 0; 00976 struct ast_conference *cnf = NULL; 00977 struct ast_conf_user *usr = NULL; 00978 char *confno = NULL; 00979 char usrno[50] = ""; 00980 char *myline, *ret = NULL; 00981 00982 if (pos == 1) { /* Command */ 00983 return ast_cli_complete(word, cmds, state); 00984 } else if (pos == 2) { /* Conference Number */ 00985 AST_LIST_LOCK(&confs); 00986 AST_LIST_TRAVERSE(&confs, cnf, list) { 00987 if (!strncasecmp(word, cnf->confno, len) && ++which > state) { 00988 ret = cnf->confno; 00989 break; 00990 } 00991 } 00992 ret = ast_strdup(ret); /* dup before releasing the lock */ 00993 AST_LIST_UNLOCK(&confs); 00994 return ret; 00995 } else if (pos == 3) { 00996 /* User Number || Conf Command option*/ 00997 if (strstr(line, "mute") || strstr(line, "kick")) { 00998 if (state == 0 && (strstr(line, "kick") || strstr(line,"mute")) && !strncasecmp(word, "all", len)) 00999 return strdup("all"); 01000 which++; 01001 AST_LIST_LOCK(&confs); 01002 01003 /* TODO: Find the conf number from the cmdline (ignore spaces) <- test this and make it fail-safe! */ 01004 myline = ast_strdupa(line); 01005 if (strsep(&myline, " ") && strsep(&myline, " ") && !confno) { 01006 while((confno = strsep(&myline, " ")) && (strcmp(confno, " ") == 0)) 01007 ; 01008 } 01009 01010 AST_LIST_TRAVERSE(&confs, cnf, list) { 01011 if (!strcmp(confno, cnf->confno)) 01012 break; 01013 } 01014 01015 if (cnf) { 01016 /* Search for the user */ 01017 AST_LIST_TRAVERSE(&cnf->userlist, usr, list) { 01018 snprintf(usrno, sizeof(usrno), "%d", usr->user_no); 01019 if (!strncasecmp(word, usrno, len) && ++which > state) 01020 break; 01021 } 01022 } 01023 AST_LIST_UNLOCK(&confs); 01024 return usr ? strdup(usrno) : NULL; 01025 } else if ( strstr(line, "list") && ( 0 == state ) ) 01026 return strdup("concise"); 01027 } 01028 01029 return NULL; 01030 }
static int conf_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
The meetme() application.
Definition at line 2519 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_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_ADMIN, 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, LOG_ERROR, LOG_WARNING, MAX_CONFNUM, MAX_PIN, ast_variable::name, ast_variable::next, OPT_ARG_ARRAY_SIZE, ast_conference::pin, ast_conference::pinadmin, strsep(), ast_variable::value, and var.
Referenced by load_module().
02520 { 02521 int res=-1; 02522 struct ast_module_user *u; 02523 char confno[MAX_CONFNUM] = ""; 02524 int allowretry = 0; 02525 int retrycnt = 0; 02526 struct ast_conference *cnf = NULL; 02527 struct ast_flags confflags = {0}; 02528 int dynamic = 0; 02529 int empty = 0, empty_no_pin = 0; 02530 int always_prompt = 0; 02531 char *notdata, *info, the_pin[MAX_PIN] = ""; 02532 AST_DECLARE_APP_ARGS(args, 02533 AST_APP_ARG(confno); 02534 AST_APP_ARG(options); 02535 AST_APP_ARG(pin); 02536 ); 02537 char *optargs[OPT_ARG_ARRAY_SIZE] = { NULL, }; 02538 02539 u = ast_module_user_add(chan); 02540 02541 if (ast_strlen_zero(data)) { 02542 allowretry = 1; 02543 notdata = ""; 02544 } else { 02545 notdata = data; 02546 } 02547 02548 if (chan->_state != AST_STATE_UP) 02549 ast_answer(chan); 02550 02551 info = ast_strdupa(notdata); 02552 02553 AST_STANDARD_APP_ARGS(args, info); 02554 02555 if (args.confno) { 02556 ast_copy_string(confno, args.confno, sizeof(confno)); 02557 if (ast_strlen_zero(confno)) { 02558 allowretry = 1; 02559 } 02560 } 02561 02562 if (args.pin) 02563 ast_copy_string(the_pin, args.pin, sizeof(the_pin)); 02564 02565 if (args.options) { 02566 ast_app_parse_options(meetme_opts, &confflags, optargs, args.options); 02567 dynamic = ast_test_flag(&confflags, CONFFLAG_DYNAMIC | CONFFLAG_DYNAMICPIN); 02568 if (ast_test_flag(&confflags, CONFFLAG_DYNAMICPIN) && !args.pin) 02569 strcpy(the_pin, "q"); 02570 02571 empty = ast_test_flag(&confflags, CONFFLAG_EMPTY | CONFFLAG_EMPTYNOPIN); 02572 empty_no_pin = ast_test_flag(&confflags, CONFFLAG_EMPTYNOPIN); 02573 always_prompt = ast_test_flag(&confflags, CONFFLAG_ALWAYSPROMPT); 02574 } 02575 02576 do { 02577 if (retrycnt > 3) 02578 allowretry = 0; 02579 if (empty) { 02580 int i; 02581 struct ast_config *cfg; 02582 struct ast_variable *var; 02583 int confno_int; 02584 02585 /* We only need to load the config file for static and empty_no_pin (otherwise we don't care) */ 02586 if ((empty_no_pin) || (!dynamic)) { 02587 cfg = ast_config_load(CONFIG_FILE_NAME); 02588 if (cfg) { 02589 var = ast_variable_browse(cfg, "rooms"); 02590 while (var) { 02591 if (!strcasecmp(var->name, "conf")) { 02592 char *stringp = ast_strdupa(var->value); 02593 if (stringp) { 02594 char *confno_tmp = strsep(&stringp, "|,"); 02595 int found = 0; 02596 if (!dynamic) { 02597 /* For static: run through the list and see if this conference is empty */ 02598 AST_LIST_LOCK(&confs); 02599 AST_LIST_TRAVERSE(&confs, cnf, list) { 02600 if (!strcmp(confno_tmp, cnf->confno)) { 02601 /* The conference exists, therefore it's not empty */ 02602 found = 1; 02603 break; 02604 } 02605 } 02606 AST_LIST_UNLOCK(&confs); 02607 if (!found) { 02608 /* At this point, we have a confno_tmp (static conference) that is empty */ 02609 if ((empty_no_pin && ast_strlen_zero(stringp)) || (!empty_no_pin)) { 02610 /* Case 1: empty_no_pin and pin is nonexistent (NULL) 02611 * Case 2: empty_no_pin and pin is blank (but not NULL) 02612 * Case 3: not empty_no_pin 02613 */ 02614 ast_copy_string(confno, confno_tmp, sizeof(confno)); 02615 break; 02616 /* XXX the map is not complete (but we do have a confno) */ 02617 } 02618 } 02619 } 02620 } 02621 } 02622 var = var->next; 02623 } 02624 ast_config_destroy(cfg); 02625 } 02626 } 02627 02628 /* Select first conference number not in use */ 02629 if (ast_strlen_zero(confno) && dynamic) { 02630 AST_LIST_LOCK(&confs); 02631 for (i = 0; i < sizeof(conf_map) / sizeof(conf_map[0]); i++) { 02632 if (!conf_map[i]) { 02633 snprintf(confno, sizeof(confno), "%d", i); 02634 conf_map[i] = 1; 02635 break; 02636 } 02637 } 02638 AST_LIST_UNLOCK(&confs); 02639 } 02640 02641 /* Not found? */ 02642 if (ast_strlen_zero(confno)) { 02643 res = ast_streamfile(chan, "conf-noempty", chan->language); 02644 if (!res) 02645 ast_waitstream(chan, ""); 02646 } else { 02647 if (sscanf(confno, "%d", &confno_int) == 1) { 02648 res = ast_streamfile(chan, "conf-enteringno", chan->language); 02649 if (!res) { 02650 ast_waitstream(chan, ""); 02651 res = ast_say_digits(chan, confno_int, "", chan->language); 02652 } 02653 } else { 02654 ast_log(LOG_ERROR, "Could not scan confno '%s'\n", confno); 02655 } 02656 } 02657 } 02658 02659 while (allowretry && (ast_strlen_zero(confno)) && (++retrycnt < 4)) { 02660 /* Prompt user for conference number */ 02661 res = ast_app_getdata(chan, "conf-getconfno", confno, sizeof(confno) - 1, 0); 02662 if (res < 0) { 02663 /* Don't try to validate when we catch an error */ 02664 confno[0] = '\0'; 02665 allowretry = 0; 02666 break; 02667 } 02668 } 02669 if (!ast_strlen_zero(confno)) { 02670 /* Check the validity of the conference */ 02671 cnf = find_conf(chan, confno, 1, dynamic, the_pin, 02672 sizeof(the_pin), 1, &confflags); 02673 if (!cnf) { 02674 cnf = find_conf_realtime(chan, confno, 1, dynamic, 02675 the_pin, sizeof(the_pin), 1, &confflags); 02676 } 02677 02678 if (!cnf) { 02679 res = ast_streamfile(chan, "conf-invalid", chan->language); 02680 if (!res) 02681 ast_waitstream(chan, ""); 02682 res = -1; 02683 if (allowretry) 02684 confno[0] = '\0'; 02685 } else { 02686 if ((!ast_strlen_zero(cnf->pin) && 02687 !ast_test_flag(&confflags, CONFFLAG_ADMIN)) || 02688 (!ast_strlen_zero(cnf->pinadmin) && 02689 ast_test_flag(&confflags, CONFFLAG_ADMIN))) { 02690 char pin[MAX_PIN] = ""; 02691 int j; 02692 02693 /* Allow the pin to be retried up to 3 times */ 02694 for (j = 0; j < 3; j++) { 02695 if (*the_pin && (always_prompt == 0)) { 02696 ast_copy_string(pin, the_pin, sizeof(pin)); 02697 res = 0; 02698 } else { 02699 /* Prompt user for pin if pin is required */ 02700 res = ast_app_getdata(chan, "conf-getpin", pin + strlen(pin), sizeof(pin) - 1 - strlen(pin), 0); 02701 } 02702 if (res >= 0) { 02703 if (!strcasecmp(pin, cnf->pin) || 02704 (!ast_strlen_zero(cnf->pinadmin) && 02705 !strcasecmp(pin, cnf->pinadmin))) { 02706 /* Pin correct */ 02707 allowretry = 0; 02708 if (!ast_strlen_zero(cnf->pinadmin) && !strcasecmp(pin, cnf->pinadmin)) 02709 ast_set_flag(&confflags, CONFFLAG_ADMIN); 02710 /* Run the conference */ 02711 res = conf_run(chan, cnf, confflags.flags, optargs); 02712 break; 02713 } else { 02714 /* Pin invalid */ 02715 if (!ast_streamfile(chan, "conf-invalidpin", chan->language)) { 02716 res = ast_waitstream(chan, AST_DIGIT_ANY); 02717 ast_stopstream(chan); 02718 } 02719 else { 02720 ast_log(LOG_WARNING, "Couldn't play invalid pin msg!\n"); 02721 break; 02722 } 02723 if (res < 0) 02724 break; 02725 pin[0] = res; 02726 pin[1] = '\0'; 02727 res = -1; 02728 if (allowretry) 02729 confno[0] = '\0'; 02730 } 02731 } else { 02732 /* failed when getting the pin */ 02733 res = -1; 02734 allowretry = 0; 02735 /* see if we need to get rid of the conference */ 02736 break; 02737 } 02738 02739 /* Don't retry pin with a static pin */ 02740 if (*the_pin && (always_prompt==0)) { 02741 break; 02742 } 02743 } 02744 } else { 02745 /* No pin required */ 02746 allowretry = 0; 02747 02748 /* Run the conference */ 02749 res = conf_run(chan, cnf, confflags.flags, optargs); 02750 } 02751 dispose_conf(cnf); 02752 cnf = NULL; 02753 } 02754 } 02755 } while (allowretry); 02756 02757 if (cnf) 02758 dispose_conf(cnf); 02759 02760 ast_module_user_remove(u); 02761 02762 return res; 02763 }
static void conf_flush | ( | int | fd, | |
struct ast_channel * | chan | |||
) | [static] |
Definition at line 1196 of file app_meetme.c.
References ast_frfree, ast_log(), ast_read(), ast_waitfor(), f, and LOG_WARNING.
Referenced by conf_run().
01197 { 01198 int x; 01199 01200 /* read any frames that may be waiting on the channel 01201 and throw them away 01202 */ 01203 if (chan) { 01204 struct ast_frame *f; 01205 01206 /* when no frames are available, this will wait 01207 for 1 millisecond maximum 01208 */ 01209 while (ast_waitfor(chan, 1)) { 01210 f = ast_read(chan); 01211 if (f) 01212 ast_frfree(f); 01213 else /* channel was hung up or something else happened */ 01214 break; 01215 } 01216 } 01217 01218 /* flush any data sitting in the pseudo channel */ 01219 x = ZT_FLUSH_ALL; 01220 if (ioctl(fd, ZT_FLUSH, &x)) 01221 ast_log(LOG_WARNING, "Error flushing channel\n"); 01222 01223 }
static int conf_free | ( | struct ast_conference * | conf | ) | [static] |
Definition at line 1227 of file app_meetme.c.
References AST_FRAME_BITS, ast_frfree, ast_hangup(), AST_LIST_LOCK, AST_LIST_REMOVE, AST_LIST_UNLOCK, ast_mutex_destroy(), ast_translator_free_path(), ast_conference::chan, ast_conference::fd, free, ast_conference::lchan, ast_conference::listenlock, MEETME_RECORD_ACTIVE, MEETME_RECORD_OFF, MEETME_RECORD_TERMINATE, ast_conference::origframe, ast_conference::playlock, ast_conference::recordthreadlock, ast_conference::transframe, and ast_conference::transpath.
Referenced by dispose_conf().
01228 { 01229 int x; 01230 01231 AST_LIST_REMOVE(&confs, conf, list); 01232 01233 if (conf->recording == MEETME_RECORD_ACTIVE) { 01234 conf->recording = MEETME_RECORD_TERMINATE; 01235 AST_LIST_UNLOCK(&confs); 01236 while (1) { 01237 usleep(1); 01238 AST_LIST_LOCK(&confs); 01239 if (conf->recording == MEETME_RECORD_OFF) 01240 break; 01241 AST_LIST_UNLOCK(&confs); 01242 } 01243 } 01244 01245 for (x=0;x<AST_FRAME_BITS;x++) { 01246 if (conf->transframe[x]) 01247 ast_frfree(conf->transframe[x]); 01248 if (conf->transpath[x]) 01249 ast_translator_free_path(conf->transpath[x]); 01250 } 01251 if (conf->origframe) 01252 ast_frfree(conf->origframe); 01253 if (conf->lchan) 01254 ast_hangup(conf->lchan); 01255 if (conf->chan) 01256 ast_hangup(conf->chan); 01257 if (conf->fd >= 0) 01258 close(conf->fd); 01259 01260 ast_mutex_destroy(&conf->playlock); 01261 ast_mutex_destroy(&conf->listenlock); 01262 ast_mutex_destroy(&conf->recordthreadlock); 01263 free(conf); 01264 01265 return 0; 01266 }
static void conf_play | ( | struct ast_channel * | chan, | |
struct ast_conference * | conf, | |||
enum entrance_sound | sound | |||
) | [static] |
Definition at line 692 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, LEAVE, and len.
Referenced by conf_run().
00693 { 00694 unsigned char *data; 00695 int len; 00696 int res = -1; 00697 00698 if (!chan->_softhangup) 00699 res = ast_autoservice_start(chan); 00700 00701 AST_LIST_LOCK(&confs); 00702 00703 switch(sound) { 00704 case ENTER: 00705 data = enter; 00706 len = sizeof(enter); 00707 break; 00708 case LEAVE: 00709 data = leave; 00710 len = sizeof(leave); 00711 break; 00712 default: 00713 data = NULL; 00714 len = 0; 00715 } 00716 if (data) { 00717 careful_write(conf->fd, data, len, 1); 00718 } 00719 00720 AST_LIST_UNLOCK(&confs); 00721 00722 if (!res) 00723 ast_autoservice_stop(chan); 00724 }
static void conf_queue_dtmf | ( | const struct ast_conference * | conf, | |
const struct ast_conf_user * | sender, | |||
struct ast_frame * | f | |||
) | [static] |
Definition at line 1268 of file app_meetme.c.
References AST_LIST_TRAVERSE, ast_log(), ast_write(), ast_conf_user::chan, and LOG_WARNING.
Referenced by conf_run().
01270 { 01271 struct ast_conf_user *user; 01272 01273 AST_LIST_TRAVERSE(&conf->userlist, user, list) { 01274 if (user == sender) 01275 continue; 01276 if (ast_write(user->chan, f) < 0) 01277 ast_log(LOG_WARNING, "Error writing frame to channel %s\n", user->chan->name); 01278 } 01279 }
static int conf_run | ( | struct ast_channel * | chan, | |
struct ast_conference * | conf, | |||
int | confflags, | |||
char * | optargs[] | |||
) | [static] |
Definition at line 1368 of file app_meetme.c.
References volume::actual, ADMINFLAG_KICKME, ADMINFLAG_MUTED, ADMINFLAG_SELFMUTED, ast_conf_user::adminflags, ast_calloc, ast_channel_setoption(), ast_check_hangup(), ast_config_AST_SPOOL_DIR, AST_CONTROL_HOLD, ast_device_state_changed(), AST_DIGIT_ANY, ast_dsp_free(), ast_dsp_new(), ast_dsp_silence(), ast_filedelete(), ast_fileexists(), AST_FORMAT_SLINEAR, ast_frame_adjust_volume(), AST_FRAME_BITS, AST_FRAME_CONTROL, AST_FRAME_DTMF, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, AST_FRAME_NULL, AST_FRAME_VOICE, ast_frfree, AST_FRIENDLY_OFFSET, ast_goto_if_exists(), ast_hangup(), ast_indicate(), AST_LIST_EMPTY, AST_LIST_INSERT_TAIL, AST_LIST_LAST, AST_LIST_LOCK, AST_LIST_REMOVE, AST_LIST_UNLOCK, ast_log(), AST_MAX_CONTEXT, AST_MAX_EXTENSION, ast_moh_start(), ast_moh_stop(), 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_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, careful_write(), ast_conference::chan, ast_conf_user::chan, ast_channel::cid, ast_callerid::cid_name, ast_callerid::cid_num, conf_flush(), conf_play(), conf_queue_dtmf(), CONF_SIZE, CONFFLAG_ADMIN, CONFFLAG_AGI, CONFFLAG_ANNOUNCEUSERCOUNT, CONFFLAG_EXIT_CONTEXT, CONFFLAG_INTROUSER, CONFFLAG_INTROUSERNOREVIEW, CONFFLAG_MARKEDEXIT, CONFFLAG_MARKEDUSER, CONFFLAG_MOH, CONFFLAG_MONITOR, CONFFLAG_MONITORTALKER, 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, ast_frame::data, ast_frame::datalen, volume::desired, ENTER, errno, EVENT_FLAG_CALL, exitcontext, f, ast_conference::fd, ast_channel::fds, ast_frame::frametype, free, ast_conf_user::jointime, ast_conference::lchan, LEAVE, ast_conf_user::listen, ast_conference::listenlock, ast_conference::locked, LOG_DEBUG, LOG_NOTICE, LOG_WARNING, ast_channel::macrocontext, manager_event(), ast_conference::markedusers, MEETME_DELAYDETECTENDTALK, MEETME_DELAYDETECTTALK, ast_conf_user::namerecloc, ast_frame::offset, OPT_ARG_WAITMARKED, option_debug, ast_conference::origframe, pbx_builtin_getvar_helper(), pbx_builtin_setvar_helper(), pbx_exec(), pbx_findapp(), ast_conference::playlock, ast_channel::rawwriteformat, ast_conference::recordingfilename, ast_conference::recordingformat, ast_conference::recordthread, ast_conference::recordthreadlock, reset_volumes(), s, S_OR, ast_frame::samples, set_talk_volume(), SLA_EVENT_HOLD, sla_queue_event_conf(), ast_channel::spies, ast_frame::subclass, ast_conf_user::talk, ast_conf_user::talking, ast_channel::tech, ast_conference::transframe, ast_conference::transpath, tweak_listen_volume(), tweak_talk_volume(), ast_channel_tech::type, ast_conf_user::user_no, ast_conf_user::userflags, ast_conference::users, VERBOSE_PREFIX_4, VOL_DOWN, VOL_UP, ast_conf_user::zapchannel, and ast_conference::zapconf.
Referenced by conf_exec(), dial_trunk(), run_station(), sla_station_exec(), and sla_trunk_exec().
01369 { 01370 struct ast_conf_user *user = NULL; 01371 struct ast_conf_user *usr = NULL; 01372 int fd; 01373 struct zt_confinfo ztc, ztc_empty; 01374 struct ast_frame *f; 01375 struct ast_channel *c; 01376 struct ast_frame fr; 01377 int outfd; 01378 int ms; 01379 int nfds; 01380 int res; 01381 int flags; 01382 int retryzap; 01383 int origfd; 01384 int musiconhold = 0; 01385 int firstpass = 0; 01386 int lastmarked = 0; 01387 int currentmarked = 0; 01388 int ret = -1; 01389 int x; 01390 int menu_active = 0; 01391 int using_pseudo = 0; 01392 int duration=20; 01393 int hr, min, sec; 01394 int sent_event = 0; 01395 time_t now; 01396 struct ast_dsp *dsp=NULL; 01397 struct ast_app *app; 01398 const char *agifile; 01399 const char *agifiledefault = "conf-background.agi"; 01400 char meetmesecs[30] = ""; 01401 char exitcontext[AST_MAX_CONTEXT] = ""; 01402 char recordingtmp[AST_MAX_EXTENSION] = ""; 01403 char members[10] = ""; 01404 int dtmf, opt_waitmarked_timeout = 0; 01405 time_t timeout = 0; 01406 int dyna_buff = CONF_SIZE; 01407 ZT_BUFFERINFO bi; 01408 char __buf[ZT_MAX_BUF_SPACE / ZT_DEFAULT_NUM_BUFS + AST_FRIENDLY_OFFSET]; 01409 char *buf = __buf + AST_FRIENDLY_OFFSET; 01410 int setusercount = 0; 01411 01412 if (!(user = ast_calloc(1, sizeof(*user)))) 01413 return ret; 01414 01415 /* Possible timeout waiting for marked user */ 01416 if ((confflags & CONFFLAG_WAITMARKED) && 01417 !ast_strlen_zero(optargs[OPT_ARG_WAITMARKED]) && 01418 (sscanf(optargs[OPT_ARG_WAITMARKED], "%d", &opt_waitmarked_timeout) == 1) && 01419 (opt_waitmarked_timeout > 0)) { 01420 timeout = time(NULL) + opt_waitmarked_timeout; 01421 } 01422 01423 if (confflags & CONFFLAG_RECORDCONF) { 01424 if (!conf->recordingfilename) { 01425 conf->recordingfilename = pbx_builtin_getvar_helper(chan, "MEETME_RECORDINGFILE"); 01426 if (!conf->recordingfilename) { 01427 snprintf(recordingtmp, sizeof(recordingtmp), "meetme-conf-rec-%s-%s", conf->confno, chan->uniqueid); 01428 conf->recordingfilename = ast_strdupa(recordingtmp); 01429 } 01430 conf->recordingformat = pbx_builtin_getvar_helper(chan, "MEETME_RECORDINGFORMAT"); 01431 if (!conf->recordingformat) { 01432 snprintf(recordingtmp, sizeof(recordingtmp), "wav"); 01433 conf->recordingformat = ast_strdupa(recordingtmp); 01434 } 01435 ast_verbose(VERBOSE_PREFIX_4 "Starting recording of MeetMe Conference %s into file %s.%s.\n", 01436 conf->confno, conf->recordingfilename, conf->recordingformat); 01437 } 01438 } 01439 01440 ast_mutex_lock(&conf->recordthreadlock); 01441 if ((conf->recordthread == AST_PTHREADT_NULL) && (confflags & CONFFLAG_RECORDCONF) && ((conf->lchan = ast_request("zap", AST_FORMAT_SLINEAR, "pseudo", NULL)))) { 01442 ast_set_read_format(conf->lchan, AST_FORMAT_SLINEAR); 01443 ast_set_write_format(conf->lchan, AST_FORMAT_SLINEAR); 01444 ztc.chan = 0; 01445 ztc.confno = conf->zapconf; 01446 ztc.confmode = ZT_CONF_CONFANN | ZT_CONF_CONFANNMON; 01447 if (ioctl(conf->lchan->fds[0], ZT_SETCONF, &ztc)) { 01448 ast_log(LOG_WARNING, "Error starting listen channel\n"); 01449 ast_hangup(conf->lchan); 01450 conf->lchan = NULL; 01451 } else { 01452 pthread_attr_init(&conf->attr); 01453 pthread_attr_setdetachstate(&conf->attr, PTHREAD_CREATE_DETACHED); 01454 ast_pthread_create_background(&conf->recordthread, &conf->attr, recordthread, conf); 01455 pthread_attr_destroy(&conf->attr); 01456 } 01457 } 01458 ast_mutex_unlock(&conf->recordthreadlock); 01459 01460 time(&user->jointime); 01461 01462 if (conf->locked && (!(confflags & CONFFLAG_ADMIN))) { 01463 /* Sorry, but this confernce is locked! */ 01464 if (!ast_streamfile(chan, "conf-locked", chan->language)) 01465 ast_waitstream(chan, ""); 01466 goto outrun; 01467 } 01468 01469 ast_mutex_lock(&conf->playlock); 01470 01471 if (AST_LIST_EMPTY(&conf->userlist)) 01472 user->user_no = 1; 01473 else 01474 user->user_no = AST_LIST_LAST(&conf->userlist)->user_no + 1; 01475 01476 AST_LIST_INSERT_TAIL(&conf->userlist, user, list); 01477 01478 user->chan = chan; 01479 user->userflags = confflags; 01480 user->adminflags = (confflags & CONFFLAG_STARTMUTED) ? ADMINFLAG_SELFMUTED : 0; 01481 user->talking = -1; 01482 01483 ast_mutex_unlock(&conf->playlock); 01484 01485 if (!(confflags & CONFFLAG_QUIET) && ((confflags & CONFFLAG_INTROUSER) || (confflags & CONFFLAG_INTROUSERNOREVIEW))) { 01486 snprintf(user->namerecloc, sizeof(user->namerecloc), 01487 "%s/meetme/meetme-username-%s-%d", ast_config_AST_SPOOL_DIR, 01488 conf->confno, user->user_no); 01489 if (confflags & CONFFLAG_INTROUSERNOREVIEW) 01490 res = ast_play_and_record(chan, "vm-rec-name", user->namerecloc, 10, "sln", &duration, 128, 0, NULL); 01491 else 01492 res = ast_record_review(chan, "vm-rec-name", user->namerecloc, 10, "sln", &duration, NULL); 01493 if (res == -1) 01494 goto outrun; 01495 } 01496 01497 ast_mutex_lock(&conf->playlock); 01498 01499 if (confflags & CONFFLAG_MARKEDUSER) 01500 conf->markedusers++; 01501 conf->users++; 01502 /* Update table */ 01503 snprintf(members, sizeof(members), "%d", conf->users); 01504 ast_update_realtime("meetme", "confno", conf->confno, "members", members , NULL); 01505 setusercount = 1; 01506 01507 /* This device changed state now - if this is the first user */ 01508 if (conf->users == 1) 01509 ast_device_state_changed("meetme:%s", conf->confno); 01510 01511 ast_mutex_unlock(&conf->playlock); 01512 01513 if (confflags & CONFFLAG_EXIT_CONTEXT) { 01514 if ((agifile = pbx_builtin_getvar_helper(chan, "MEETME_EXIT_CONTEXT"))) 01515 ast_copy_string(exitcontext, agifile, sizeof(exitcontext)); 01516 else if (!ast_strlen_zero(chan->macrocontext)) 01517 ast_copy_string(exitcontext, chan->macrocontext, sizeof(exitcontext)); 01518 else 01519 ast_copy_string(exitcontext, chan->context, sizeof(exitcontext)); 01520 } 01521 01522 if ( !(confflags & (CONFFLAG_QUIET | CONFFLAG_NOONLYPERSON)) ) { 01523 if (conf->users == 1 && !(confflags & CONFFLAG_WAITMARKED)) 01524 if (!ast_streamfile(chan, "conf-onlyperson", chan->language)) 01525 ast_waitstream(chan, ""); 01526 if ((confflags & CONFFLAG_WAITMARKED) && conf->markedusers == 0) 01527 if (!ast_streamfile(chan, "conf-waitforleader", chan->language)) 01528 ast_waitstream(chan, ""); 01529 } 01530 01531 if (!(confflags & CONFFLAG_QUIET) && (confflags & CONFFLAG_ANNOUNCEUSERCOUNT) && conf->users > 1) { 01532 int keepplaying = 1; 01533 01534 if (conf->users == 2) { 01535 if (!ast_streamfile(chan,"conf-onlyone",chan->language)) { 01536 res = ast_waitstream(chan, AST_DIGIT_ANY); 01537 ast_stopstream(chan); 01538 if (res > 0) 01539 keepplaying=0; 01540 else if (res == -1) 01541 goto outrun; 01542 } 01543 } else { 01544 if (!ast_streamfile(chan, "conf-thereare", chan->language)) { 01545 res = ast_waitstream(chan, AST_DIGIT_ANY); 01546 ast_stopstream(chan); 01547 if (res > 0) 01548 keepplaying=0; 01549 else if (res == -1) 01550 goto outrun; 01551 } 01552 if (keepplaying) { 01553 res = ast_say_number(chan, conf->users - 1, AST_DIGIT_ANY, chan->language, (char *) NULL); 01554 if (res > 0) 01555 keepplaying=0; 01556 else if (res == -1) 01557 goto outrun; 01558 } 01559 if (keepplaying && !ast_streamfile(chan, "conf-otherinparty", chan->language)) { 01560 res = ast_waitstream(chan, AST_DIGIT_ANY); 01561 ast_stopstream(chan); 01562 if (res > 0) 01563 keepplaying=0; 01564 else if (res == -1) 01565 goto outrun; 01566 } 01567 } 01568 } 01569 01570 ast_indicate(chan, -1); 01571 01572 if (ast_set_write_format(chan, AST_FORMAT_SLINEAR) < 0) { 01573 ast_log(LOG_WARNING, "Unable to set '%s' to write linear mode\n", chan->name); 01574 goto outrun; 01575 } 01576 01577 if (ast_set_read_format(chan, AST_FORMAT_SLINEAR) < 0) { 01578 ast_log(LOG_WARNING, "Unable to set '%s' to read linear mode\n", chan->name); 01579 goto outrun; 01580 } 01581 01582 retryzap = (strcasecmp(chan->tech->type, "Zap") || chan->spies ? 1 : 0); 01583 user->zapchannel = !retryzap; 01584 01585 zapretry: 01586 origfd = chan->fds[0]; 01587 if (retryzap) { 01588 fd = open("/dev/zap/pseudo", O_RDWR); 01589 if (fd < 0) { 01590 ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno)); 01591 goto outrun; 01592 } 01593 using_pseudo = 1; 01594 /* Make non-blocking */ 01595 flags = fcntl(fd, F_GETFL); 01596 if (flags < 0) { 01597 ast_log(LOG_WARNING, "Unable to get flags: %s\n", strerror(errno)); 01598 close(fd); 01599 goto outrun; 01600 } 01601 if (fcntl(fd, F_SETFL, flags | O_NONBLOCK)) { 01602 ast_log(LOG_WARNING, "Unable to set flags: %s\n", strerror(errno)); 01603 close(fd); 01604 goto outrun; 01605 } 01606 /* Setup buffering information */ 01607 memset(&bi, 0, sizeof(bi)); 01608 bi.bufsize = dyna_buff / 2; 01609 bi.txbufpolicy = ZT_POLICY_IMMEDIATE; 01610 bi.rxbufpolicy = ZT_POLICY_IMMEDIATE; 01611 bi.numbufs = audio_buffers; 01612 if (ioctl(fd, ZT_SET_BUFINFO, &bi)) { 01613 ast_log(LOG_WARNING, "Unable to set buffering information: %s\n", strerror(errno)); 01614 close(fd); 01615 goto outrun; 01616 } 01617 x = 1; 01618 if (ioctl(fd, ZT_SETLINEAR, &x)) { 01619 ast_log(LOG_WARNING, "Unable to set linear mode: %s\n", strerror(errno)); 01620 close(fd); 01621 goto outrun; 01622 } 01623 nfds = 1; 01624 } else { 01625 /* XXX Make sure we're not running on a pseudo channel XXX */ 01626 fd = chan->fds[0]; 01627 nfds = 0; 01628 } 01629 memset(&ztc, 0, sizeof(ztc)); 01630 memset(&ztc_empty, 0, sizeof(ztc_empty)); 01631 /* Check to see if we're in a conference... */ 01632 ztc.chan = 0; 01633 if (ioctl(fd, ZT_GETCONF, &ztc)) { 01634 ast_log(LOG_WARNING, "Error getting conference\n"); 01635 close(fd); 01636 goto outrun; 01637 } 01638 if (ztc.confmode) { 01639 /* Whoa, already in a conference... Retry... */ 01640 if (!retryzap) { 01641 ast_log(LOG_DEBUG, "Zap channel is in a conference already, retrying with pseudo\n"); 01642 retryzap = 1; 01643 goto zapretry; 01644 } 01645 } 01646 memset(&ztc, 0, sizeof(ztc)); 01647 /* Add us to the conference */ 01648 ztc.chan = 0; 01649 ztc.confno = conf->zapconf; 01650 01651 ast_mutex_lock(&conf->playlock); 01652 01653 if (!(confflags & CONFFLAG_QUIET) && ((confflags & CONFFLAG_INTROUSER) || (confflags & CONFFLAG_INTROUSERNOREVIEW)) && conf->users > 1) { 01654 if (conf->chan && ast_fileexists(user->namerecloc, NULL, NULL)) { 01655 if (!ast_streamfile(conf->chan, user->namerecloc, chan->language)) 01656 ast_waitstream(conf->chan, ""); 01657 if (!ast_streamfile(conf->chan, "conf-hasjoin", chan->language)) 01658 ast_waitstream(conf->chan, ""); 01659 } 01660 } 01661 01662 if (confflags & CONFFLAG_MONITOR) 01663 ztc.confmode = ZT_CONF_CONFMON | ZT_CONF_LISTENER; 01664 else if (confflags & CONFFLAG_TALKER) 01665 ztc.confmode = ZT_CONF_CONF | ZT_CONF_TALKER; 01666 else 01667 ztc.confmode = ZT_CONF_CONF | ZT_CONF_TALKER | ZT_CONF_LISTENER; 01668 01669 if (ioctl(fd, ZT_SETCONF, &ztc)) { 01670 ast_log(LOG_WARNING, "Error setting conference\n"); 01671 close(fd); 01672 ast_mutex_unlock(&conf->playlock); 01673 goto outrun; 01674 } 01675 ast_log(LOG_DEBUG, "Placed channel %s in ZAP conf %d\n", chan->name, conf->zapconf); 01676 01677 if (!sent_event) { 01678 manager_event(EVENT_FLAG_CALL, "MeetmeJoin", 01679 "Channel: %s\r\n" 01680 "Uniqueid: %s\r\n" 01681 "Meetme: %s\r\n" 01682 "Usernum: %d\r\n", 01683 chan->name, chan->uniqueid, conf->confno, user->user_no); 01684 sent_event = 1; 01685 } 01686 01687 if (!firstpass && !(confflags & CONFFLAG_MONITOR) && !(confflags & CONFFLAG_ADMIN)) { 01688 firstpass = 1; 01689 if (!(confflags & CONFFLAG_QUIET)) 01690 if (!(confflags & CONFFLAG_WAITMARKED) || ((confflags & CONFFLAG_MARKEDUSER) && (conf->markedusers >= 1))) 01691 conf_play(chan, conf, ENTER); 01692 } 01693 01694 ast_mutex_unlock(&conf->playlock); 01695 01696 conf_flush(fd, chan); 01697 01698 if (confflags & CONFFLAG_AGI) { 01699 /* Get name of AGI file to run from $(MEETME_AGI_BACKGROUND) 01700 or use default filename of conf-background.agi */ 01701 01702 agifile = pbx_builtin_getvar_helper(chan, "MEETME_AGI_BACKGROUND"); 01703 if (!agifile) 01704 agifile = agifiledefault; 01705 01706 if (user->zapchannel) { 01707 /* Set CONFMUTE mode on Zap channel to mute DTMF tones */ 01708 x = 1; 01709 ast_channel_setoption(chan, AST_OPTION_TONE_VERIFY, &x, sizeof(char), 0); 01710 } 01711 /* Find a pointer to the agi app and execute the script */ 01712 app = pbx_findapp("agi"); 01713 if (app) { 01714 char *s = ast_strdupa(agifile); 01715 ret = pbx_exec(chan, app, s); 01716 } else { 01717 ast_log(LOG_WARNING, "Could not find application (agi)\n"); 01718 ret = -2; 01719 } 01720 if (user->zapchannel) { 01721 /* Remove CONFMUTE mode on Zap channel */ 01722 x = 0; 01723 ast_channel_setoption(chan, AST_OPTION_TONE_VERIFY, &x, sizeof(char), 0); 01724 } 01725 } else { 01726 if (user->zapchannel && (confflags & CONFFLAG_STARMENU)) { 01727 /* Set CONFMUTE mode on Zap channel to mute DTMF tones when the menu is enabled */ 01728 x = 1; 01729 ast_channel_setoption(chan, AST_OPTION_TONE_VERIFY, &x, sizeof(char), 0); 01730 } 01731 if (confflags & (CONFFLAG_MONITORTALKER | CONFFLAG_OPTIMIZETALKER) && !(dsp = ast_dsp_new())) { 01732 ast_log(LOG_WARNING, "Unable to allocate DSP!\n"); 01733 res = -1; 01734 } 01735 for(;;) { 01736 int menu_was_active = 0; 01737 01738 outfd = -1; 01739 ms = -1; 01740 01741 if (timeout && time(NULL) >= timeout) 01742 break; 01743 01744 /* if we have just exited from the menu, and the user had a channel-driver 01745 volume adjustment, restore it 01746 */ 01747 if (!menu_active && menu_was_active && user->listen.desired && !user->listen.actual) 01748 set_talk_volume(user, user->listen.desired); 01749 01750 menu_was_active = menu_active; 01751 01752 currentmarked = conf->markedusers; 01753 if (!(confflags & CONFFLAG_QUIET) && 01754 (confflags & CONFFLAG_MARKEDUSER) && 01755 (confflags & CONFFLAG_WAITMARKED) && 01756 lastmarked == 0) { 01757 if (currentmarked == 1 && conf->users > 1) { 01758 ast_say_number(chan, conf->users - 1, AST_DIGIT_ANY, chan->language, (char *) NULL); 01759 if (conf->users - 1 == 1) { 01760 if (!ast_streamfile(chan, "conf-userwilljoin", chan->language)) 01761 ast_waitstream(chan, ""); 01762 } else { 01763 if (!ast_streamfile(chan, "conf-userswilljoin", chan->language)) 01764 ast_waitstream(chan, ""); 01765 } 01766 } 01767 if (conf->users == 1 && ! (confflags & CONFFLAG_MARKEDUSER)) 01768 if (!ast_streamfile(chan, "conf-onlyperson", chan->language)) 01769 ast_waitstream(chan, ""); 01770 } 01771 01772 c = ast_waitfor_nandfds(&chan, 1, &fd, nfds, NULL, &outfd, &ms); 01773 01774 01775 /* Update the struct with the actual confflags */ 01776 user->userflags = confflags; 01777 01778 if (confflags & CONFFLAG_WAITMARKED) { 01779 if(currentmarked == 0) { 01780 if (lastmarked != 0) { 01781 if (!(confflags & CONFFLAG_QUIET)) 01782 if (!ast_streamfile(chan, "conf-leaderhasleft", chan->language)) 01783 ast_waitstream(chan, ""); 01784 if(confflags & CONFFLAG_MARKEDEXIT) 01785 break; 01786 else { 01787 ztc.confmode = ZT_CONF_CONF; 01788 if (ioctl(fd, ZT_SETCONF, &ztc)) { 01789 ast_log(LOG_WARNING, "Error setting conference\n"); 01790 close(fd); 01791 goto outrun; 01792 } 01793 } 01794 } 01795 if (musiconhold == 0 && (confflags & CONFFLAG_MOH)) { 01796 ast_moh_start(chan, NULL, NULL); 01797 musiconhold = 1; 01798 } 01799 } else if(currentmarked >= 1 && lastmarked == 0) { 01800 /* Marked user entered, so cancel timeout */ 01801 timeout = 0; 01802 if (confflags & CONFFLAG_MONITOR) 01803 ztc.confmode = ZT_CONF_CONFMON | ZT_CONF_LISTENER; 01804 else if (confflags & CONFFLAG_TALKER) 01805 ztc.confmode = ZT_CONF_CONF | ZT_CONF_TALKER; 01806 else 01807 ztc.confmode = ZT_CONF_CONF | ZT_CONF_TALKER | ZT_CONF_LISTENER; 01808 if (ioctl(fd, ZT_SETCONF, &ztc)) { 01809 ast_log(LOG_WARNING, "Error setting conference\n"); 01810 close(fd); 01811 goto outrun; 01812 } 01813 if (musiconhold && (confflags & CONFFLAG_MOH)) { 01814 ast_moh_stop(chan); 01815 musiconhold = 0; 01816 } 01817 if ( !(confflags & CONFFLAG_QUIET) && !(confflags & CONFFLAG_MARKEDUSER)) { 01818 if (!ast_streamfile(chan, "conf-placeintoconf", chan->language)) 01819 ast_waitstream(chan, ""); 01820 conf_play(chan, conf, ENTER); 01821 } 01822 } 01823 } 01824 01825 /* trying to add moh for single person conf */ 01826 if ((confflags & CONFFLAG_MOH) && !(confflags & CONFFLAG_WAITMARKED)) { 01827 if (conf->users == 1) { 01828 if (musiconhold == 0) { 01829 ast_moh_start(chan, NULL, NULL); 01830 musiconhold = 1; 01831 } 01832 } else { 01833 if (musiconhold) { 01834 ast_moh_stop(chan); 01835 musiconhold = 0; 01836 } 01837 } 01838 } 01839 01840 /* Leave if the last marked user left */ 01841 if (currentmarked == 0 && lastmarked != 0 && (confflags & CONFFLAG_MARKEDEXIT)) { 01842 ret = -1; 01843 break; 01844 } 01845 01846 /* Check if my modes have changed */ 01847 01848 /* If I should be muted but am still talker, mute me */ 01849 if ((user->adminflags & (ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED)) && (ztc.confmode & ZT_CONF_TALKER)) { 01850 ztc.confmode ^= ZT_CONF_TALKER; 01851 if (ioctl(fd, ZT_SETCONF, &ztc)) { 01852 ast_log(LOG_WARNING, "Error setting conference - Un/Mute \n"); 01853 ret = -1; 01854 break; 01855 } 01856 01857 manager_event(EVENT_FLAG_CALL, "MeetmeMute", 01858 "Channel: %s\r\n" 01859 "Uniqueid: %s\r\n" 01860 "Meetme: %s\r\n" 01861 "Usernum: %i\r\n" 01862 "Status: on\r\n", 01863 chan->name, chan->uniqueid, conf->confno, user->user_no); 01864 } 01865 01866 /* If I should be un-muted but am not talker, un-mute me */ 01867 if (!(user->adminflags & (ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED)) && !(confflags & CONFFLAG_MONITOR) && !(ztc.confmode & ZT_CONF_TALKER)) { 01868 ztc.confmode |= ZT_CONF_TALKER; 01869 if (ioctl(fd, ZT_SETCONF, &ztc)) { 01870 ast_log(LOG_WARNING, "Error setting conference - Un/Mute \n"); 01871 ret = -1; 01872 break; 01873 } 01874 01875 manager_event(EVENT_FLAG_CALL, "MeetmeMute", 01876 "Channel: %s\r\n" 01877 "Uniqueid: %s\r\n" 01878 "Meetme: %s\r\n" 01879 "Usernum: %i\r\n" 01880 "Status: off\r\n", 01881 chan->name, chan->uniqueid, conf->confno, user->user_no); 01882 } 01883 01884 /* If I have been kicked, exit the conference */ 01885 if (user->adminflags & ADMINFLAG_KICKME) { 01886 //You have been kicked. 01887 if (!(confflags & CONFFLAG_QUIET) && 01888 !ast_streamfile(chan, "conf-kicked", chan->language)) { 01889 ast_waitstream(chan, ""); 01890 } 01891 ret = 0; 01892 break; 01893 } 01894 01895 /* Perform an extra hangup check just in case */ 01896 if (ast_check_hangup(chan)) 01897 break; 01898 01899 if (c) { 01900 if (c->fds[0] != origfd || (user->zapchannel && c->spies)) { 01901 if (using_pseudo) { 01902 /* Kill old pseudo */ 01903 close(fd); 01904 using_pseudo = 0; 01905 } 01906 ast_log(LOG_DEBUG, "Ooh, something swapped out under us, starting over\n"); 01907 retryzap = (strcasecmp(c->tech->type, "Zap") || c->spies ? 1 : 0); 01908 user->zapchannel = !retryzap; 01909 goto zapretry; 01910 } 01911 if ((confflags & CONFFLAG_MONITOR) || (user->adminflags & (ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED))) 01912 f = ast_read_noaudio(c); 01913 else 01914 f = ast_read(c); 01915 if (!f) 01916 break; 01917 if (f->datalen && f->datalen != dyna_buff) { 01918 ast_log(LOG_NOTICE, "Audio bytes: %d Buffer size: %d\n", f->datalen, dyna_buff); 01919 if (f->datalen < ZT_MAX_BUF_SPACE/audio_buffers) { /* skip too large frame to avoid overflow */ 01920 dyna_buff = f->datalen; 01921 close(fd); 01922 goto zapretry; 01923 } 01924 } 01925 if ((f->frametype == AST_FRAME_VOICE) && (f->subclass == AST_FORMAT_SLINEAR)) { 01926 if (user->talk.actual) 01927 ast_frame_adjust_volume(f, user->talk.actual); 01928 01929 if (confflags & (CONFFLAG_MONITORTALKER | CONFFLAG_OPTIMIZETALKER)) { 01930 int totalsilence; 01931 01932 if (user->talking == -1) 01933 user->talking = 0; 01934 01935 res = ast_dsp_silence(dsp, f, &totalsilence); 01936 if (!user->talking && totalsilence < MEETME_DELAYDETECTTALK) { 01937 user->talking = 1; 01938 if (confflags & CONFFLAG_MONITORTALKER) 01939 manager_event(EVENT_FLAG_CALL, "MeetmeTalking", 01940 "Channel: %s\r\n" 01941 "Uniqueid: %s\r\n" 01942 "Meetme: %s\r\n" 01943 "Usernum: %d\r\n" 01944 "Status: on\r\n", 01945 chan->name, chan->uniqueid, conf->confno, user->user_no); 01946 } 01947 if (user->talking && totalsilence > MEETME_DELAYDETECTENDTALK) { 01948 user->talking = 0; 01949 if (confflags & CONFFLAG_MONITORTALKER) 01950 manager_event(EVENT_FLAG_CALL, "MeetmeTalking", 01951 "Channel: %s\r\n" 01952 "Uniqueid: %s\r\n" 01953 "Meetme: %s\r\n" 01954 "Usernum: %d\r\n" 01955 "Status: off\r\n", 01956 chan->name, chan->uniqueid, conf->confno, user->user_no); 01957 } 01958 } 01959 if (using_pseudo) { 01960 /* Absolutely do _not_ use careful_write here... 01961 it is important that we read data from the channel 01962 as fast as it arrives, and feed it into the conference. 01963 The buffering in the pseudo channel will take care of any 01964 timing differences, unless they are so drastic as to lose 01965 audio frames (in which case carefully writing would only 01966 have delayed the audio even further). 01967 */ 01968 /* As it turns out, we do want to use careful write. We just 01969 don't want to block, but we do want to at least *try* 01970 to write out all the samples. 01971 */ 01972 if (user->talking || !(confflags & CONFFLAG_OPTIMIZETALKER)) 01973 careful_write(fd, f->data, f->datalen, 0); 01974 } 01975 } else if ((f->frametype == AST_FRAME_DTMF) && (confflags & CONFFLAG_EXIT_CONTEXT)) { 01976 char tmp[2]; 01977 01978 if (confflags & CONFFLAG_PASS_DTMF) 01979 conf_queue_dtmf(conf, user, f); 01980 01981 tmp[0] = f->subclass; 01982 tmp[1] = '\0'; 01983 if (!ast_goto_if_exists(chan, exitcontext, tmp, 1)) { 01984 ast_log(LOG_DEBUG, "Got DTMF %c, goto context %s\n", tmp[0], exitcontext); 01985 ret = 0; 01986 ast_frfree(f); 01987 break; 01988 } else if (option_debug > 1) 01989 ast_log(LOG_DEBUG, "Exit by single digit did not work in meetme. Extension %s does not exist in context %s\n", tmp, exitcontext); 01990 } else if ((f->frametype == AST_FRAME_DTMF) && (f->subclass == '#') && (confflags & CONFFLAG_POUNDEXIT)) { 01991 if (confflags & CONFFLAG_PASS_DTMF) 01992 conf_queue_dtmf(conf, user, f); 01993 ret = 0; 01994 ast_frfree(f); 01995 break; 01996 } else if (((f->frametype == AST_FRAME_DTMF) && (f->subclass == '*') && (confflags & CONFFLAG_STARMENU)) || ((f->frametype == AST_FRAME_DTMF) && menu_active)) { 01997 if (confflags & CONFFLAG_PASS_DTMF) 01998 conf_queue_dtmf(conf, user, f); 01999 if (ioctl(fd, ZT_SETCONF, &ztc_empty)) { 02000 ast_log(LOG_WARNING, "Error setting conference\n"); 02001 close(fd); 02002 ast_frfree(f); 02003 goto outrun; 02004 } 02005 02006 /* if we are entering the menu, and the user has a channel-driver 02007 volume adjustment, clear it 02008 */ 02009 if (!menu_active && user->talk.desired && !user->talk.actual) 02010 set_talk_volume(user, 0); 02011 02012 if (musiconhold) { 02013 ast_moh_stop(chan); 02014 } 02015 if ((confflags & CONFFLAG_ADMIN)) { 02016 /* Admin menu */ 02017 if (!menu_active) { 02018 menu_active = 1; 02019 /* Record this sound! */ 02020 if (!ast_streamfile(chan, "conf-adminmenu", chan->language)) { 02021 dtmf = ast_waitstream(chan, AST_DIGIT_ANY); 02022 ast_stopstream(chan); 02023 } else 02024 dtmf = 0; 02025 } else 02026 dtmf = f->subclass; 02027 if (dtmf) { 02028 switch(dtmf) { 02029 case '1': /* Un/Mute */ 02030 menu_active = 0; 02031 02032 /* for admin, change both admin and use flags */ 02033 if (user->adminflags & (ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED)) 02034 user->adminflags &= ~(ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED); 02035 else 02036 user->adminflags |= (ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED); 02037 02038 if ((confflags & CONFFLAG_MONITOR) || (user->adminflags & (ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED))) { 02039 if (!ast_streamfile(chan, "conf-muted", chan->language)) 02040 ast_waitstream(chan, ""); 02041 } else { 02042 if (!ast_streamfile(chan, "conf-unmuted", chan->language)) 02043 ast_waitstream(chan, ""); 02044 } 02045 break; 02046 case '2': /* Un/Lock the Conference */ 02047 menu_active = 0; 02048 if (conf->locked) { 02049 conf->locked = 0; 02050 if (!ast_streamfile(chan, "conf-unlockednow", chan->language)) 02051 ast_waitstream(chan, ""); 02052 } else { 02053 conf->locked = 1; 02054 if (!ast_streamfile(chan, "conf-lockednow", chan->language)) 02055 ast_waitstream(chan, ""); 02056 } 02057 break; 02058 case '3': /* Eject last user */ 02059 menu_active = 0; 02060 usr = AST_LIST_LAST(&conf->userlist); 02061 if ((usr->chan->name == chan->name)||(usr->userflags & CONFFLAG_ADMIN)) { 02062 if(!ast_streamfile(chan, "conf-errormenu", chan->language)) 02063 ast_waitstream(chan, ""); 02064 } else 02065 usr->adminflags |= ADMINFLAG_KICKME; 02066 ast_stopstream(chan); 02067 break; 02068 case '4': 02069 tweak_listen_volume(user, VOL_DOWN); 02070 break; 02071 case '6': 02072 tweak_listen_volume(user, VOL_UP); 02073 break; 02074 case '7': 02075 tweak_talk_volume(user, VOL_DOWN); 02076 break; 02077 case '8': 02078 menu_active = 0; 02079 break; 02080 case '9': 02081 tweak_talk_volume(user, VOL_UP); 02082 break; 02083 default: 02084 menu_active = 0; 02085 /* Play an error message! */ 02086 if (!ast_streamfile(chan, "conf-errormenu", chan->language)) 02087 ast_waitstream(chan, ""); 02088 break; 02089 } 02090 } 02091 } else { 02092 /* User menu */ 02093 if (!menu_active) { 02094 menu_active = 1; 02095 if (!ast_streamfile(chan, "conf-usermenu", chan->language)) { 02096 dtmf = ast_waitstream(chan, AST_DIGIT_ANY); 02097 ast_stopstream(chan); 02098 } else 02099 dtmf = 0; 02100 } else 02101 dtmf = f->subclass; 02102 if (dtmf) { 02103 switch(dtmf) { 02104 case '1': /* Un/Mute */ 02105 menu_active = 0; 02106 02107 /* user can only toggle the self-muted state */ 02108 user->adminflags ^= ADMINFLAG_SELFMUTED; 02109 02110 /* they can't override the admin mute state */ 02111 if ((confflags & CONFFLAG_MONITOR) || (user->adminflags & (ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED))) { 02112 if (!ast_streamfile(chan, "conf-muted", chan->language)) 02113 ast_waitstream(chan, ""); 02114 } else { 02115 if (!ast_streamfile(chan, "conf-unmuted", chan->language)) 02116 ast_waitstream(chan, ""); 02117 } 02118 break; 02119 case '4': 02120 tweak_listen_volume(user, VOL_DOWN); 02121 break; 02122 case '6': 02123 tweak_listen_volume(user, VOL_UP); 02124 break; 02125 case '7': 02126 tweak_talk_volume(user, VOL_DOWN); 02127 break; 02128 case '8': 02129 menu_active = 0; 02130 break; 02131 case '9': 02132 tweak_talk_volume(user, VOL_UP); 02133 break; 02134 default: 02135 menu_active = 0; 02136 if (!ast_streamfile(chan, "conf-errormenu", chan->language)) 02137 ast_waitstream(chan, ""); 02138 break; 02139 } 02140 } 02141 } 02142 if (musiconhold) 02143 ast_moh_start(chan, NULL, NULL); 02144 02145 if (ioctl(fd, ZT_SETCONF, &ztc)) { 02146 ast_log(LOG_WARNING, "Error setting conference\n"); 02147 close(fd); 02148 ast_frfree(f); 02149 goto outrun; 02150 } 02151 02152 conf_flush(fd, chan); 02153 } else if ((f->frametype == AST_FRAME_DTMF_BEGIN || f->frametype == AST_FRAME_DTMF_END) 02154 && confflags & CONFFLAG_PASS_DTMF) { 02155 conf_queue_dtmf(conf, user, f); 02156 } else if ((confflags & CONFFLAG_SLA_STATION) && f->frametype == AST_FRAME_CONTROL) { 02157 switch (f->subclass) { 02158 case AST_CONTROL_HOLD: 02159 sla_queue_event_conf(SLA_EVENT_HOLD, chan, conf); 02160 break; 02161 default: 02162 break; 02163 } 02164 } else if (f->frametype == AST_FRAME_NULL) { 02165 /* Ignore NULL frames. It is perfectly normal to get these if the person is muted. */ 02166 } else if (option_debug) { 02167 ast_log(LOG_DEBUG, 02168 "Got unrecognized frame on channel %s, f->frametype=%d,f->subclass=%d\n", 02169 chan->name, f->frametype, f->subclass); 02170 } 02171 ast_frfree(f); 02172 } else if (outfd > -1) { 02173 res = read(outfd, buf, CONF_SIZE); 02174 if (res > 0) { 02175 memset(&fr, 0, sizeof(fr)); 02176 fr.frametype = AST_FRAME_VOICE; 02177 fr.subclass = AST_FORMAT_SLINEAR; 02178 fr.datalen = res; 02179 fr.samples = res/2; 02180 fr.data = buf; 02181 fr.offset = AST_FRIENDLY_OFFSET; 02182 if (!user->listen.actual && 02183 ((confflags & CONFFLAG_MONITOR) || 02184 (user->adminflags & (ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED)) || 02185 (!user->talking && (confflags & CONFFLAG_OPTIMIZETALKER)) 02186 )) { 02187 int index; 02188 for (index=0;index<AST_FRAME_BITS;index++) 02189 if (chan->rawwriteformat & (1 << index)) 02190 break; 02191 if (index >= AST_FRAME_BITS) 02192 goto bailoutandtrynormal; 02193 ast_mutex_lock(&conf->listenlock); 02194 if (!conf->transframe[index]) { 02195 if (conf->origframe) { 02196 if (!conf->transpath[index]) 02197 conf->transpath[index] = ast_translator_build_path((1 << index), AST_FORMAT_SLINEAR); 02198 if (conf->transpath[index]) { 02199 conf->transframe[index] = ast_translate(conf->transpath[index], conf->origframe, 0); 02200 if (!conf->transframe[index]) 02201 conf->transframe[index] = &ast_null_frame; 02202 } 02203 } 02204 } 02205 if (conf->transframe[index]) { 02206 if (conf->transframe[index]->frametype != AST_FRAME_NULL) { 02207 if (ast_write(chan, conf->transframe[index])) 02208 ast_log(LOG_WARNING, "Unable to write frame to channel %s\n", chan->name); 02209 } 02210 } else { 02211 ast_mutex_unlock(&conf->listenlock); 02212 goto bailoutandtrynormal; 02213 } 02214 ast_mutex_unlock(&conf->listenlock); 02215 } else { 02216 bailoutandtrynormal: 02217 if (user->listen.actual) 02218 ast_frame_adjust_volume(&fr, user->listen.actual); 02219 if (ast_write(chan, &fr) < 0) { 02220 ast_log(LOG_WARNING, "Unable to write frame to channel %s\n", chan->name); 02221 } 02222 } 02223 } else 02224 ast_log(LOG_WARNING, "Failed to read frame: %s\n", strerror(errno)); 02225 } 02226 lastmarked = currentmarked; 02227 } 02228 } 02229 02230 if (musiconhold) 02231 ast_moh_stop(chan); 02232 02233 if (using_pseudo) 02234 close(fd); 02235 else { 02236 /* Take out of conference */ 02237 ztc.chan = 0; 02238 ztc.confno = 0; 02239 ztc.confmode = 0; 02240 if (ioctl(fd, ZT_SETCONF, &ztc)) { 02241 ast_log(LOG_WARNING, "Error setting conference\n"); 02242 } 02243 } 02244 02245 reset_volumes(user); 02246 02247 AST_LIST_LOCK(&confs); 02248 if (!(confflags & CONFFLAG_QUIET) && !(confflags & CONFFLAG_MONITOR) && !(confflags & CONFFLAG_ADMIN)) 02249 conf_play(chan, conf, LEAVE); 02250 02251 if (!(confflags & CONFFLAG_QUIET) && ((confflags & CONFFLAG_INTROUSER) || (confflags & CONFFLAG_INTROUSERNOREVIEW))) { 02252 if (ast_fileexists(user->namerecloc, NULL, NULL)) { 02253 if ((conf->chan) && (conf->users > 1)) { 02254 if (!ast_streamfile(conf->chan, user->namerecloc, chan->language)) 02255 ast_waitstream(conf->chan, ""); 02256 if (!ast_streamfile(conf->chan, "conf-hasleft", chan->language)) 02257 ast_waitstream(conf->chan, ""); 02258 } 02259 ast_filedelete(user->namerecloc, NULL); 02260 } 02261 } 02262 AST_LIST_UNLOCK(&confs); 02263 02264 outrun: 02265 AST_LIST_LOCK(&confs); 02266 02267 if (dsp) 02268 ast_dsp_free(dsp); 02269 02270 if (user->user_no) { /* Only cleanup users who really joined! */ 02271 now = time(NULL); 02272 hr = (now - user->jointime) / 3600; 02273 min = ((now - user->jointime) % 3600) / 60; 02274 sec = (now - user->jointime) % 60; 02275 02276 if (sent_event) { 02277 manager_event(EVENT_FLAG_CALL, "MeetmeLeave", 02278 "Channel: %s\r\n" 02279 "Uniqueid: %s\r\n" 02280 "Meetme: %s\r\n" 02281 "Usernum: %d\r\n" 02282 "CallerIDnum: %s\r\n" 02283 "CallerIDname: %s\r\n" 02284 "Duration: %ld\r\n", 02285 chan->name, chan->uniqueid, conf->confno, 02286 user->user_no, 02287 S_OR(user->chan->cid.cid_num, "<unknown>"), 02288 S_OR(user->chan->cid.cid_name, "<unknown>"), 02289 (long)(now - user->jointime)); 02290 } 02291 02292 if (setusercount) { 02293 conf->users--; 02294 /* Update table */ 02295 snprintf(members, sizeof(members), "%d", conf->users); 02296 ast_update_realtime("meetme", "confno", conf->confno, "members", members, NULL); 02297 if (confflags & CONFFLAG_MARKEDUSER) 02298 conf->markedusers--; 02299 } 02300 /* Remove ourselves from the list */ 02301 AST_LIST_REMOVE(&conf->userlist, user, list); 02302 02303 /* Change any states */ 02304 if (!conf->users) 02305 ast_device_state_changed("meetme:%s", conf->confno); 02306 02307 /* Return the number of seconds the user was in the conf */ 02308 snprintf(meetmesecs, sizeof(meetmesecs), "%d", (int) (time(NULL) - user->jointime)); 02309 pbx_builtin_setvar_helper(chan, "MEETMESECS", meetmesecs); 02310 } 02311 free(user); 02312 AST_LIST_UNLOCK(&confs); 02313 02314 return ret; 02315 }
static int count_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
The MeetmeCount application.
Definition at line 2468 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::confno, dispose_conf(), find_conf(), LOG_WARNING, pbx_builtin_setvar_helper(), and ast_conference::users.
Referenced by load_module().
02469 { 02470 struct ast_module_user *u; 02471 int res = 0; 02472 struct ast_conference *conf; 02473 int count; 02474 char *localdata; 02475 char val[80] = "0"; 02476 AST_DECLARE_APP_ARGS(args, 02477 AST_APP_ARG(confno); 02478 AST_APP_ARG(varname); 02479 ); 02480 02481 if (ast_strlen_zero(data)) { 02482 ast_log(LOG_WARNING, "MeetMeCount requires an argument (conference number)\n"); 02483 return -1; 02484 } 02485 02486 u = ast_module_user_add(chan); 02487 02488 if (!(localdata = ast_strdupa(data))) { 02489 ast_module_user_remove(u); 02490 return -1; 02491 } 02492 02493 AST_STANDARD_APP_ARGS(args, localdata); 02494 02495 conf = find_conf(chan, args.confno, 0, 0, NULL, 0, 1, NULL); 02496 02497 if (conf) { 02498 count = conf->users; 02499 dispose_conf(conf); 02500 conf = NULL; 02501 } else 02502 count = 0; 02503 02504 if (!ast_strlen_zero(args.varname)){ 02505 /* have var so load it and exit */ 02506 snprintf(val, sizeof(val), "%d",count); 02507 pbx_builtin_setvar_helper(chan, args.varname, val); 02508 } else { 02509 if (chan->_state != AST_STATE_UP) 02510 ast_answer(chan); 02511 res = ast_say_number(chan, count, "", chan->language, (char *) NULL); /* Needs gender */ 02512 } 02513 ast_module_user_remove(u); 02514 02515 return res; 02516 }
static struct sla_trunk_ref* create_trunk_ref | ( | struct sla_trunk * | trunk | ) | [static, read] |
Definition at line 4286 of file app_meetme.c.
References ast_calloc.
Referenced by sla_add_trunk_to_station().
04287 { 04288 struct sla_trunk_ref *trunk_ref; 04289 04290 if (!(trunk_ref = ast_calloc(1, sizeof(*trunk_ref)))) 04291 return NULL; 04292 04293 trunk_ref->trunk = trunk; 04294 04295 return trunk_ref; 04296 }
static void destroy_station | ( | struct sla_station * | station | ) | [static] |
Definition at line 4453 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(), exten, free, PRIORITY_HINT, and sla_registrar.
Referenced by sla_build_station(), and sla_destroy().
04454 { 04455 struct sla_trunk_ref *trunk_ref; 04456 04457 if (!ast_strlen_zero(station->autocontext)) { 04458 AST_RWLIST_RDLOCK(&sla_trunks); 04459 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) { 04460 char exten[AST_MAX_EXTENSION]; 04461 char hint[AST_MAX_APP]; 04462 snprintf(exten, sizeof(exten), "%s_%s", station->name, trunk_ref->trunk->name); 04463 snprintf(hint, sizeof(hint), "SLA:%s", exten); 04464 ast_context_remove_extension(station->autocontext, exten, 04465 1, sla_registrar); 04466 ast_context_remove_extension(station->autocontext, hint, 04467 PRIORITY_HINT, sla_registrar); 04468 } 04469 AST_RWLIST_UNLOCK(&sla_trunks); 04470 } 04471 04472 while ((trunk_ref = AST_LIST_REMOVE_HEAD(&station->trunks, entry))) 04473 free(trunk_ref); 04474 04475 ast_string_field_free_memory(station); 04476 free(station); 04477 }
static void destroy_trunk | ( | struct sla_trunk * | trunk | ) | [static] |
Definition at line 4439 of file app_meetme.c.
References ast_context_remove_extension(), AST_LIST_REMOVE_HEAD, ast_string_field_free_memory, ast_strlen_zero(), free, and sla_registrar.
Referenced by sla_build_trunk(), and sla_destroy().
04440 { 04441 struct sla_station_ref *station_ref; 04442 04443 if (!ast_strlen_zero(trunk->autocontext)) 04444 ast_context_remove_extension(trunk->autocontext, "s", 1, sla_registrar); 04445 04446 while ((station_ref = AST_LIST_REMOVE_HEAD(&trunk->stations, entry))) 04447 free(station_ref); 04448 04449 ast_string_field_free_memory(trunk); 04450 free(trunk); 04451 }
static void* dial_trunk | ( | void * | data | ) | [static] |
Definition at line 4005 of file app_meetme.c.
References ALL_TRUNK_REFS, 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_set_flag, ast_strdup, ast_strdupa, ast_strlen_zero(), build_conf(), cid_name, cid_num, dial_trunk_args::cond, dial_trunk_args::cond_lock, conf_run(), CONFFLAG_MARKEDEXIT, CONFFLAG_MARKEDUSER, CONFFLAG_PASS_DTMF, CONFFLAG_QUIET, CONFFLAG_SLA_TRUNK, dispose_conf(), ast_flags::flags, free, MAX_CONFNUM, sla, sla_change_trunk_state(), SLA_TRUNK_STATE_IDLE, strsep(), and dial_trunk_args::trunk_ref.
Referenced by sla_station_exec().
04006 { 04007 struct dial_trunk_args *args = data; 04008 struct ast_dial *dial; 04009 char *tech, *tech_data; 04010 enum ast_dial_result dial_res; 04011 char conf_name[MAX_CONFNUM]; 04012 struct ast_conference *conf; 04013 struct ast_flags conf_flags = { 0 }; 04014 struct sla_trunk_ref *trunk_ref = args->trunk_ref; 04015 const char *cid_name = NULL, *cid_num = NULL; 04016 04017 if (!(dial = ast_dial_create())) { 04018 ast_mutex_lock(args->cond_lock); 04019 ast_cond_signal(args->cond); 04020 ast_mutex_unlock(args->cond_lock); 04021 return NULL; 04022 } 04023 04024 tech_data = ast_strdupa(trunk_ref->trunk->device); 04025 tech = strsep(&tech_data, "/"); 04026 if (ast_dial_append(dial, tech, tech_data) == -1) { 04027 ast_mutex_lock(args->cond_lock); 04028 ast_cond_signal(args->cond); 04029 ast_mutex_unlock(args->cond_lock); 04030 ast_dial_destroy(dial); 04031 return NULL; 04032 } 04033 04034 if (!sla.attempt_callerid && !ast_strlen_zero(trunk_ref->chan->cid.cid_name)) { 04035 cid_name = ast_strdupa(trunk_ref->chan->cid.cid_name); 04036 free(trunk_ref->chan->cid.cid_name); 04037 trunk_ref->chan->cid.cid_name = NULL; 04038 } 04039 if (!sla.attempt_callerid && !ast_strlen_zero(trunk_ref->chan->cid.cid_num)) { 04040 cid_num = ast_strdupa(trunk_ref->chan->cid.cid_num); 04041 free(trunk_ref->chan->cid.cid_num); 04042 trunk_ref->chan->cid.cid_num = NULL; 04043 } 04044 04045 dial_res = ast_dial_run(dial, trunk_ref->chan, 1); 04046 04047 if (cid_name) 04048 trunk_ref->chan->cid.cid_name = ast_strdup(cid_name); 04049 if (cid_num) 04050 trunk_ref->chan->cid.cid_num = ast_strdup(cid_num); 04051 04052 if (dial_res != AST_DIAL_RESULT_TRYING) { 04053 ast_mutex_lock(args->cond_lock); 04054 ast_cond_signal(args->cond); 04055 ast_mutex_unlock(args->cond_lock); 04056 ast_dial_destroy(dial); 04057 return NULL; 04058 } 04059 04060 for (;;) { 04061 unsigned int done = 0; 04062 switch ((dial_res = ast_dial_state(dial))) { 04063 case AST_DIAL_RESULT_ANSWERED: 04064 trunk_ref->trunk->chan = ast_dial_answered(dial); 04065 case AST_DIAL_RESULT_HANGUP: 04066 case AST_DIAL_RESULT_INVALID: 04067 case AST_DIAL_RESULT_FAILED: 04068 case AST_DIAL_RESULT_TIMEOUT: 04069 case AST_DIAL_RESULT_UNANSWERED: 04070 done = 1; 04071 case AST_DIAL_RESULT_TRYING: 04072 case AST_DIAL_RESULT_RINGING: 04073 case AST_DIAL_RESULT_PROGRESS: 04074 case AST_DIAL_RESULT_PROCEEDING: 04075 break; 04076 } 04077 if (done) 04078 break; 04079 } 04080 04081 if (!trunk_ref->trunk->chan) { 04082 ast_mutex_lock(args->cond_lock); 04083 ast_cond_signal(args->cond); 04084 ast_mutex_unlock(args->cond_lock); 04085 ast_dial_join(dial); 04086 ast_dial_destroy(dial); 04087 return NULL; 04088 } 04089 04090 snprintf(conf_name, sizeof(conf_name), "SLA_%s", trunk_ref->trunk->name); 04091 ast_set_flag(&conf_flags, 04092 CONFFLAG_QUIET | CONFFLAG_MARKEDEXIT | CONFFLAG_MARKEDUSER | 04093 CONFFLAG_PASS_DTMF | CONFFLAG_SLA_TRUNK); 04094 conf = build_conf(conf_name, "", "", 1, 1, 1); 04095 04096 ast_mutex_lock(args->cond_lock); 04097 ast_cond_signal(args->cond); 04098 ast_mutex_unlock(args->cond_lock); 04099 04100 if (conf) { 04101 conf_run(trunk_ref->trunk->chan, conf, conf_flags.flags, NULL); 04102 dispose_conf(conf); 04103 conf = NULL; 04104 } 04105 04106 /* If the trunk is going away, it is definitely now IDLE. */ 04107 sla_change_trunk_state(trunk_ref->trunk, SLA_TRUNK_STATE_IDLE, ALL_TRUNK_REFS, NULL); 04108 04109 trunk_ref->trunk->chan = NULL; 04110 trunk_ref->trunk->on_hold = 0; 04111 04112 ast_dial_join(dial); 04113 ast_dial_destroy(dial); 04114 04115 return NULL; 04116 }
static int dispose_conf | ( | struct ast_conference * | conf | ) | [static] |
Definition at line 1349 of file app_meetme.c.
References 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(), dial_trunk(), run_station(), sla_station_exec(), and sla_trunk_exec().
01350 { 01351 int res = 0; 01352 int confno_int = 0; 01353 01354 AST_LIST_LOCK(&confs); 01355 if (ast_atomic_dec_and_test(&conf->refcount)) { 01356 /* Take the conference room number out of an inuse state */ 01357 if ((sscanf(conf->confno, "%d", &confno_int) == 1) && (confno_int >= 0 && confno_int < 1024)) 01358 conf_map[confno_int] = 0; 01359 conf_free(conf); 01360 res = 1; 01361 } 01362 AST_LIST_UNLOCK(&confs); 01363 01364 return res; 01365 }
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, read] |
Definition at line 2374 of file app_meetme.c.
References AST_APP_ARG, ast_app_getdata(), ast_clear_flag, ast_config_destroy(), ast_config_load(), AST_DECLARE_APP_ARGS, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), AST_NONSTANDARD_APP_ARGS, ast_strdupa, ast_test_flag, ast_variable_browse(), build_conf(), ast_conference::chan, CONFFLAG_INTROUSER, CONFFLAG_QUIET, CONFFLAG_RECORDCONF, CONFIG_FILE_NAME, ast_conference::confno, LOG_DEBUG, LOG_WARNING, ast_variable::name, ast_variable::next, parse(), ast_conference::pin, ast_conference::pinadmin, ast_conference::refcount, S_OR, ast_variable::value, and var.
Referenced by conf_exec(), and count_exec().
02376 { 02377 struct ast_config *cfg; 02378 struct ast_variable *var; 02379 struct ast_conference *cnf; 02380 char *parse; 02381 AST_DECLARE_APP_ARGS(args, 02382 AST_APP_ARG(confno); 02383 AST_APP_ARG(pin); 02384 AST_APP_ARG(pinadmin); 02385 ); 02386 02387 /* Check first in the conference list */ 02388 AST_LIST_LOCK(&confs); 02389 AST_LIST_TRAVERSE(&confs, cnf, list) { 02390 if (!strcmp(confno, cnf->confno)) 02391 break; 02392 } 02393 if (cnf){ 02394 cnf->refcount += refcount; 02395 } 02396 AST_LIST_UNLOCK(&confs); 02397 02398 if (!cnf) { 02399 if (dynamic) { 02400 /* No need to parse meetme.conf */ 02401 ast_log(LOG_DEBUG, "Building dynamic conference '%s'\n", confno); 02402 if (dynamic_pin) { 02403 if (dynamic_pin[0] == 'q') { 02404 /* Query the user to enter a PIN */ 02405 if (ast_app_getdata(chan, "conf-getpin", dynamic_pin, pin_buf_len - 1, 0) < 0) 02406 return NULL; 02407 } 02408 cnf = build_conf(confno, dynamic_pin, "", make, dynamic, refcount); 02409 } else { 02410 cnf = build_conf(confno, "", "", make, dynamic, refcount); 02411 } 02412 } else { 02413 /* Check the config */ 02414 cfg = ast_config_load(CONFIG_FILE_NAME); 02415 if (!cfg) { 02416 ast_log(LOG_WARNING, "No %s file :(\n", CONFIG_FILE_NAME); 02417 return NULL; 02418 } 02419 for (var = ast_variable_browse(cfg, "rooms"); var; var = var->next) { 02420 if (strcasecmp(var->name, "conf")) 02421 continue; 02422 02423 if (!(parse = ast_strdupa(var->value))) 02424 return NULL; 02425 02426 AST_NONSTANDARD_APP_ARGS(args, parse, ','); 02427 if (!strcasecmp(args.confno, confno)) { 02428 /* Bingo it's a valid conference */ 02429 cnf = build_conf(args.confno, 02430 S_OR(args.pin, ""), 02431 S_OR(args.pinadmin, ""), 02432 make, dynamic, refcount); 02433 break; 02434 } 02435 } 02436 if (!var) { 02437 ast_log(LOG_DEBUG, "%s isn't a valid conference\n", confno); 02438 } 02439 ast_config_destroy(cfg); 02440 } 02441 } else if (dynamic_pin) { 02442 /* Correct for the user selecting 'D' instead of 'd' to have 02443 someone join into a conference that has already been created 02444 with a pin. */ 02445 if (dynamic_pin[0] == 'q') 02446 dynamic_pin[0] = '\0'; 02447 } 02448 02449 if (cnf) { 02450 if (confflags && !cnf->chan && 02451 !ast_test_flag(confflags, CONFFLAG_QUIET) && 02452 ast_test_flag(confflags, CONFFLAG_INTROUSER)) { 02453 ast_log(LOG_WARNING, "No Zap channel available for conference, user introduction disabled (is chan_zap loaded?)\n"); 02454 ast_clear_flag(confflags, CONFFLAG_INTROUSER); 02455 } 02456 02457 if (confflags && !cnf->chan && 02458 ast_test_flag(confflags, CONFFLAG_RECORDCONF)) { 02459 ast_log(LOG_WARNING, "No Zap channel available for conference, conference recording disabled (is chan_zap loaded?)\n"); 02460 ast_clear_flag(confflags, CONFFLAG_RECORDCONF); 02461 } 02462 } 02463 02464 return cnf; 02465 }
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, read] |
Definition at line 2317 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_INTROUSER, CONFFLAG_QUIET, CONFFLAG_RECORDCONF, ast_conference::confno, LOG_WARNING, ast_variable::name, ast_variable::next, ast_conference::pin, ast_conference::pinadmin, ast_conference::refcount, ast_variable::value, and var.
Referenced by conf_exec().
02319 { 02320 struct ast_variable *var; 02321 struct ast_conference *cnf; 02322 02323 /* Check first in the conference list */ 02324 AST_LIST_LOCK(&confs); 02325 AST_LIST_TRAVERSE(&confs, cnf, list) { 02326 if (!strcmp(confno, cnf->confno)) 02327 break; 02328 } 02329 if (cnf) { 02330 cnf->refcount += refcount; 02331 } 02332 AST_LIST_UNLOCK(&confs); 02333 02334 if (!cnf) { 02335 char *pin = NULL, *pinadmin = NULL; /* For temp use */ 02336 02337 var = ast_load_realtime("meetme", "confno", confno, NULL); 02338 02339 if (!var) 02340 return NULL; 02341 02342 while (var) { 02343 if (!strcasecmp(var->name, "pin")) { 02344 pin = ast_strdupa(var->value); 02345 } else if (!strcasecmp(var->name, "adminpin")) { 02346 pinadmin = ast_strdupa(var->value); 02347 } 02348 var = var->next; 02349 } 02350 ast_variables_destroy(var); 02351 02352 cnf = build_conf(confno, pin ? pin : "", pinadmin ? pinadmin : "", make, dynamic, refcount); 02353 } 02354 02355 if (cnf) { 02356 if (confflags && !cnf->chan && 02357 !ast_test_flag(confflags, CONFFLAG_QUIET) && 02358 ast_test_flag(confflags, CONFFLAG_INTROUSER)) { 02359 ast_log(LOG_WARNING, "No Zap channel available for conference, user introduction disabled (is chan_zap loaded?)\n"); 02360 ast_clear_flag(confflags, CONFFLAG_INTROUSER); 02361 } 02362 02363 if (confflags && !cnf->chan && 02364 ast_test_flag(confflags, CONFFLAG_RECORDCONF)) { 02365 ast_log(LOG_WARNING, "No Zap channel available for conference, conference recording disabled (is chan_zap loaded?)\n"); 02366 ast_clear_flag(confflags, CONFFLAG_RECORDCONF); 02367 } 02368 } 02369 02370 return cnf; 02371 }
static struct ast_conf_user* find_user | ( | struct ast_conference * | conf, | |
char * | callerident | |||
) | [static, read] |
Definition at line 2765 of file app_meetme.c.
References AST_LIST_TRAVERSE, and ast_conf_user::user_no.
02766 { 02767 struct ast_conf_user *user = NULL; 02768 int cid; 02769 02770 sscanf(callerident, "%i", &cid); 02771 if (conf && callerident) { 02772 AST_LIST_TRAVERSE(&conf->userlist, user, list) { 02773 if (cid == user->user_no) 02774 return user; 02775 } 02776 } 02777 return NULL; 02778 }
static char* istalking | ( | int | x | ) | [static] |
Definition at line 564 of file app_meetme.c.
Referenced by meetme_cmd().
00565 { 00566 if (x > 0) 00567 return "(talking)"; 00568 else if (x < 0) 00569 return "(unmonitored)"; 00570 else 00571 return "(not talking)"; 00572 }
static int load_config | ( | int | reload | ) | [static] |
Definition at line 4807 of file app_meetme.c.
References load_config_meetme(), and sla_load_config().
04808 { 04809 int res = 0; 04810 04811 load_config_meetme(); 04812 if (!reload) 04813 res = sla_load_config(); 04814 04815 return res; 04816 }
static void load_config_meetme | ( | void | ) | [static] |
Definition at line 3093 of file app_meetme.c.
References ast_config_destroy(), ast_config_load(), ast_log(), ast_variable_retrieve(), CONFIG_FILE_NAME, DEFAULT_AUDIO_BUFFERS, LOG_NOTICE, and LOG_WARNING.
Referenced by load_config().
03094 { 03095 struct ast_config *cfg; 03096 const char *val; 03097 03098 audio_buffers = DEFAULT_AUDIO_BUFFERS; 03099 03100 if (!(cfg = ast_config_load(CONFIG_FILE_NAME))) 03101 return; 03102 03103 if ((val = ast_variable_retrieve(cfg, "general", "audiobuffers"))) { 03104 if ((sscanf(val, "%d", &audio_buffers) != 1)) { 03105 ast_log(LOG_WARNING, "audiobuffers setting must be a number, not '%s'\n", val); 03106 audio_buffers = DEFAULT_AUDIO_BUFFERS; 03107 } else if ((audio_buffers < ZT_DEFAULT_NUM_BUFS) || (audio_buffers > ZT_MAX_NUM_BUFS)) { 03108 ast_log(LOG_WARNING, "audiobuffers setting must be between %d and %d\n", 03109 ZT_DEFAULT_NUM_BUFS, ZT_MAX_NUM_BUFS); 03110 audio_buffers = DEFAULT_AUDIO_BUFFERS; 03111 } 03112 if (audio_buffers != DEFAULT_AUDIO_BUFFERS) 03113 ast_log(LOG_NOTICE, "Audio buffers per channel set to %d\n", audio_buffers); 03114 } 03115 03116 ast_config_destroy(cfg); 03117 }
static int load_module | ( | void | ) | [static] |
Definition at line 4841 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(), conf_exec(), count_exec(), EVENT_FLAG_CALL, load_config(), meetmestate(), sla_state(), sla_station_exec(), and sla_trunk_exec().
04842 { 04843 int res = 0; 04844 04845 res |= load_config(0); 04846 04847 ast_cli_register_multiple(cli_meetme, ARRAY_LEN(cli_meetme)); 04848 res |= ast_manager_register("MeetmeMute", EVENT_FLAG_CALL, 04849 action_meetmemute, "Mute a Meetme user"); 04850 res |= ast_manager_register("MeetmeUnmute", EVENT_FLAG_CALL, 04851 action_meetmeunmute, "Unmute a Meetme user"); 04852 res |= ast_register_application(app3, admin_exec, synopsis3, descrip3); 04853 res |= ast_register_application(app2, count_exec, synopsis2, descrip2); 04854 res |= ast_register_application(app, conf_exec, synopsis, descrip); 04855 res |= ast_register_application(slastation_app, sla_station_exec, 04856 slastation_synopsis, slastation_desc); 04857 res |= ast_register_application(slatrunk_app, sla_trunk_exec, 04858 slatrunk_synopsis, slatrunk_desc); 04859 04860 res |= ast_devstate_prov_add("Meetme", meetmestate); 04861 res |= ast_devstate_prov_add("SLA", sla_state); 04862 04863 return res; 04864 }
static int meetme_cmd | ( | int | fd, | |
int | argc, | |||
char ** | argv | |||
) | [static] |
Definition at line 822 of file app_meetme.c.
References admin_exec(), ADMINFLAG_MUTED, ADMINFLAG_SELFMUTED, ast_conf_user::adminflags, ast_cli(), 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, LOG_DEBUG, ast_conference::markedusers, RESULT_SHOWUSAGE, RESULT_SUCCESS, S_OR, ast_conference::start, ast_conf_user::talking, total, ast_conf_user::user_no, ast_conf_user::userflags, and ast_conference::users.
00823 { 00824 /* Process the command */ 00825 struct ast_conference *cnf; 00826 struct ast_conf_user *user; 00827 int hr, min, sec; 00828 int i = 0, total = 0; 00829 time_t now; 00830 char *header_format = "%-14s %-14s %-10s %-8s %-8s\n"; 00831 char *data_format = "%-12.12s %4.4d %4.4s %02d:%02d:%02d %-8s\n"; 00832 char cmdline[1024] = ""; 00833 00834 if (argc > 8) 00835 ast_cli(fd, "Invalid Arguments.\n"); 00836 /* Check for length so no buffer will overflow... */ 00837 for (i = 0; i < argc; i++) { 00838 if (strlen(argv[i]) > 100) 00839 ast_cli(fd, "Invalid Arguments.\n"); 00840 } 00841 if (argc == 1) { 00842 /* 'MeetMe': List all the conferences */ 00843 now = time(NULL); 00844 AST_LIST_LOCK(&confs); 00845 if (AST_LIST_EMPTY(&confs)) { 00846 ast_cli(fd, "No active MeetMe conferences.\n"); 00847 AST_LIST_UNLOCK(&confs); 00848 return RESULT_SUCCESS; 00849 } 00850 ast_cli(fd, header_format, "Conf Num", "Parties", "Marked", "Activity", "Creation"); 00851 AST_LIST_TRAVERSE(&confs, cnf, list) { 00852 if (cnf->markedusers == 0) 00853 strcpy(cmdline, "N/A "); 00854 else 00855 snprintf(cmdline, sizeof(cmdline), "%4.4d", cnf->markedusers); 00856 hr = (now - cnf->start) / 3600; 00857 min = ((now - cnf->start) % 3600) / 60; 00858 sec = (now - cnf->start) % 60; 00859 00860 ast_cli(fd, data_format, cnf->confno, cnf->users, cmdline, hr, min, sec, cnf->isdynamic ? "Dynamic" : "Static"); 00861 00862 total += cnf->users; 00863 } 00864 AST_LIST_UNLOCK(&confs); 00865 ast_cli(fd, "* Total number of MeetMe users: %d\n", total); 00866 return RESULT_SUCCESS; 00867 } 00868 if (argc < 3) 00869 return RESULT_SHOWUSAGE; 00870 ast_copy_string(cmdline, argv[2], sizeof(cmdline)); /* Argv 2: conference number */ 00871 if (strstr(argv[1], "lock")) { 00872 if (strcmp(argv[1], "lock") == 0) { 00873 /* Lock */ 00874 strncat(cmdline, "|L", sizeof(cmdline) - strlen(cmdline) - 1); 00875 } else { 00876 /* Unlock */ 00877 strncat(cmdline, "|l", sizeof(cmdline) - strlen(cmdline) - 1); 00878 } 00879 } else if (strstr(argv[1], "mute")) { 00880 if (argc < 4) 00881 return RESULT_SHOWUSAGE; 00882 if (strcmp(argv[1], "mute") == 0) { 00883 /* Mute */ 00884 if (strcmp(argv[3], "all") == 0) { 00885 strncat(cmdline, "|N", sizeof(cmdline) - strlen(cmdline) - 1); 00886 } else { 00887 strncat(cmdline, "|M|", sizeof(cmdline) - strlen(cmdline) - 1); 00888 strncat(cmdline, argv[3], sizeof(cmdline) - strlen(cmdline) - 1); 00889 } 00890 } else { 00891 /* Unmute */ 00892 if (strcmp(argv[3], "all") == 0) { 00893 strncat(cmdline, "|n", sizeof(cmdline) - strlen(cmdline) - 1); 00894 } else { 00895 strncat(cmdline, "|m|", sizeof(cmdline) - strlen(cmdline) - 1); 00896 strncat(cmdline, argv[3], sizeof(cmdline) - strlen(cmdline) - 1); 00897 } 00898 } 00899 } else if (strcmp(argv[1], "kick") == 0) { 00900 if (argc < 4) 00901 return RESULT_SHOWUSAGE; 00902 if (strcmp(argv[3], "all") == 0) { 00903 /* Kick all */ 00904 strncat(cmdline, "|K", sizeof(cmdline) - strlen(cmdline) - 1); 00905 } else { 00906 /* Kick a single user */ 00907 strncat(cmdline, "|k|", sizeof(cmdline) - strlen(cmdline) - 1); 00908 strncat(cmdline, argv[3], sizeof(cmdline) - strlen(cmdline) - 1); 00909 } 00910 } else if(strcmp(argv[1], "list") == 0) { 00911 int concise = ( 4 == argc && ( !strcasecmp(argv[3], "concise") ) ); 00912 /* List all the users in a conference */ 00913 if (AST_LIST_EMPTY(&confs)) { 00914 if ( !concise ) 00915 ast_cli(fd, "No active conferences.\n"); 00916 return RESULT_SUCCESS; 00917 } 00918 /* Find the right conference */ 00919 AST_LIST_LOCK(&confs); 00920 AST_LIST_TRAVERSE(&confs, cnf, list) { 00921 if (strcmp(cnf->confno, argv[2]) == 0) 00922 break; 00923 } 00924 if (!cnf) { 00925 if ( !concise ) 00926 ast_cli(fd, "No such conference: %s.\n",argv[2]); 00927 AST_LIST_UNLOCK(&confs); 00928 return RESULT_SUCCESS; 00929 } 00930 /* Show all the users */ 00931 time(&now); 00932 AST_LIST_TRAVERSE(&cnf->userlist, user, list) { 00933 hr = (now - user->jointime) / 3600; 00934 min = ((now - user->jointime) % 3600) / 60; 00935 sec = (now - user->jointime) % 60; 00936 if ( !concise ) 00937 ast_cli(fd, "User #: %-2.2d %12.12s %-20.20s Channel: %s %s %s %s %s %02d:%02d:%02d\n", 00938 user->user_no, 00939 S_OR(user->chan->cid.cid_num, "<unknown>"), 00940 S_OR(user->chan->cid.cid_name, "<no name>"), 00941 user->chan->name, 00942 user->userflags & CONFFLAG_ADMIN ? "(Admin)" : "", 00943 user->userflags & CONFFLAG_MONITOR ? "(Listen only)" : "", 00944 user->adminflags & ADMINFLAG_MUTED ? "(Admin Muted)" : user->adminflags & ADMINFLAG_SELFMUTED ? "(Muted)" : "", 00945 istalking(user->talking), hr, min, sec); 00946 else 00947 ast_cli(fd, "%d!%s!%s!%s!%s!%s!%s!%d!%02d:%02d:%02d\n", 00948 user->user_no, 00949 S_OR(user->chan->cid.cid_num, ""), 00950 S_OR(user->chan->cid.cid_name, ""), 00951 user->chan->name, 00952 user->userflags & CONFFLAG_ADMIN ? "1" : "", 00953 user->userflags & CONFFLAG_MONITOR ? "1" : "", 00954 user->adminflags & (ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED) ? "1" : "", 00955 user->talking, hr, min, sec); 00956 00957 } 00958 if ( !concise ) 00959 ast_cli(fd,"%d users in that conference.\n",cnf->users); 00960 AST_LIST_UNLOCK(&confs); 00961 return RESULT_SUCCESS; 00962 } else 00963 return RESULT_SHOWUSAGE; 00964 ast_log(LOG_DEBUG, "Cmdline: %s\n", cmdline); 00965 admin_exec(NULL, cmdline); 00966 00967 return 0; 00968 }
static int meetmemute | ( | struct mansession * | s, | |
const struct message * | m, | |||
int | mute | |||
) | [static] |
Definition at line 2935 of file app_meetme.c.
References ADMINFLAG_MUTED, ADMINFLAG_SELFMUTED, ast_conf_user::adminflags, 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, LOG_NOTICE, and ast_conf_user::user_no.
Referenced by action_meetmemute(), and action_meetmeunmute().
02936 { 02937 struct ast_conference *conf; 02938 struct ast_conf_user *user; 02939 const char *confid = astman_get_header(m, "Meetme"); 02940 char *userid = ast_strdupa(astman_get_header(m, "Usernum")); 02941 int userno; 02942 02943 if (ast_strlen_zero(confid)) { 02944 astman_send_error(s, m, "Meetme conference not specified"); 02945 return 0; 02946 } 02947 02948 if (ast_strlen_zero(userid)) { 02949 astman_send_error(s, m, "Meetme user number not specified"); 02950 return 0; 02951 } 02952 02953 userno = strtoul(userid, &userid, 10); 02954 02955 if (*userid) { 02956 astman_send_error(s, m, "Invalid user number"); 02957 return 0; 02958 } 02959 02960 /* Look in the conference list */ 02961 AST_LIST_LOCK(&confs); 02962 AST_LIST_TRAVERSE(&confs, conf, list) { 02963 if (!strcmp(confid, conf->confno)) 02964 break; 02965 } 02966 02967 if (!conf) { 02968 AST_LIST_UNLOCK(&confs); 02969 astman_send_error(s, m, "Meetme conference does not exist"); 02970 return 0; 02971 } 02972 02973 AST_LIST_TRAVERSE(&conf->userlist, user, list) 02974 if (user->user_no == userno) 02975 break; 02976 02977 if (!user) { 02978 AST_LIST_UNLOCK(&confs); 02979 astman_send_error(s, m, "User number not found"); 02980 return 0; 02981 } 02982 02983 if (mute) 02984 user->adminflags |= ADMINFLAG_MUTED; /* request user muting */ 02985 else 02986 user->adminflags &= ~(ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED); /* request user unmuting */ 02987 02988 AST_LIST_UNLOCK(&confs); 02989 02990 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); 02991 02992 astman_send_ack(s, m, mute ? "User muted" : "User unmuted"); 02993 return 0; 02994 }
static int meetmestate | ( | const char * | data | ) | [static] |
Callback for devicestate providers.
Definition at line 3071 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, and ast_conference::users.
Referenced by load_module().
03072 { 03073 struct ast_conference *conf; 03074 03075 /* Find conference */ 03076 AST_LIST_LOCK(&confs); 03077 AST_LIST_TRAVERSE(&confs, conf, list) { 03078 if (!strcmp(data, conf->confno)) 03079 break; 03080 } 03081 AST_LIST_UNLOCK(&confs); 03082 if (!conf) 03083 return AST_DEVICE_INVALID; 03084 03085 03086 /* SKREP to fill */ 03087 if (!conf->users) 03088 return AST_DEVICE_NOT_INUSE; 03089 03090 return AST_DEVICE_INUSE; 03091 }
static struct sla_ringing_trunk* queue_ringing_trunk | ( | struct sla_trunk * | trunk | ) | [static, read] |
Definition at line 4298 of file app_meetme.c.
References ALL_TRUNK_REFS, ast_calloc, AST_LIST_INSERT_HEAD, ast_mutex_lock(), ast_mutex_unlock(), sla_ringing_trunk::ring_begin, 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().
04299 { 04300 struct sla_ringing_trunk *ringing_trunk; 04301 04302 if (!(ringing_trunk = ast_calloc(1, sizeof(*ringing_trunk)))) 04303 return NULL; 04304 04305 ringing_trunk->trunk = trunk; 04306 ringing_trunk->ring_begin = ast_tvnow(); 04307 04308 sla_change_trunk_state(trunk, SLA_TRUNK_STATE_RINGING, ALL_TRUNK_REFS, NULL); 04309 04310 ast_mutex_lock(&sla.lock); 04311 AST_LIST_INSERT_HEAD(&sla.ringing_trunks, ringing_trunk, entry); 04312 ast_mutex_unlock(&sla.lock); 04313 04314 sla_queue_event(SLA_EVENT_RINGING_TRUNK); 04315 04316 return ringing_trunk; 04317 }
static void * recordthread | ( | void * | args | ) | [static] |
Definition at line 3006 of file app_meetme.c.
References ast_closestream(), 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::frametype, ast_conference::lchan, ast_conference::listenlock, MEETME_RECORD_ACTIVE, MEETME_RECORD_OFF, MEETME_RECORD_TERMINATE, ast_conference::origframe, ast_conference::recordingfilename, ast_conference::recordingformat, s, and ast_conference::transframe.
03007 { 03008 struct ast_conference *cnf = args; 03009 struct ast_frame *f=NULL; 03010 int flags; 03011 struct ast_filestream *s=NULL; 03012 int res=0; 03013 int x; 03014 const char *oldrecordingfilename = NULL; 03015 03016 if (!cnf || !cnf->lchan) { 03017 pthread_exit(0); 03018 } 03019 03020 ast_stopstream(cnf->lchan); 03021 flags = O_CREAT|O_TRUNC|O_WRONLY; 03022 03023 03024 cnf->recording = MEETME_RECORD_ACTIVE; 03025 while (ast_waitfor(cnf->lchan, -1) > -1) { 03026 if (cnf->recording == MEETME_RECORD_TERMINATE) { 03027 AST_LIST_LOCK(&confs); 03028 AST_LIST_UNLOCK(&confs); 03029 break; 03030 } 03031 if (!s && cnf->recordingfilename && (cnf->recordingfilename != oldrecordingfilename)) { 03032 s = ast_writefile(cnf->recordingfilename, cnf->recordingformat, NULL, flags, 0, 0644); 03033 oldrecordingfilename = cnf->recordingfilename; 03034 } 03035 03036 f = ast_read(cnf->lchan); 03037 if (!f) { 03038 res = -1; 03039 break; 03040 } 03041 if (f->frametype == AST_FRAME_VOICE) { 03042 ast_mutex_lock(&cnf->listenlock); 03043 for (x=0;x<AST_FRAME_BITS;x++) { 03044 /* Free any translations that have occured */ 03045 if (cnf->transframe[x]) { 03046 ast_frfree(cnf->transframe[x]); 03047 cnf->transframe[x] = NULL; 03048 } 03049 } 03050 if (cnf->origframe) 03051 ast_frfree(cnf->origframe); 03052 cnf->origframe = ast_frdup(f); 03053 ast_mutex_unlock(&cnf->listenlock); 03054 if (s) 03055 res = ast_writestream(s, f); 03056 if (res) { 03057 ast_frfree(f); 03058 break; 03059 } 03060 } 03061 ast_frfree(f); 03062 } 03063 cnf->recording = MEETME_RECORD_OFF; 03064 if (s) 03065 ast_closestream(s); 03066 03067 pthread_exit(0); 03068 }
static int reload | ( | void | ) | [static] |
Definition at line 4866 of file app_meetme.c.
References load_config().
04867 { 04868 return load_config(1); 04869 }
static void reset_volumes | ( | struct ast_conf_user * | user | ) | [static] |
Definition at line 684 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 conf_run().
00685 { 00686 signed char zero_volume = 0; 00687 00688 ast_channel_setoption(user->chan, AST_OPTION_TXGAIN, &zero_volume, sizeof(zero_volume), 0); 00689 ast_channel_setoption(user->chan, AST_OPTION_RXGAIN, &zero_volume, sizeof(zero_volume), 0); 00690 }
static void* run_station | ( | void * | data | ) | [static] |
Definition at line 3252 of file app_meetme.c.
References admin_exec(), ALL_TRUNK_REFS, ast_answer(), ast_cond_signal(), ast_dial_destroy(), ast_dial_join(), ast_mutex_lock(), ast_mutex_unlock(), ast_set_flag, build_conf(), run_station_args::cond, run_station_args::cond_lock, conf_run(), CONFFLAG_MARKEDEXIT, CONFFLAG_PASS_DTMF, CONFFLAG_QUIET, CONFFLAG_SLA_STATION, dispose_conf(), ast_flags::flags, MAX_CONFNUM, sla_change_trunk_state(), SLA_TRUNK_STATE_IDLE, SLA_TRUNK_STATE_ONHOLD_BYME, run_station_args::station, and run_station_args::trunk_ref.
Referenced by sla_handle_dial_state_event().
03253 { 03254 struct sla_station *station; 03255 struct sla_trunk_ref *trunk_ref; 03256 char conf_name[MAX_CONFNUM]; 03257 struct ast_flags conf_flags = { 0 }; 03258 struct ast_conference *conf; 03259 03260 { 03261 struct run_station_args *args = data; 03262 station = args->station; 03263 trunk_ref = args->trunk_ref; 03264 ast_mutex_lock(args->cond_lock); 03265 ast_cond_signal(args->cond); 03266 ast_mutex_unlock(args->cond_lock); 03267 /* args is no longer valid here. */ 03268 } 03269 03270 ast_atomic_fetchadd_int((int *) &trunk_ref->trunk->active_stations, 1); 03271 snprintf(conf_name, sizeof(conf_name), "SLA_%s", trunk_ref->trunk->name); 03272 ast_set_flag(&conf_flags, 03273 CONFFLAG_QUIET | CONFFLAG_MARKEDEXIT | CONFFLAG_PASS_DTMF | CONFFLAG_SLA_STATION); 03274 ast_answer(trunk_ref->chan); 03275 conf = build_conf(conf_name, "", "", 0, 0, 1); 03276 if (conf) { 03277 conf_run(trunk_ref->chan, conf, conf_flags.flags, NULL); 03278 dispose_conf(conf); 03279 conf = NULL; 03280 } 03281 trunk_ref->chan = NULL; 03282 if (ast_atomic_dec_and_test((int *) &trunk_ref->trunk->active_stations) && 03283 trunk_ref->state != SLA_TRUNK_STATE_ONHOLD_BYME) { 03284 strncat(conf_name, "|K", sizeof(conf_name) - strlen(conf_name) - 1); 03285 admin_exec(NULL, conf_name); 03286 trunk_ref->trunk->hold_stations = 0; 03287 sla_change_trunk_state(trunk_ref->trunk, SLA_TRUNK_STATE_IDLE, ALL_TRUNK_REFS, NULL); 03288 } 03289 03290 ast_dial_join(station->dial); 03291 ast_dial_destroy(station->dial); 03292 station->dial = NULL; 03293 03294 return NULL; 03295 }
static int set_listen_volume | ( | struct ast_conf_user * | user, | |
int | volume | |||
) | [static] |
Definition at line 613 of file app_meetme.c.
References ast_channel_setoption(), AST_OPTION_TXGAIN, and ast_conf_user::chan.
Referenced by tweak_listen_volume().
00614 { 00615 char gain_adjust; 00616 00617 /* attempt to make the adjustment in the channel driver; 00618 if successful, don't adjust in the frame reading routine 00619 */ 00620 gain_adjust = gain_map[volume + 5]; 00621 00622 return ast_channel_setoption(user->chan, AST_OPTION_TXGAIN, &gain_adjust, sizeof(gain_adjust), 0); 00623 }
static int set_talk_volume | ( | struct ast_conf_user * | user, | |
int | volume | |||
) | [static] |
Definition at line 601 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().
00602 { 00603 char gain_adjust; 00604 00605 /* attempt to make the adjustment in the channel driver; 00606 if successful, don't adjust in the frame reading routine 00607 */ 00608 gain_adjust = gain_map[volume + 5]; 00609 00610 return ast_channel_setoption(user->chan, AST_OPTION_RXGAIN, &gain_adjust, sizeof(gain_adjust), 0); 00611 }
static void sla_add_trunk_to_station | ( | struct sla_station * | station, | |
struct ast_variable * | var | |||
) | [static] |
Definition at line 4600 of file app_meetme.c.
References AST_LIST_INSERT_TAIL, ast_log(), AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_strdupa, create_trunk_ref(), free, LOG_ERROR, LOG_WARNING, name, sla_create_station_ref(), SLA_TRUNK_STATE_IDLE, strsep(), and ast_variable::value.
Referenced by sla_build_station().
04601 { 04602 struct sla_trunk *trunk; 04603 struct sla_trunk_ref *trunk_ref; 04604 struct sla_station_ref *station_ref; 04605 char *trunk_name, *options, *cur; 04606 04607 options = ast_strdupa(var->value); 04608 trunk_name = strsep(&options, ","); 04609 04610 AST_RWLIST_RDLOCK(&sla_trunks); 04611 AST_RWLIST_TRAVERSE(&sla_trunks, trunk, entry) { 04612 if (!strcasecmp(trunk->name, trunk_name)) 04613 break; 04614 } 04615 04616 AST_RWLIST_UNLOCK(&sla_trunks); 04617 if (!trunk) { 04618 ast_log(LOG_ERROR, "Trunk '%s' not found!\n", var->value); 04619 return; 04620 } 04621 if (!(trunk_ref = create_trunk_ref(trunk))) 04622 return; 04623 trunk_ref->state = SLA_TRUNK_STATE_IDLE; 04624 04625 while ((cur = strsep(&options, ","))) { 04626 char *name, *value = cur; 04627 name = strsep(&value, "="); 04628 if (!strcasecmp(name, "ringtimeout")) { 04629 if (sscanf(value, "%u", &trunk_ref->ring_timeout) != 1) { 04630 ast_log(LOG_WARNING, "Invalid ringtimeout value '%s' for " 04631 "trunk '%s' on station '%s'\n", value, trunk->name, station->name); 04632 trunk_ref->ring_timeout = 0; 04633 } 04634 } else if (!strcasecmp(name, "ringdelay")) { 04635 if (sscanf(value, "%u", &trunk_ref->ring_delay) != 1) { 04636 ast_log(LOG_WARNING, "Invalid ringdelay value '%s' for " 04637 "trunk '%s' on station '%s'\n", value, trunk->name, station->name); 04638 trunk_ref->ring_delay = 0; 04639 } 04640 } else { 04641 ast_log(LOG_WARNING, "Invalid option '%s' for " 04642 "trunk '%s' on station '%s'\n", name, trunk->name, station->name); 04643 } 04644 } 04645 04646 if (!(station_ref = sla_create_station_ref(station))) { 04647 free(trunk_ref); 04648 return; 04649 } 04650 ast_atomic_fetchadd_int((int *) &trunk->num_stations, 1); 04651 AST_RWLIST_WRLOCK(&sla_trunks); 04652 AST_LIST_INSERT_TAIL(&trunk->stations, station_ref, entry); 04653 AST_RWLIST_UNLOCK(&sla_trunks); 04654 AST_LIST_INSERT_TAIL(&station->trunks, trunk_ref, entry); 04655 }
static int sla_build_station | ( | struct ast_config * | cfg, | |
const char * | cat | |||
) | [static] |
Definition at line 4657 of file app_meetme.c.
References ast_add_extension2(), ast_calloc, ast_context_find_or_create(), ast_free, AST_LIST_TRAVERSE, ast_log(), AST_MAX_APP, AST_MAX_EXTENSION, AST_RWLIST_INSERT_TAIL, AST_RWLIST_RDLOCK, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_strdup, ast_string_field_init, ast_string_field_set, ast_strlen_zero(), ast_variable_browse(), ast_variable_retrieve(), context, destroy_station(), exten, free, ast_variable::lineno, LOG_ERROR, LOG_WARNING, ast_variable::name, name, ast_variable::next, PRIORITY_HINT, sla_add_trunk_to_station(), SLA_CONFIG_FILE, SLA_HOLD_OPEN, SLA_HOLD_PRIVATE, sla_registrar, ast_variable::value, and var.
Referenced by sla_load_config().
04658 { 04659 struct sla_station *station; 04660 struct ast_variable *var; 04661 const char *dev; 04662 04663 if (!(dev = ast_variable_retrieve(cfg, cat, "device"))) { 04664 ast_log(LOG_ERROR, "SLA Station '%s' defined with no device!\n", cat); 04665 return -1; 04666 } 04667 04668 if (!(station = ast_calloc(1, sizeof(*station)))) 04669 return -1; 04670 if (ast_string_field_init(station, 32)) { 04671 free(station); 04672 return -1; 04673 } 04674 04675 ast_string_field_set(station, name, cat); 04676 ast_string_field_set(station, device, dev); 04677 04678 for (var = ast_variable_browse(cfg, cat); var; var = var->next) { 04679 if (!strcasecmp(var->name, "trunk")) 04680 sla_add_trunk_to_station(station, var); 04681 else if (!strcasecmp(var->name, "autocontext")) 04682 ast_string_field_set(station, autocontext, var->value); 04683 else if (!strcasecmp(var->name, "ringtimeout")) { 04684 if (sscanf(var->value, "%u", &station->ring_timeout) != 1) { 04685 ast_log(LOG_WARNING, "Invalid ringtimeout '%s' specified for station '%s'\n", 04686 var->value, station->name); 04687 station->ring_timeout = 0; 04688 } 04689 } else if (!strcasecmp(var->name, "ringdelay")) { 04690 if (sscanf(var->value, "%u", &station->ring_delay) != 1) { 04691 ast_log(LOG_WARNING, "Invalid ringdelay '%s' specified for station '%s'\n", 04692 var->value, station->name); 04693 station->ring_delay = 0; 04694 } 04695 } else if (!strcasecmp(var->name, "hold")) { 04696 if (!strcasecmp(var->value, "private")) 04697 station->hold_access = SLA_HOLD_PRIVATE; 04698 else if (!strcasecmp(var->value, "open")) 04699 station->hold_access = SLA_HOLD_OPEN; 04700 else { 04701 ast_log(LOG_WARNING, "Invalid value '%s' for hold on station %s\n", 04702 var->value, station->name); 04703 } 04704 04705 } else if (strcasecmp(var->name, "type") && strcasecmp(var->name, "device")) { 04706 ast_log(LOG_ERROR, "Invalid option '%s' specified at line %d of %s!\n", 04707 var->name, var->lineno, SLA_CONFIG_FILE); 04708 } 04709 } 04710 04711 if (!ast_strlen_zero(station->autocontext)) { 04712 struct ast_context *context; 04713 struct sla_trunk_ref *trunk_ref; 04714 context = ast_context_find_or_create(NULL, station->autocontext, sla_registrar); 04715 if (!context) { 04716 ast_log(LOG_ERROR, "Failed to automatically find or create " 04717 "context '%s' for SLA!\n", station->autocontext); 04718 destroy_station(station); 04719 return -1; 04720 } 04721 /* The extension for when the handset goes off-hook. 04722 * exten => station1,1,SLAStation(station1) */ 04723 if (ast_add_extension2(context, 0 /* don't replace */, station->name, 1, 04724 NULL, NULL, slastation_app, ast_strdup(station->name), ast_free, sla_registrar)) { 04725 ast_log(LOG_ERROR, "Failed to automatically create extension " 04726 "for trunk '%s'!\n", station->name); 04727 destroy_station(station); 04728 return -1; 04729 } 04730 AST_RWLIST_RDLOCK(&sla_trunks); 04731 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) { 04732 char exten[AST_MAX_EXTENSION]; 04733 char hint[AST_MAX_APP]; 04734 snprintf(exten, sizeof(exten), "%s_%s", station->name, trunk_ref->trunk->name); 04735 snprintf(hint, sizeof(hint), "SLA:%s", exten); 04736 /* Extension for this line button 04737 * exten => station1_line1,1,SLAStation(station1_line1) */ 04738 if (ast_add_extension2(context, 0 /* don't replace */, exten, 1, 04739 NULL, NULL, slastation_app, ast_strdup(exten), ast_free, sla_registrar)) { 04740 ast_log(LOG_ERROR, "Failed to automatically create extension " 04741 "for trunk '%s'!\n", station->name); 04742 destroy_station(station); 04743 return -1; 04744 } 04745 /* Hint for this line button 04746 * exten => station1_line1,hint,SLA:station1_line1 */ 04747 if (ast_add_extension2(context, 0 /* don't replace */, exten, PRIORITY_HINT, 04748 NULL, NULL, hint, NULL, NULL, sla_registrar)) { 04749 ast_log(LOG_ERROR, "Failed to automatically create hint " 04750 "for trunk '%s'!\n", station->name); 04751 destroy_station(station); 04752 return -1; 04753 } 04754 } 04755 AST_RWLIST_UNLOCK(&sla_trunks); 04756 } 04757 04758 AST_RWLIST_WRLOCK(&sla_stations); 04759 AST_RWLIST_INSERT_TAIL(&sla_stations, station, entry); 04760 AST_RWLIST_UNLOCK(&sla_stations); 04761 04762 return 0; 04763 }
static int sla_build_trunk | ( | struct ast_config * | cfg, | |
const char * | cat | |||
) | [static] |
Definition at line 4522 of file app_meetme.c.
References ast_add_extension2(), ast_calloc, ast_context_find_or_create(), ast_false(), ast_free, ast_log(), AST_RWLIST_INSERT_TAIL, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_strdup, ast_string_field_init, ast_string_field_set, ast_strlen_zero(), ast_variable_browse(), ast_variable_retrieve(), context, destroy_trunk(), free, ast_variable::lineno, LOG_ERROR, LOG_WARNING, ast_variable::name, name, ast_variable::next, sla_check_device(), SLA_CONFIG_FILE, SLA_HOLD_OPEN, SLA_HOLD_PRIVATE, sla_registrar, ast_variable::value, and var.
Referenced by sla_load_config().
04523 { 04524 struct sla_trunk *trunk; 04525 struct ast_variable *var; 04526 const char *dev; 04527 04528 if (!(dev = ast_variable_retrieve(cfg, cat, "device"))) { 04529 ast_log(LOG_ERROR, "SLA Trunk '%s' defined with no device!\n", cat); 04530 return -1; 04531 } 04532 04533 if (sla_check_device(dev)) { 04534 ast_log(LOG_ERROR, "SLA Trunk '%s' define with invalid device '%s'!\n", 04535 cat, dev); 04536 return -1; 04537 } 04538 04539 if (!(trunk = ast_calloc(1, sizeof(*trunk)))) 04540 return -1; 04541 if (ast_string_field_init(trunk, 32)) { 04542 free(trunk); 04543 return -1; 04544 } 04545 04546 ast_string_field_set(trunk, name, cat); 04547 ast_string_field_set(trunk, device, dev); 04548 04549 for (var = ast_variable_browse(cfg, cat); var; var = var->next) { 04550 if (!strcasecmp(var->name, "autocontext")) 04551 ast_string_field_set(trunk, autocontext, var->value); 04552 else if (!strcasecmp(var->name, "ringtimeout")) { 04553 if (sscanf(var->value, "%u", &trunk->ring_timeout) != 1) { 04554 ast_log(LOG_WARNING, "Invalid ringtimeout '%s' specified for trunk '%s'\n", 04555 var->value, trunk->name); 04556 trunk->ring_timeout = 0; 04557 } 04558 } else if (!strcasecmp(var->name, "barge")) 04559 trunk->barge_disabled = ast_false(var->value); 04560 else if (!strcasecmp(var->name, "hold")) { 04561 if (!strcasecmp(var->value, "private")) 04562 trunk->hold_access = SLA_HOLD_PRIVATE; 04563 else if (!strcasecmp(var->value, "open")) 04564 trunk->hold_access = SLA_HOLD_OPEN; 04565 else { 04566 ast_log(LOG_WARNING, "Invalid value '%s' for hold on trunk %s\n", 04567 var->value, trunk->name); 04568 } 04569 } else if (strcasecmp(var->name, "type") && strcasecmp(var->name, "device")) { 04570 ast_log(LOG_ERROR, "Invalid option '%s' specified at line %d of %s!\n", 04571 var->name, var->lineno, SLA_CONFIG_FILE); 04572 } 04573 } 04574 04575 if (!ast_strlen_zero(trunk->autocontext)) { 04576 struct ast_context *context; 04577 context = ast_context_find_or_create(NULL, trunk->autocontext, sla_registrar); 04578 if (!context) { 04579 ast_log(LOG_ERROR, "Failed to automatically find or create " 04580 "context '%s' for SLA!\n", trunk->autocontext); 04581 destroy_trunk(trunk); 04582 return -1; 04583 } 04584 if (ast_add_extension2(context, 0 /* don't replace */, "s", 1, 04585 NULL, NULL, slatrunk_app, ast_strdup(trunk->name), ast_free, sla_registrar)) { 04586 ast_log(LOG_ERROR, "Failed to automatically create extension " 04587 "for trunk '%s'!\n", trunk->name); 04588 destroy_trunk(trunk); 04589 return -1; 04590 } 04591 } 04592 04593 AST_RWLIST_WRLOCK(&sla_trunks); 04594 AST_RWLIST_INSERT_TAIL(&sla_trunks, trunk, entry); 04595 AST_RWLIST_UNLOCK(&sla_trunks); 04596 04597 return 0; 04598 }
static int sla_calc_station_delays | ( | unsigned int * | timeout | ) | [static] |
Calculate the ring delay for a station.
Definition at line 3869 of file app_meetme.c.
References AST_LIST_TRAVERSE, sla_check_inuse_station(), sla_check_ringing_station(), sla_check_station_delay(), and sla_choose_ringing_trunk().
Referenced by sla_process_timers().
03870 { 03871 struct sla_station *station; 03872 int res = 0; 03873 03874 AST_LIST_TRAVERSE(&sla_stations, station, entry) { 03875 struct sla_ringing_trunk *ringing_trunk; 03876 int time_left; 03877 03878 /* Ignore stations already ringing */ 03879 if (sla_check_ringing_station(station)) 03880 continue; 03881 03882 /* Ignore stations already on a call */ 03883 if (sla_check_inuse_station(station)) 03884 continue; 03885 03886 /* Ignore stations that don't have one of their trunks ringing */ 03887 if (!(ringing_trunk = sla_choose_ringing_trunk(station, NULL, 0))) 03888 continue; 03889 03890 if ((time_left = sla_check_station_delay(station, ringing_trunk)) == INT_MAX) 03891 continue; 03892 03893 /* If there is no time left, then the station needs to start ringing. 03894 * Return non-zero so that an event will be queued up an event to 03895 * make that happen. */ 03896 if (time_left <= 0) { 03897 res = 1; 03898 continue; 03899 } 03900 03901 if (time_left < *timeout) 03902 *timeout = time_left; 03903 } 03904 03905 return res; 03906 }
static int sla_calc_station_timeouts | ( | unsigned int * | timeout | ) | [static] |
Process station ring timeouts.
Definition at line 3786 of file app_meetme.c.
References AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, sla_ringing_station::ring_begin, sla_ringing_trunk::ring_begin, sla, SLA_STATION_HANGUP_TIMEOUT, sla_stop_ringing_station(), sla_ringing_station::station, and sla_ringing_trunk::trunk.
Referenced by sla_process_timers().
03787 { 03788 struct sla_ringing_trunk *ringing_trunk; 03789 struct sla_ringing_station *ringing_station; 03790 int res = 0; 03791 03792 AST_LIST_TRAVERSE_SAFE_BEGIN(&sla.ringing_stations, ringing_station, entry) { 03793 unsigned int ring_timeout = 0; 03794 int time_elapsed, time_left = INT_MAX, final_trunk_time_left = INT_MIN; 03795 struct sla_trunk_ref *trunk_ref; 03796 03797 /* If there are any ring timeouts specified for a specific trunk 03798 * on the station, then use the highest per-trunk ring timeout. 03799 * Otherwise, use the ring timeout set for the entire station. */ 03800 AST_LIST_TRAVERSE(&ringing_station->station->trunks, trunk_ref, entry) { 03801 struct sla_station_ref *station_ref; 03802 int trunk_time_elapsed, trunk_time_left; 03803 03804 AST_LIST_TRAVERSE(&sla.ringing_trunks, ringing_trunk, entry) { 03805 if (ringing_trunk->trunk == trunk_ref->trunk) 03806 break; 03807 } 03808 if (!ringing_trunk) 03809 continue; 03810 03811 /* If there is a trunk that is ringing without a timeout, then the 03812 * only timeout that could matter is a global station ring timeout. */ 03813 if (!trunk_ref->ring_timeout) 03814 break; 03815 03816 /* This trunk on this station is ringing and has a timeout. 03817 * However, make sure this trunk isn't still ringing from a 03818 * previous timeout. If so, don't consider it. */ 03819 AST_LIST_TRAVERSE(&ringing_trunk->timed_out_stations, station_ref, entry) { 03820 if (station_ref->station == ringing_station->station) 03821 break; 03822 } 03823 if (station_ref) 03824 continue; 03825 03826 trunk_time_elapsed = ast_tvdiff_ms(ast_tvnow(), ringing_trunk->ring_begin); 03827 trunk_time_left = (trunk_ref->ring_timeout * 1000) - trunk_time_elapsed; 03828 if (trunk_time_left > final_trunk_time_left) 03829 final_trunk_time_left = trunk_time_left; 03830 } 03831 03832 /* No timeout was found for ringing trunks, and no timeout for the entire station */ 03833 if (final_trunk_time_left == INT_MIN && !ringing_station->station->ring_timeout) 03834 continue; 03835 03836 /* Compute how much time is left for a global station timeout */ 03837 if (ringing_station->station->ring_timeout) { 03838 ring_timeout = ringing_station->station->ring_timeout; 03839 time_elapsed = ast_tvdiff_ms(ast_tvnow(), ringing_station->ring_begin); 03840 time_left = (ring_timeout * 1000) - time_elapsed; 03841 } 03842 03843 /* If the time left based on the per-trunk timeouts is smaller than the 03844 * global station ring timeout, use that. */ 03845 if (final_trunk_time_left > INT_MIN && final_trunk_time_left < time_left) 03846 time_left = final_trunk_time_left; 03847 03848 /* If there is no time left, the station needs to stop ringing */ 03849 if (time_left <= 0) { 03850 AST_LIST_REMOVE_CURRENT(&sla.ringing_stations, entry); 03851 sla_stop_ringing_station(ringing_station, SLA_STATION_HANGUP_TIMEOUT); 03852 res = 1; 03853 continue; 03854 } 03855 03856 /* There is still some time left for this station to ring, so save that 03857 * timeout if it is the first event scheduled to occur */ 03858 if (time_left < *timeout) 03859 *timeout = time_left; 03860 } 03861 AST_LIST_TRAVERSE_SAFE_END 03862 03863 return res; 03864 }
static int sla_calc_trunk_timeouts | ( | unsigned int * | timeout | ) | [static] |
Process trunk ring timeouts.
Definition at line 3756 of file app_meetme.c.
References AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, pbx_builtin_setvar_helper(), sla_ringing_trunk::ring_begin, sla, sla_stop_ringing_trunk(), and sla_ringing_trunk::trunk.
Referenced by sla_process_timers().
03757 { 03758 struct sla_ringing_trunk *ringing_trunk; 03759 int res = 0; 03760 03761 AST_LIST_TRAVERSE_SAFE_BEGIN(&sla.ringing_trunks, ringing_trunk, entry) { 03762 int time_left, time_elapsed; 03763 if (!ringing_trunk->trunk->ring_timeout) 03764 continue; 03765 time_elapsed = ast_tvdiff_ms(ast_tvnow(), ringing_trunk->ring_begin); 03766 time_left = (ringing_trunk->trunk->ring_timeout * 1000) - time_elapsed; 03767 if (time_left <= 0) { 03768 pbx_builtin_setvar_helper(ringing_trunk->trunk->chan, "SLATRUNK_STATUS", "RINGTIMEOUT"); 03769 AST_LIST_REMOVE_CURRENT(&sla.ringing_trunks, entry); 03770 sla_stop_ringing_trunk(ringing_trunk); 03771 res = 1; 03772 continue; 03773 } 03774 if (time_left < *timeout) 03775 *timeout = time_left; 03776 } 03777 AST_LIST_TRAVERSE_SAFE_END 03778 03779 return res; 03780 }
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 3227 of file app_meetme.c.
References ast_device_state_changed(), and AST_LIST_TRAVERSE.
Referenced by dial_trunk(), 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().
03229 { 03230 struct sla_station *station; 03231 struct sla_trunk_ref *trunk_ref; 03232 03233 AST_LIST_TRAVERSE(&sla_stations, station, entry) { 03234 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) { 03235 if (trunk_ref->trunk != trunk || (inactive_only ? trunk_ref->chan : 0) 03236 || trunk_ref == exclude) 03237 continue; 03238 trunk_ref->state = state; 03239 ast_device_state_changed("SLA:%s_%s", station->name, trunk->name); 03240 break; 03241 } 03242 } 03243 }
static int sla_check_device | ( | const char * | device | ) | [static] |
Definition at line 4509 of file app_meetme.c.
References ast_strdupa, ast_strlen_zero(), and strsep().
Referenced by sla_build_trunk().
04510 { 04511 char *tech, *tech_data; 04512 04513 tech_data = ast_strdupa(device); 04514 tech = strsep(&tech_data, "/"); 04515 04516 if (ast_strlen_zero(tech) || ast_strlen_zero(tech_data)) 04517 return -1; 04518 04519 return 0; 04520 }
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 3504 of file app_meetme.c.
References AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, free, sla_failed_station::last_try, sla, and sla_failed_station::station.
Referenced by sla_ring_stations().
03505 { 03506 struct sla_failed_station *failed_station; 03507 int res = 0; 03508 03509 AST_LIST_TRAVERSE_SAFE_BEGIN(&sla.failed_stations, failed_station, entry) { 03510 if (station != failed_station->station) 03511 continue; 03512 if (ast_tvdiff_ms(ast_tvnow(), failed_station->last_try) > 1000) { 03513 AST_LIST_REMOVE_CURRENT(&sla.failed_stations, entry); 03514 free(failed_station); 03515 break; 03516 } 03517 res = 1; 03518 } 03519 AST_LIST_TRAVERSE_SAFE_END 03520 03521 return res; 03522 }
static int sla_check_inuse_station | ( | const struct sla_station * | station | ) | [static] |
Check to see if a station is in use.
Definition at line 3590 of file app_meetme.c.
References AST_LIST_TRAVERSE.
Referenced by sla_calc_station_delays(), and sla_ring_stations().
03591 { 03592 struct sla_trunk_ref *trunk_ref; 03593 03594 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) { 03595 if (trunk_ref->chan) 03596 return 1; 03597 } 03598 03599 return 0; 03600 }
static int sla_check_ringing_station | ( | const struct sla_station * | station | ) | [static] |
Check to see if this station is already ringing.
Definition at line 3489 of file app_meetme.c.
References AST_LIST_TRAVERSE, sla, and sla_ringing_station::station.
Referenced by sla_calc_station_delays(), and sla_ring_stations().
03490 { 03491 struct sla_ringing_station *ringing_station; 03492 03493 AST_LIST_TRAVERSE(&sla.ringing_stations, ringing_station, entry) { 03494 if (station == ringing_station->station) 03495 return 1; 03496 } 03497 03498 return 0; 03499 }
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 3620 of file app_meetme.c.
References sla_ringing_trunk::ring_begin, sla_choose_ringing_trunk(), sla_find_trunk_ref(), and sla_ringing_trunk::trunk.
Referenced by sla_calc_station_delays(), and sla_ring_stations().
03622 { 03623 struct sla_trunk_ref *trunk_ref; 03624 unsigned int delay = UINT_MAX; 03625 int time_left, time_elapsed; 03626 03627 if (!ringing_trunk) 03628 ringing_trunk = sla_choose_ringing_trunk(station, &trunk_ref, 0); 03629 else 03630 trunk_ref = sla_find_trunk_ref(station, ringing_trunk->trunk); 03631 03632 if (!ringing_trunk || !trunk_ref) 03633 return delay; 03634 03635 /* If this station has a ring delay specific to the highest priority 03636 * ringing trunk, use that. Otherwise, use the ring delay specified 03637 * globally for the station. */ 03638 delay = trunk_ref->ring_delay; 03639 if (!delay) 03640 delay = station->ring_delay; 03641 if (!delay) 03642 return INT_MAX; 03643 03644 time_elapsed = ast_tvdiff_ms(ast_tvnow(), ringing_trunk->ring_begin); 03645 time_left = (delay * 1000) - time_elapsed; 03646 03647 return time_left; 03648 }
static int sla_check_station_hold_access | ( | const struct sla_trunk * | trunk, | |
const struct sla_station * | station | |||
) | [static] |
Definition at line 3149 of file app_meetme.c.
References AST_LIST_TRAVERSE, SLA_HOLD_PRIVATE, and SLA_TRUNK_STATE_ONHOLD_BYME.
Referenced by sla_find_trunk_ref_byname().
03151 { 03152 struct sla_station_ref *station_ref; 03153 struct sla_trunk_ref *trunk_ref; 03154 03155 /* For each station that has this call on hold, check for private hold. */ 03156 AST_LIST_TRAVERSE(&trunk->stations, station_ref, entry) { 03157 AST_LIST_TRAVERSE(&station_ref->station->trunks, trunk_ref, entry) { 03158 if (trunk_ref->trunk != trunk || station_ref->station == station) 03159 continue; 03160 if (trunk_ref->state == SLA_TRUNK_STATE_ONHOLD_BYME && 03161 station_ref->station->hold_access == SLA_HOLD_PRIVATE) 03162 return 1; 03163 return 0; 03164 } 03165 } 03166 03167 return 0; 03168 }
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 3355 of file app_meetme.c.
References AST_LIST_TRAVERSE.
Referenced by sla_choose_ringing_trunk(), and sla_ring_stations().
03357 { 03358 struct sla_station_ref *timed_out_station; 03359 03360 AST_LIST_TRAVERSE(&ringing_trunk->timed_out_stations, timed_out_station, entry) { 03361 if (station == timed_out_station->station) 03362 return 1; 03363 } 03364 03365 return 0; 03366 }
static struct sla_trunk_ref* sla_choose_idle_trunk | ( | const struct sla_station * | station | ) | [static, read] |
For a given station, choose the highest priority idle trunk.
Definition at line 4120 of file app_meetme.c.
References AST_LIST_TRAVERSE, and SLA_TRUNK_STATE_IDLE.
Referenced by sla_station_exec().
04121 { 04122 struct sla_trunk_ref *trunk_ref = NULL; 04123 04124 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) { 04125 if (trunk_ref->state == SLA_TRUNK_STATE_IDLE) 04126 break; 04127 } 04128 04129 return trunk_ref; 04130 }
static struct sla_ringing_trunk* sla_choose_ringing_trunk | ( | struct sla_station * | station, | |
struct sla_trunk_ref ** | trunk_ref, | |||
int | remove | |||
) | [static, read] |
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 3376 of file app_meetme.c.
References AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, sla, sla_check_timed_out_station(), and sla_ringing_trunk::trunk.
Referenced by sla_calc_station_delays(), sla_check_station_delay(), and sla_handle_dial_state_event().
03378 { 03379 struct sla_trunk_ref *s_trunk_ref; 03380 struct sla_ringing_trunk *ringing_trunk = NULL; 03381 03382 AST_LIST_TRAVERSE(&station->trunks, s_trunk_ref, entry) { 03383 AST_LIST_TRAVERSE_SAFE_BEGIN(&sla.ringing_trunks, ringing_trunk, entry) { 03384 /* Make sure this is the trunk we're looking for */ 03385 if (s_trunk_ref->trunk != ringing_trunk->trunk) 03386 continue; 03387 03388 /* This trunk on the station is ringing. But, make sure this station 03389 * didn't already time out while this trunk was ringing. */ 03390 if (sla_check_timed_out_station(ringing_trunk, station)) 03391 continue; 03392 03393 if (remove) 03394 AST_LIST_REMOVE_CURRENT(&sla.ringing_trunks, entry); 03395 03396 if (trunk_ref) 03397 *trunk_ref = s_trunk_ref; 03398 03399 break; 03400 } 03401 AST_LIST_TRAVERSE_SAFE_END 03402 03403 if (ringing_trunk) 03404 break; 03405 } 03406 03407 return ringing_trunk; 03408 }
static struct sla_ringing_station* sla_create_ringing_station | ( | struct sla_station * | station | ) | [static, read] |
Definition at line 3214 of file app_meetme.c.
References ast_calloc, sla_ringing_station::ring_begin, and sla_ringing_station::station.
Referenced by sla_ring_station().
03215 { 03216 struct sla_ringing_station *ringing_station; 03217 03218 if (!(ringing_station = ast_calloc(1, sizeof(*ringing_station)))) 03219 return NULL; 03220 03221 ringing_station->station = station; 03222 ringing_station->ring_begin = ast_tvnow(); 03223 03224 return ringing_station; 03225 }
static struct sla_station_ref* sla_create_station_ref | ( | struct sla_station * | station | ) | [static, read] |
Definition at line 3202 of file app_meetme.c.
References ast_calloc.
Referenced by sla_add_trunk_to_station(), and sla_stop_ringing_station().
03203 { 03204 struct sla_station_ref *station_ref; 03205 03206 if (!(station_ref = ast_calloc(1, sizeof(*station_ref)))) 03207 return NULL; 03208 03209 station_ref->station = station; 03210 03211 return station_ref; 03212 }
static void sla_destroy | ( | void | ) | [static] |
Definition at line 4479 of file app_meetme.c.
References ast_cond_destroy(), ast_cond_signal(), ast_context_destroy(), ast_mutex_destroy(), ast_mutex_lock(), ast_mutex_unlock(), AST_PTHREADT_NULL, AST_RWLIST_REMOVE_HEAD, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, destroy_station(), destroy_trunk(), sla, and sla_registrar.
Referenced by unload_module().
04480 { 04481 struct sla_trunk *trunk; 04482 struct sla_station *station; 04483 04484 AST_RWLIST_WRLOCK(&sla_trunks); 04485 while ((trunk = AST_RWLIST_REMOVE_HEAD(&sla_trunks, entry))) 04486 destroy_trunk(trunk); 04487 AST_RWLIST_UNLOCK(&sla_trunks); 04488 04489 AST_RWLIST_WRLOCK(&sla_stations); 04490 while ((station = AST_RWLIST_REMOVE_HEAD(&sla_stations, entry))) 04491 destroy_station(station); 04492 AST_RWLIST_UNLOCK(&sla_stations); 04493 04494 if (sla.thread != AST_PTHREADT_NULL) { 04495 ast_mutex_lock(&sla.lock); 04496 sla.stop = 1; 04497 ast_cond_signal(&sla.cond); 04498 ast_mutex_unlock(&sla.lock); 04499 pthread_join(sla.thread, NULL); 04500 } 04501 04502 /* Drop any created contexts from the dialplan */ 04503 ast_context_destroy(NULL, sla_registrar); 04504 04505 ast_mutex_destroy(&sla.lock); 04506 ast_cond_destroy(&sla.cond); 04507 }
static void sla_dial_state_callback | ( | struct ast_dial * | dial | ) | [static] |
Definition at line 3347 of file app_meetme.c.
References SLA_EVENT_DIAL_STATE, and sla_queue_event().
Referenced by sla_ring_station().
03348 { 03349 sla_queue_event(SLA_EVENT_DIAL_STATE); 03350 }
static struct sla_station* sla_find_station | ( | const char * | name | ) | [static, read] |
Find an SLA station by name.
Definition at line 3137 of file app_meetme.c.
References AST_RWLIST_TRAVERSE.
Referenced by sla_station_exec().
03138 { 03139 struct sla_station *station = NULL; 03140 03141 AST_RWLIST_TRAVERSE(&sla_stations, station, entry) { 03142 if (!strcasecmp(station->name, name)) 03143 break; 03144 } 03145 03146 return station; 03147 }
static struct sla_trunk* sla_find_trunk | ( | const char * | name | ) | [static, read] |
Find an SLA trunk by name.
Definition at line 3122 of file app_meetme.c.
References AST_RWLIST_TRAVERSE.
Referenced by sla_trunk_exec().
03123 { 03124 struct sla_trunk *trunk = NULL; 03125 03126 AST_RWLIST_TRAVERSE(&sla_trunks, trunk, entry) { 03127 if (!strcasecmp(trunk->name, name)) 03128 break; 03129 } 03130 03131 return trunk; 03132 }
static struct sla_trunk_ref* sla_find_trunk_ref | ( | const struct sla_station * | station, | |
const struct sla_trunk * | trunk | |||
) | [static, read] |
Definition at line 3602 of file app_meetme.c.
References AST_LIST_TRAVERSE.
Referenced by sla_check_station_delay().
03604 { 03605 struct sla_trunk_ref *trunk_ref = NULL; 03606 03607 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) { 03608 if (trunk_ref->trunk == trunk) 03609 break; 03610 } 03611 03612 return trunk_ref; 03613 }
static struct sla_trunk_ref* sla_find_trunk_ref_byname | ( | const struct sla_station * | station, | |
const char * | name | |||
) | [static, read] |
Find a trunk reference on a station by name.
station | the station | |
name | the trunk's name |
Definition at line 3177 of file app_meetme.c.
References AST_LIST_TRAVERSE, sla_check_station_hold_access(), SLA_HOLD_PRIVATE, SLA_TRUNK_STATE_ONHOLD_BYME, and SLA_TRUNK_STATE_UP.
Referenced by sla_station_exec().
03179 { 03180 struct sla_trunk_ref *trunk_ref = NULL; 03181 03182 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) { 03183 if (strcasecmp(trunk_ref->trunk->name, name)) 03184 continue; 03185 03186 if ( (trunk_ref->trunk->barge_disabled 03187 && trunk_ref->state == SLA_TRUNK_STATE_UP) || 03188 (trunk_ref->trunk->hold_stations 03189 && trunk_ref->trunk->hold_access == SLA_HOLD_PRIVATE 03190 && trunk_ref->state != SLA_TRUNK_STATE_ONHOLD_BYME) || 03191 sla_check_station_hold_access(trunk_ref->trunk, station) ) 03192 { 03193 trunk_ref = NULL; 03194 } 03195 03196 break; 03197 } 03198 03199 return trunk_ref; 03200 }
static void sla_handle_dial_state_event | ( | void | ) | [static] |
Definition at line 3410 of file app_meetme.c.
References ALL_TRUNK_REFS, ast_answer(), 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, ast_conference::attr, run_station_args::cond, run_station_args::cond_lock, free, LOG_DEBUG, 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().
03411 { 03412 struct sla_ringing_station *ringing_station; 03413 03414 AST_LIST_TRAVERSE_SAFE_BEGIN(&sla.ringing_stations, ringing_station, entry) { 03415 struct sla_trunk_ref *s_trunk_ref = NULL; 03416 struct sla_ringing_trunk *ringing_trunk = NULL; 03417 struct run_station_args args; 03418 enum ast_dial_result dial_res; 03419 pthread_attr_t attr; 03420 pthread_t dont_care; 03421 ast_mutex_t cond_lock; 03422 ast_cond_t cond; 03423 03424 switch ((dial_res = ast_dial_state(ringing_station->station->dial))) { 03425 case AST_DIAL_RESULT_HANGUP: 03426 case AST_DIAL_RESULT_INVALID: 03427 case AST_DIAL_RESULT_FAILED: 03428 case AST_DIAL_RESULT_TIMEOUT: 03429 case AST_DIAL_RESULT_UNANSWERED: 03430 AST_LIST_REMOVE_CURRENT(&sla.ringing_stations, entry); 03431 sla_stop_ringing_station(ringing_station, SLA_STATION_HANGUP_NORMAL); 03432 break; 03433 case AST_DIAL_RESULT_ANSWERED: 03434 AST_LIST_REMOVE_CURRENT(&sla.ringing_stations, entry); 03435 /* Find the appropriate trunk to answer. */ 03436 ast_mutex_lock(&sla.lock); 03437 ringing_trunk = sla_choose_ringing_trunk(ringing_station->station, &s_trunk_ref, 1); 03438 ast_mutex_unlock(&sla.lock); 03439 if (!ringing_trunk) { 03440 ast_log(LOG_DEBUG, "Found no ringing trunk for station '%s' to answer!\n", 03441 ringing_station->station->name); 03442 break; 03443 } 03444 /* Track the channel that answered this trunk */ 03445 s_trunk_ref->chan = ast_dial_answered(ringing_station->station->dial); 03446 /* Actually answer the trunk */ 03447 ast_answer(ringing_trunk->trunk->chan); 03448 sla_change_trunk_state(ringing_trunk->trunk, SLA_TRUNK_STATE_UP, ALL_TRUNK_REFS, NULL); 03449 /* Now, start a thread that will connect this station to the trunk. The rest of 03450 * the code here sets up the thread and ensures that it is able to save the arguments 03451 * before they are no longer valid since they are allocated on the stack. */ 03452 args.trunk_ref = s_trunk_ref; 03453 args.station = ringing_station->station; 03454 args.cond = &cond; 03455 args.cond_lock = &cond_lock; 03456 free(ringing_trunk); 03457 free(ringing_station); 03458 ast_mutex_init(&cond_lock); 03459 ast_cond_init(&cond, NULL); 03460 pthread_attr_init(&attr); 03461 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 03462 ast_mutex_lock(&cond_lock); 03463 ast_pthread_create_background(&dont_care, &attr, run_station, &args); 03464 ast_cond_wait(&cond, &cond_lock); 03465 ast_mutex_unlock(&cond_lock); 03466 ast_mutex_destroy(&cond_lock); 03467 ast_cond_destroy(&cond); 03468 pthread_attr_destroy(&attr); 03469 break; 03470 case AST_DIAL_RESULT_TRYING: 03471 case AST_DIAL_RESULT_RINGING: 03472 case AST_DIAL_RESULT_PROGRESS: 03473 case AST_DIAL_RESULT_PROCEEDING: 03474 break; 03475 } 03476 if (dial_res == AST_DIAL_RESULT_ANSWERED) { 03477 /* Queue up reprocessing ringing trunks, and then ringing stations again */ 03478 sla_queue_event(SLA_EVENT_RINGING_TRUNK); 03479 sla_queue_event(SLA_EVENT_DIAL_STATE); 03480 break; 03481 } 03482 } 03483 AST_LIST_TRAVERSE_SAFE_END 03484 }
static void sla_handle_hold_event | ( | struct sla_event * | event | ) | [static] |
Definition at line 3732 of file app_meetme.c.
References AST_CAUSE_NORMAL, AST_CONTROL_HOLD, ast_device_state_changed(), ast_indicate(), ast_softhangup(), INACTIVE_TRUNK_REFS, sla_change_trunk_state(), SLA_TRUNK_STATE_ONHOLD, SLA_TRUNK_STATE_ONHOLD_BYME, sla_event::station, and sla_event::trunk_ref.
Referenced by sla_thread().
03733 { 03734 ast_atomic_fetchadd_int((int *) &event->trunk_ref->trunk->hold_stations, 1); 03735 event->trunk_ref->state = SLA_TRUNK_STATE_ONHOLD_BYME; 03736 ast_device_state_changed("SLA:%s_%s", 03737 event->station->name, event->trunk_ref->trunk->name); 03738 sla_change_trunk_state(event->trunk_ref->trunk, SLA_TRUNK_STATE_ONHOLD, 03739 INACTIVE_TRUNK_REFS, event->trunk_ref); 03740 03741 if (event->trunk_ref->trunk->active_stations == 1) { 03742 /* The station putting it on hold is the only one on the call, so start 03743 * Music on hold to the trunk. */ 03744 event->trunk_ref->trunk->on_hold = 1; 03745 ast_indicate(event->trunk_ref->trunk->chan, AST_CONTROL_HOLD); 03746 } 03747 03748 ast_softhangup(event->trunk_ref->chan, AST_CAUSE_NORMAL); 03749 event->trunk_ref->chan = NULL; 03750 }
static void sla_handle_ringing_trunk_event | ( | void | ) | [static] |
Definition at line 3722 of file app_meetme.c.
References ast_mutex_lock(), ast_mutex_unlock(), sla, sla_hangup_stations(), and sla_ring_stations().
Referenced by sla_thread().
03723 { 03724 ast_mutex_lock(&sla.lock); 03725 sla_ring_stations(); 03726 ast_mutex_unlock(&sla.lock); 03727 03728 /* Find stations that shouldn't be ringing anymore. */ 03729 sla_hangup_stations(); 03730 }
static void sla_hangup_stations | ( | void | ) | [static] |
Definition at line 3694 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(), free, sla, sla_ringing_station::station, and sla_ringing_trunk::trunk.
Referenced by sla_handle_ringing_trunk_event().
03695 { 03696 struct sla_trunk_ref *trunk_ref; 03697 struct sla_ringing_station *ringing_station; 03698 03699 AST_LIST_TRAVERSE_SAFE_BEGIN(&sla.ringing_stations, ringing_station, entry) { 03700 AST_LIST_TRAVERSE(&ringing_station->station->trunks, trunk_ref, entry) { 03701 struct sla_ringing_trunk *ringing_trunk; 03702 ast_mutex_lock(&sla.lock); 03703 AST_LIST_TRAVERSE(&sla.ringing_trunks, ringing_trunk, entry) { 03704 if (trunk_ref->trunk == ringing_trunk->trunk) 03705 break; 03706 } 03707 ast_mutex_unlock(&sla.lock); 03708 if (ringing_trunk) 03709 break; 03710 } 03711 if (!trunk_ref) { 03712 AST_LIST_REMOVE_CURRENT(&sla.ringing_stations, entry); 03713 ast_dial_join(ringing_station->station->dial); 03714 ast_dial_destroy(ringing_station->station->dial); 03715 ringing_station->station->dial = NULL; 03716 free(ringing_station); 03717 } 03718 } 03719 AST_LIST_TRAVERSE_SAFE_END 03720 }
static const char* sla_hold_str | ( | unsigned int | hold_access | ) | [static] |
Definition at line 1036 of file app_meetme.c.
References SLA_HOLD_OPEN, and SLA_HOLD_PRIVATE.
Referenced by sla_show_stations(), and sla_show_trunks().
01037 { 01038 const char *hold = "Unknown"; 01039 01040 switch (hold_access) { 01041 case SLA_HOLD_OPEN: 01042 hold = "Open"; 01043 break; 01044 case SLA_HOLD_PRIVATE: 01045 hold = "Private"; 01046 default: 01047 break; 01048 } 01049 01050 return hold; 01051 }
static int sla_load_config | ( | void | ) | [static] |
Definition at line 4765 of file app_meetme.c.
References ast_category_browse(), ast_cond_init(), ast_config_destroy(), ast_config_load(), 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().
04766 { 04767 struct ast_config *cfg; 04768 const char *cat = NULL; 04769 int res = 0; 04770 const char *val; 04771 04772 ast_mutex_init(&sla.lock); 04773 ast_cond_init(&sla.cond, NULL); 04774 04775 if (!(cfg = ast_config_load(SLA_CONFIG_FILE))) 04776 return 0; /* Treat no config as normal */ 04777 04778 if ((val = ast_variable_retrieve(cfg, "general", "attemptcallerid"))) 04779 sla.attempt_callerid = ast_true(val); 04780 04781 while ((cat = ast_category_browse(cfg, cat)) && !res) { 04782 const char *type; 04783 if (!strcasecmp(cat, "general")) 04784 continue; 04785 if (!(type = ast_variable_retrieve(cfg, cat, "type"))) { 04786 ast_log(LOG_WARNING, "Invalid entry in %s defined with no type!\n", 04787 SLA_CONFIG_FILE); 04788 continue; 04789 } 04790 if (!strcasecmp(type, "trunk")) 04791 res = sla_build_trunk(cfg, cat); 04792 else if (!strcasecmp(type, "station")) 04793 res = sla_build_station(cfg, cat); 04794 else { 04795 ast_log(LOG_WARNING, "Entry in %s defined with invalid type '%s'!\n", 04796 SLA_CONFIG_FILE, type); 04797 } 04798 } 04799 04800 ast_config_destroy(cfg); 04801 04802 ast_pthread_create(&sla.thread, NULL, sla_thread, NULL); 04803 04804 return res; 04805 }
static int sla_process_timers | ( | struct timespec * | ts | ) | [static] |
Calculate the time until the next known event.
Definition at line 3910 of file app_meetme.c.
References ast_tvadd(), 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().
03911 { 03912 unsigned int timeout = UINT_MAX; 03913 struct timeval tv; 03914 unsigned int change_made = 0; 03915 03916 /* Check for ring timeouts on ringing trunks */ 03917 if (sla_calc_trunk_timeouts(&timeout)) 03918 change_made = 1; 03919 03920 /* Check for ring timeouts on ringing stations */ 03921 if (sla_calc_station_timeouts(&timeout)) 03922 change_made = 1; 03923 03924 /* Check for station ring delays */ 03925 if (sla_calc_station_delays(&timeout)) 03926 change_made = 1; 03927 03928 /* queue reprocessing of ringing trunks */ 03929 if (change_made) 03930 sla_queue_event_nolock(SLA_EVENT_RINGING_TRUNK); 03931 03932 /* No timeout */ 03933 if (timeout == UINT_MAX) 03934 return 0; 03935 03936 if (ts) { 03937 tv = ast_tvadd(ast_tvnow(), ast_samp2tv(timeout, 1000)); 03938 ts->tv_sec = tv.tv_sec; 03939 ts->tv_nsec = tv.tv_usec * 1000; 03940 } 03941 03942 return 1; 03943 }
static void sla_queue_event | ( | enum sla_event_type | type | ) | [static] |
Definition at line 1309 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().
01310 { 01311 sla_queue_event_full(type, NULL, NULL, 1); 01312 }
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 1315 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(), ast_conference::confno, LOG_DEBUG, LOG_ERROR, sla_queue_event_full(), and strsep().
Referenced by conf_run().
01317 { 01318 struct sla_station *station; 01319 struct sla_trunk_ref *trunk_ref = NULL; 01320 char *trunk_name; 01321 01322 trunk_name = ast_strdupa(conf->confno); 01323 strsep(&trunk_name, "_"); 01324 if (ast_strlen_zero(trunk_name)) { 01325 ast_log(LOG_ERROR, "Invalid conference name for SLA - '%s'!\n", conf->confno); 01326 return; 01327 } 01328 01329 AST_RWLIST_RDLOCK(&sla_stations); 01330 AST_RWLIST_TRAVERSE(&sla_stations, station, entry) { 01331 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) { 01332 if (trunk_ref->chan == chan && !strcmp(trunk_ref->trunk->name, trunk_name)) 01333 break; 01334 } 01335 if (trunk_ref) 01336 break; 01337 } 01338 AST_RWLIST_UNLOCK(&sla_stations); 01339 01340 if (!trunk_ref) { 01341 ast_log(LOG_DEBUG, "Trunk not found for event!\n"); 01342 return; 01343 } 01344 01345 sla_queue_event_full(type, trunk_ref, station, 1); 01346 }
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 1281 of file app_meetme.c.
References ast_calloc, ast_cond_signal(), AST_LIST_INSERT_TAIL, ast_mutex_lock(), ast_mutex_unlock(), event, and sla.
Referenced by sla_queue_event(), sla_queue_event_conf(), and sla_queue_event_nolock().
01283 { 01284 struct sla_event *event; 01285 01286 if (!(event = ast_calloc(1, sizeof(*event)))) 01287 return; 01288 01289 event->type = type; 01290 event->trunk_ref = trunk_ref; 01291 event->station = station; 01292 01293 if (!lock) { 01294 AST_LIST_INSERT_TAIL(&sla.event_q, event, entry); 01295 return; 01296 } 01297 01298 ast_mutex_lock(&sla.lock); 01299 AST_LIST_INSERT_TAIL(&sla.event_q, event, entry); 01300 ast_cond_signal(&sla.cond); 01301 ast_mutex_unlock(&sla.lock); 01302 }
static void sla_queue_event_nolock | ( | enum sla_event_type | type | ) | [static] |
Definition at line 1304 of file app_meetme.c.
References sla_queue_event_full().
Referenced by sla_process_timers().
01305 { 01306 sla_queue_event_full(type, NULL, NULL, 0); 01307 }
static int sla_ring_station | ( | struct sla_ringing_trunk * | ringing_trunk, | |
struct sla_station * | station | |||
) | [static] |
Ring a station.
Definition at line 3527 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(), cid_name, cid_num, free, sla_failed_station::last_try, sla, sla_create_ringing_station(), sla_dial_state_callback(), sla_failed_station::station, strsep(), and sla_ringing_trunk::trunk.
Referenced by sla_ring_stations().
03528 { 03529 char *tech, *tech_data; 03530 struct ast_dial *dial; 03531 struct sla_ringing_station *ringing_station; 03532 const char *cid_name = NULL, *cid_num = NULL; 03533 enum ast_dial_result res; 03534 03535 if (!(dial = ast_dial_create())) 03536 return -1; 03537 03538 ast_dial_set_state_callback(dial, sla_dial_state_callback); 03539 tech_data = ast_strdupa(station->device); 03540 tech = strsep(&tech_data, "/"); 03541 03542 if (ast_dial_append(dial, tech, tech_data) == -1) { 03543 ast_dial_destroy(dial); 03544 return -1; 03545 } 03546 03547 if (!sla.attempt_callerid && !ast_strlen_zero(ringing_trunk->trunk->chan->cid.cid_name)) { 03548 cid_name = ast_strdupa(ringing_trunk->trunk->chan->cid.cid_name); 03549 free(ringing_trunk->trunk->chan->cid.cid_name); 03550 ringing_trunk->trunk->chan->cid.cid_name = NULL; 03551 } 03552 if (!sla.attempt_callerid && !ast_strlen_zero(ringing_trunk->trunk->chan->cid.cid_num)) { 03553 cid_num = ast_strdupa(ringing_trunk->trunk->chan->cid.cid_num); 03554 free(ringing_trunk->trunk->chan->cid.cid_num); 03555 ringing_trunk->trunk->chan->cid.cid_num = NULL; 03556 } 03557 03558 res = ast_dial_run(dial, ringing_trunk->trunk->chan, 1); 03559 03560 if (cid_name) 03561 ringing_trunk->trunk->chan->cid.cid_name = ast_strdup(cid_name); 03562 if (cid_num) 03563 ringing_trunk->trunk->chan->cid.cid_num = ast_strdup(cid_num); 03564 03565 if (res != AST_DIAL_RESULT_TRYING) { 03566 struct sla_failed_station *failed_station; 03567 ast_dial_destroy(dial); 03568 if (!(failed_station = ast_calloc(1, sizeof(*failed_station)))) 03569 return -1; 03570 failed_station->station = station; 03571 failed_station->last_try = ast_tvnow(); 03572 AST_LIST_INSERT_HEAD(&sla.failed_stations, failed_station, entry); 03573 return -1; 03574 } 03575 if (!(ringing_station = sla_create_ringing_station(station))) { 03576 ast_dial_join(dial); 03577 ast_dial_destroy(dial); 03578 return -1; 03579 } 03580 03581 station->dial = dial; 03582 03583 AST_LIST_INSERT_HEAD(&sla.ringing_stations, ringing_station, entry); 03584 03585 return 0; 03586 }
static void sla_ring_stations | ( | void | ) | [static] |
Ring stations based on current set of ringing trunks.
Definition at line 3653 of file app_meetme.c.
References AST_LIST_TRAVERSE, 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(), and sla_ringing_trunk::trunk.
Referenced by sla_handle_ringing_trunk_event().
03654 { 03655 struct sla_station_ref *station_ref; 03656 struct sla_ringing_trunk *ringing_trunk; 03657 03658 /* Make sure that every station that uses at least one of the ringing 03659 * trunks, is ringing. */ 03660 AST_LIST_TRAVERSE(&sla.ringing_trunks, ringing_trunk, entry) { 03661 AST_LIST_TRAVERSE(&ringing_trunk->trunk->stations, station_ref, entry) { 03662 int time_left; 03663 03664 /* Is this station already ringing? */ 03665 if (sla_check_ringing_station(station_ref->station)) 03666 continue; 03667 03668 /* Is this station already in a call? */ 03669 if (sla_check_inuse_station(station_ref->station)) 03670 continue; 03671 03672 /* Did we fail to dial this station earlier? If so, has it been 03673 * a minute since we tried? */ 03674 if (sla_check_failed_station(station_ref->station)) 03675 continue; 03676 03677 /* If this station already timed out while this trunk was ringing, 03678 * do not dial it again for this ringing trunk. */ 03679 if (sla_check_timed_out_station(ringing_trunk, station_ref->station)) 03680 continue; 03681 03682 /* Check for a ring delay in progress */ 03683 time_left = sla_check_station_delay(station_ref->station, ringing_trunk); 03684 if (time_left != INT_MAX && time_left > 0) 03685 continue; 03686 03687 /* It is time to make this station begin to ring. Do it! */ 03688 sla_ring_station(ringing_trunk, station_ref->station); 03689 } 03690 } 03691 /* Now, all of the stations that should be ringing, are ringing. */ 03692 }
static int sla_show_stations | ( | int | fd, | |
int | argc, | |||
char ** | argv | |||
) | [static] |
Definition at line 1113 of file app_meetme.c.
References ast_cli(), AST_LIST_TRAVERSE, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, RESULT_SUCCESS, S_OR, sla_hold_str(), and trunkstate2str().
01114 { 01115 const struct sla_station *station; 01116 01117 ast_cli(fd, "\n" 01118 "=============================================================\n" 01119 "=== Configured SLA Stations =================================\n" 01120 "=============================================================\n" 01121 "===\n"); 01122 AST_RWLIST_RDLOCK(&sla_stations); 01123 AST_RWLIST_TRAVERSE(&sla_stations, station, entry) { 01124 struct sla_trunk_ref *trunk_ref; 01125 char ring_timeout[16] = "(none)"; 01126 char ring_delay[16] = "(none)"; 01127 if (station->ring_timeout) { 01128 snprintf(ring_timeout, sizeof(ring_timeout), 01129 "%u", station->ring_timeout); 01130 } 01131 if (station->ring_delay) { 01132 snprintf(ring_delay, sizeof(ring_delay), 01133 "%u", station->ring_delay); 01134 } 01135 ast_cli(fd, "=== ---------------------------------------------------------\n" 01136 "=== Station Name: %s\n" 01137 "=== ==> Device: %s\n" 01138 "=== ==> AutoContext: %s\n" 01139 "=== ==> RingTimeout: %s\n" 01140 "=== ==> RingDelay: %s\n" 01141 "=== ==> HoldAccess: %s\n" 01142 "=== ==> Trunks ...\n", 01143 station->name, station->device, 01144 S_OR(station->autocontext, "(none)"), 01145 ring_timeout, ring_delay, 01146 sla_hold_str(station->hold_access)); 01147 AST_RWLIST_RDLOCK(&sla_trunks); 01148 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) { 01149 if (trunk_ref->ring_timeout) { 01150 snprintf(ring_timeout, sizeof(ring_timeout), 01151 "%u", trunk_ref->ring_timeout); 01152 } else 01153 strcpy(ring_timeout, "(none)"); 01154 if (trunk_ref->ring_delay) { 01155 snprintf(ring_delay, sizeof(ring_delay), 01156 "%u", trunk_ref->ring_delay); 01157 } else 01158 strcpy(ring_delay, "(none)"); 01159 ast_cli(fd, "=== ==> Trunk Name: %s\n" 01160 "=== ==> State: %s\n" 01161 "=== ==> RingTimeout: %s\n" 01162 "=== ==> RingDelay: %s\n", 01163 trunk_ref->trunk->name, 01164 trunkstate2str(trunk_ref->state), 01165 ring_timeout, ring_delay); 01166 } 01167 AST_RWLIST_UNLOCK(&sla_trunks); 01168 ast_cli(fd, "=== ---------------------------------------------------------\n" 01169 "===\n"); 01170 } 01171 AST_RWLIST_UNLOCK(&sla_stations); 01172 ast_cli(fd, "============================================================\n" 01173 "\n"); 01174 01175 return RESULT_SUCCESS; 01176 }
static int sla_show_trunks | ( | int | fd, | |
int | argc, | |||
char ** | argv | |||
) | [static] |
Definition at line 1053 of file app_meetme.c.
References ast_cli(), AST_LIST_TRAVERSE, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, RESULT_SUCCESS, S_OR, and sla_hold_str().
01054 { 01055 const struct sla_trunk *trunk; 01056 01057 ast_cli(fd, "\n" 01058 "=============================================================\n" 01059 "=== Configured SLA Trunks ===================================\n" 01060 "=============================================================\n" 01061 "===\n"); 01062 AST_RWLIST_RDLOCK(&sla_trunks); 01063 AST_RWLIST_TRAVERSE(&sla_trunks, trunk, entry) { 01064 struct sla_station_ref *station_ref; 01065 char ring_timeout[16] = "(none)"; 01066 if (trunk->ring_timeout) 01067 snprintf(ring_timeout, sizeof(ring_timeout), "%u Seconds", trunk->ring_timeout); 01068 ast_cli(fd, "=== ---------------------------------------------------------\n" 01069 "=== Trunk Name: %s\n" 01070 "=== ==> Device: %s\n" 01071 "=== ==> AutoContext: %s\n" 01072 "=== ==> RingTimeout: %s\n" 01073 "=== ==> BargeAllowed: %s\n" 01074 "=== ==> HoldAccess: %s\n" 01075 "=== ==> Stations ...\n", 01076 trunk->name, trunk->device, 01077 S_OR(trunk->autocontext, "(none)"), 01078 ring_timeout, 01079 trunk->barge_disabled ? "No" : "Yes", 01080 sla_hold_str(trunk->hold_access)); 01081 AST_RWLIST_RDLOCK(&sla_stations); 01082 AST_LIST_TRAVERSE(&trunk->stations, station_ref, entry) 01083 ast_cli(fd, "=== ==> Station name: %s\n", station_ref->station->name); 01084 AST_RWLIST_UNLOCK(&sla_stations); 01085 ast_cli(fd, "=== ---------------------------------------------------------\n" 01086 "===\n"); 01087 } 01088 AST_RWLIST_UNLOCK(&sla_trunks); 01089 ast_cli(fd, "=============================================================\n" 01090 "\n"); 01091 01092 return RESULT_SUCCESS; 01093 }
static int sla_state | ( | const char * | data | ) | [static] |
Definition at line 4389 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, LOG_ERROR, SLA_TRUNK_STATE_IDLE, SLA_TRUNK_STATE_ONHOLD, SLA_TRUNK_STATE_ONHOLD_BYME, SLA_TRUNK_STATE_RINGING, SLA_TRUNK_STATE_UP, and strsep().
Referenced by load_module().
04390 { 04391 char *buf, *station_name, *trunk_name; 04392 struct sla_station *station; 04393 struct sla_trunk_ref *trunk_ref; 04394 int res = AST_DEVICE_INVALID; 04395 04396 trunk_name = buf = ast_strdupa(data); 04397 station_name = strsep(&trunk_name, "_"); 04398 04399 AST_RWLIST_RDLOCK(&sla_stations); 04400 AST_LIST_TRAVERSE(&sla_stations, station, entry) { 04401 if (strcasecmp(station_name, station->name)) 04402 continue; 04403 AST_RWLIST_RDLOCK(&sla_trunks); 04404 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) { 04405 if (!strcasecmp(trunk_name, trunk_ref->trunk->name)) 04406 break; 04407 } 04408 if (!trunk_ref) { 04409 AST_RWLIST_UNLOCK(&sla_trunks); 04410 break; 04411 } 04412 switch (trunk_ref->state) { 04413 case SLA_TRUNK_STATE_IDLE: 04414 res = AST_DEVICE_NOT_INUSE; 04415 break; 04416 case SLA_TRUNK_STATE_RINGING: 04417 res = AST_DEVICE_RINGING; 04418 break; 04419 case SLA_TRUNK_STATE_UP: 04420 res = AST_DEVICE_INUSE; 04421 break; 04422 case SLA_TRUNK_STATE_ONHOLD: 04423 case SLA_TRUNK_STATE_ONHOLD_BYME: 04424 res = AST_DEVICE_ONHOLD; 04425 break; 04426 } 04427 AST_RWLIST_UNLOCK(&sla_trunks); 04428 } 04429 AST_RWLIST_UNLOCK(&sla_stations); 04430 04431 if (res == AST_DEVICE_INVALID) { 04432 ast_log(LOG_ERROR, "Could not determine state for trunk %s on station %s!\n", 04433 trunk_name, station_name); 04434 } 04435 04436 return res; 04437 }
static int sla_station_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Definition at line 4132 of file app_meetme.c.
References admin_exec(), ALL_TRUNK_REFS, ast_answer(), 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(), ast_conference::attr, build_conf(), conf_run(), CONFFLAG_MARKEDEXIT, CONFFLAG_PASS_DTMF, CONFFLAG_QUIET, CONFFLAG_SLA_STATION, dial_trunk(), dispose_conf(), ast_flags::flags, free, LOG_DEBUG, LOG_NOTICE, LOG_WARNING, MAX_CONFNUM, 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, strsep(), sla_ringing_trunk::trunk, and dial_trunk_args::trunk_ref.
Referenced by load_module().
04133 { 04134 char *station_name, *trunk_name; 04135 struct sla_station *station; 04136 struct sla_trunk_ref *trunk_ref = NULL; 04137 char conf_name[MAX_CONFNUM]; 04138 struct ast_flags conf_flags = { 0 }; 04139 struct ast_conference *conf; 04140 04141 if (ast_strlen_zero(data)) { 04142 ast_log(LOG_WARNING, "Invalid Arguments to SLAStation!\n"); 04143 pbx_builtin_setvar_helper(chan, "SLASTATION_STATUS", "FAILURE"); 04144 return 0; 04145 } 04146 04147 trunk_name = ast_strdupa(data); 04148 station_name = strsep(&trunk_name, "_"); 04149 04150 if (ast_strlen_zero(station_name)) { 04151 ast_log(LOG_WARNING, "Invalid Arguments to SLAStation!\n"); 04152 pbx_builtin_setvar_helper(chan, "SLASTATION_STATUS", "FAILURE"); 04153 return 0; 04154 } 04155 04156 AST_RWLIST_RDLOCK(&sla_stations); 04157 station = sla_find_station(station_name); 04158 AST_RWLIST_UNLOCK(&sla_stations); 04159 04160 if (!station) { 04161 ast_log(LOG_WARNING, "Station '%s' not found!\n", station_name); 04162 pbx_builtin_setvar_helper(chan, "SLASTATION_STATUS", "FAILURE"); 04163 return 0; 04164 } 04165 04166 AST_RWLIST_RDLOCK(&sla_trunks); 04167 if (!ast_strlen_zero(trunk_name)) { 04168 trunk_ref = sla_find_trunk_ref_byname(station, trunk_name); 04169 } else 04170 trunk_ref = sla_choose_idle_trunk(station); 04171 AST_RWLIST_UNLOCK(&sla_trunks); 04172 04173 if (!trunk_ref) { 04174 if (ast_strlen_zero(trunk_name)) 04175 ast_log(LOG_NOTICE, "No trunks available for call.\n"); 04176 else { 04177 ast_log(LOG_NOTICE, "Can't join existing call on trunk " 04178 "'%s' due to access controls.\n", trunk_name); 04179 } 04180 pbx_builtin_setvar_helper(chan, "SLASTATION_STATUS", "CONGESTION"); 04181 return 0; 04182 } 04183 04184 if (trunk_ref->state == SLA_TRUNK_STATE_ONHOLD_BYME) { 04185 if (ast_atomic_dec_and_test((int *) &trunk_ref->trunk->hold_stations) == 1) 04186 sla_change_trunk_state(trunk_ref->trunk, SLA_TRUNK_STATE_UP, ALL_TRUNK_REFS, NULL); 04187 else { 04188 trunk_ref->state = SLA_TRUNK_STATE_UP; 04189 ast_device_state_changed("SLA:%s_%s", station->name, trunk_ref->trunk->name); 04190 } 04191 } else if (trunk_ref->state == SLA_TRUNK_STATE_RINGING) { 04192 struct sla_ringing_trunk *ringing_trunk; 04193 04194 ast_mutex_lock(&sla.lock); 04195 AST_LIST_TRAVERSE_SAFE_BEGIN(&sla.ringing_trunks, ringing_trunk, entry) { 04196 if (ringing_trunk->trunk == trunk_ref->trunk) { 04197 AST_LIST_REMOVE_CURRENT(&sla.ringing_trunks, entry); 04198 break; 04199 } 04200 } 04201 AST_LIST_TRAVERSE_SAFE_END 04202 ast_mutex_unlock(&sla.lock); 04203 04204 if (ringing_trunk) { 04205 ast_answer(ringing_trunk->trunk->chan); 04206 sla_change_trunk_state(ringing_trunk->trunk, SLA_TRUNK_STATE_UP, ALL_TRUNK_REFS, NULL); 04207 04208 free(ringing_trunk); 04209 04210 /* Queue up reprocessing ringing trunks, and then ringing stations again */ 04211 sla_queue_event(SLA_EVENT_RINGING_TRUNK); 04212 sla_queue_event(SLA_EVENT_DIAL_STATE); 04213 } 04214 } 04215 04216 trunk_ref->chan = chan; 04217 04218 if (!trunk_ref->trunk->chan) { 04219 ast_mutex_t cond_lock; 04220 ast_cond_t cond; 04221 pthread_t dont_care; 04222 pthread_attr_t attr; 04223 struct dial_trunk_args args = { 04224 .trunk_ref = trunk_ref, 04225 .station = station, 04226 .cond_lock = &cond_lock, 04227 .cond = &cond, 04228 }; 04229 sla_change_trunk_state(trunk_ref->trunk, SLA_TRUNK_STATE_UP, ALL_TRUNK_REFS, NULL); 04230 /* Create a thread to dial the trunk and dump it into the conference. 04231 * However, we want to wait until the trunk has been dialed and the 04232 * conference is created before continuing on here. */ 04233 ast_autoservice_start(chan); 04234 ast_mutex_init(&cond_lock); 04235 ast_cond_init(&cond, NULL); 04236 pthread_attr_init(&attr); 04237 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 04238 ast_mutex_lock(&cond_lock); 04239 ast_pthread_create_background(&dont_care, &attr, dial_trunk, &args); 04240 ast_cond_wait(&cond, &cond_lock); 04241 ast_mutex_unlock(&cond_lock); 04242 ast_mutex_destroy(&cond_lock); 04243 ast_cond_destroy(&cond); 04244 pthread_attr_destroy(&attr); 04245 ast_autoservice_stop(chan); 04246 if (!trunk_ref->trunk->chan) { 04247 ast_log(LOG_DEBUG, "Trunk didn't get created. chan: %lx\n", (long) trunk_ref->trunk->chan); 04248 pbx_builtin_setvar_helper(chan, "SLASTATION_STATUS", "CONGESTION"); 04249 sla_change_trunk_state(trunk_ref->trunk, SLA_TRUNK_STATE_IDLE, ALL_TRUNK_REFS, NULL); 04250 trunk_ref->chan = NULL; 04251 return 0; 04252 } 04253 } 04254 04255 if (ast_atomic_fetchadd_int((int *) &trunk_ref->trunk->active_stations, 1) == 0 && 04256 trunk_ref->trunk->on_hold) { 04257 trunk_ref->trunk->on_hold = 0; 04258 ast_indicate(trunk_ref->trunk->chan, AST_CONTROL_UNHOLD); 04259 sla_change_trunk_state(trunk_ref->trunk, SLA_TRUNK_STATE_UP, ALL_TRUNK_REFS, NULL); 04260 } 04261 04262 snprintf(conf_name, sizeof(conf_name), "SLA_%s", trunk_ref->trunk->name); 04263 ast_set_flag(&conf_flags, 04264 CONFFLAG_QUIET | CONFFLAG_MARKEDEXIT | CONFFLAG_PASS_DTMF | CONFFLAG_SLA_STATION); 04265 ast_answer(chan); 04266 conf = build_conf(conf_name, "", "", 0, 0, 1); 04267 if (conf) { 04268 conf_run(chan, conf, conf_flags.flags, NULL); 04269 dispose_conf(conf); 04270 conf = NULL; 04271 } 04272 trunk_ref->chan = NULL; 04273 if (ast_atomic_dec_and_test((int *) &trunk_ref->trunk->active_stations) && 04274 trunk_ref->state != SLA_TRUNK_STATE_ONHOLD_BYME) { 04275 strncat(conf_name, "|K", sizeof(conf_name) - strlen(conf_name) - 1); 04276 admin_exec(NULL, conf_name); 04277 trunk_ref->trunk->hold_stations = 0; 04278 sla_change_trunk_state(trunk_ref->trunk, SLA_TRUNK_STATE_IDLE, ALL_TRUNK_REFS, NULL); 04279 } 04280 04281 pbx_builtin_setvar_helper(chan, "SLASTATION_STATUS", "SUCCESS"); 04282 04283 return 0; 04284 }
static void sla_stop_ringing_station | ( | struct sla_ringing_station * | ringing_station, | |
enum sla_station_hangup | hangup | |||
) | [static] |
Definition at line 3312 of file app_meetme.c.
References ast_dial_destroy(), ast_dial_join(), AST_LIST_INSERT_TAIL, AST_LIST_TRAVERSE, free, sla, sla_create_station_ref(), SLA_STATION_HANGUP_NORMAL, sla_ringing_station::station, and sla_ringing_trunk::trunk.
Referenced by sla_calc_station_timeouts(), and sla_handle_dial_state_event().
03314 { 03315 struct sla_ringing_trunk *ringing_trunk; 03316 struct sla_trunk_ref *trunk_ref; 03317 struct sla_station_ref *station_ref; 03318 03319 ast_dial_join(ringing_station->station->dial); 03320 ast_dial_destroy(ringing_station->station->dial); 03321 ringing_station->station->dial = NULL; 03322 03323 if (hangup == SLA_STATION_HANGUP_NORMAL) 03324 goto done; 03325 03326 /* If the station is being hung up because of a timeout, then add it to the 03327 * list of timed out stations on each of the ringing trunks. This is so 03328 * that when doing further processing to figure out which stations should be 03329 * ringing, which trunk to answer, determining timeouts, etc., we know which 03330 * ringing trunks we should ignore. */ 03331 AST_LIST_TRAVERSE(&sla.ringing_trunks, ringing_trunk, entry) { 03332 AST_LIST_TRAVERSE(&ringing_station->station->trunks, trunk_ref, entry) { 03333 if (ringing_trunk->trunk == trunk_ref->trunk) 03334 break; 03335 } 03336 if (!trunk_ref) 03337 continue; 03338 if (!(station_ref = sla_create_station_ref(ringing_station->station))) 03339 continue; 03340 AST_LIST_INSERT_TAIL(&ringing_trunk->timed_out_stations, station_ref, entry); 03341 } 03342 03343 done: 03344 free(ringing_station); 03345 }
static void sla_stop_ringing_trunk | ( | struct sla_ringing_trunk * | ringing_trunk | ) | [static] |
Definition at line 3297 of file app_meetme.c.
References admin_exec(), ALL_TRUNK_REFS, AST_LIST_REMOVE_HEAD, free, sla_change_trunk_state(), SLA_TRUNK_STATE_IDLE, and sla_ringing_trunk::trunk.
Referenced by sla_calc_trunk_timeouts().
03298 { 03299 char buf[80]; 03300 struct sla_station_ref *station_ref; 03301 03302 snprintf(buf, sizeof(buf), "SLA_%s|K", ringing_trunk->trunk->name); 03303 admin_exec(NULL, buf); 03304 sla_change_trunk_state(ringing_trunk->trunk, SLA_TRUNK_STATE_IDLE, ALL_TRUNK_REFS, NULL); 03305 03306 while ((station_ref = AST_LIST_REMOVE_HEAD(&ringing_trunk->timed_out_stations, entry))) 03307 free(station_ref); 03308 03309 free(ringing_trunk); 03310 }
static void* sla_thread | ( | void * | data | ) | [static] |
Definition at line 3945 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(), event, 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().
03946 { 03947 struct sla_failed_station *failed_station; 03948 struct sla_ringing_station *ringing_station; 03949 03950 ast_mutex_lock(&sla.lock); 03951 03952 while (!sla.stop) { 03953 struct sla_event *event; 03954 struct timespec ts = { 0, }; 03955 unsigned int have_timeout = 0; 03956 03957 if (AST_LIST_EMPTY(&sla.event_q)) { 03958 if ((have_timeout = sla_process_timers(&ts))) 03959 ast_cond_timedwait(&sla.cond, &sla.lock, &ts); 03960 else 03961 ast_cond_wait(&sla.cond, &sla.lock); 03962 if (sla.stop) 03963 break; 03964 } 03965 03966 if (have_timeout) 03967 sla_process_timers(NULL); 03968 03969 while ((event = AST_LIST_REMOVE_HEAD(&sla.event_q, entry))) { 03970 ast_mutex_unlock(&sla.lock); 03971 switch (event->type) { 03972 case SLA_EVENT_HOLD: 03973 sla_handle_hold_event(event); 03974 break; 03975 case SLA_EVENT_DIAL_STATE: 03976 sla_handle_dial_state_event(); 03977 break; 03978 case SLA_EVENT_RINGING_TRUNK: 03979 sla_handle_ringing_trunk_event(); 03980 break; 03981 } 03982 free(event); 03983 ast_mutex_lock(&sla.lock); 03984 } 03985 } 03986 03987 ast_mutex_unlock(&sla.lock); 03988 03989 while ((ringing_station = AST_LIST_REMOVE_HEAD(&sla.ringing_stations, entry))) 03990 free(ringing_station); 03991 03992 while ((failed_station = AST_LIST_REMOVE_HEAD(&sla.failed_stations, entry))) 03993 free(failed_station); 03994 03995 return NULL; 03996 }
static int sla_trunk_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Definition at line 4319 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(), conf_run(), CONFFLAG_MARKEDEXIT, CONFFLAG_MARKEDUSER, CONFFLAG_PASS_DTMF, CONFFLAG_QUIET, dispose_conf(), ast_flags::flags, free, LOG_ERROR, MAX_CONFNUM, 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().
04320 { 04321 const char *trunk_name = data; 04322 char conf_name[MAX_CONFNUM]; 04323 struct ast_conference *conf; 04324 struct ast_flags conf_flags = { 0 }; 04325 struct sla_trunk *trunk; 04326 struct sla_ringing_trunk *ringing_trunk; 04327 04328 AST_RWLIST_RDLOCK(&sla_trunks); 04329 trunk = sla_find_trunk(trunk_name); 04330 AST_RWLIST_UNLOCK(&sla_trunks); 04331 if (!trunk) { 04332 ast_log(LOG_ERROR, "SLA Trunk '%s' not found!\n", trunk_name); 04333 pbx_builtin_setvar_helper(chan, "SLATRUNK_STATUS", "FAILURE"); 04334 return 0; 04335 } 04336 if (trunk->chan) { 04337 ast_log(LOG_ERROR, "Call came in on %s, but the trunk is already in use!\n", 04338 trunk_name); 04339 pbx_builtin_setvar_helper(chan, "SLATRUNK_STATUS", "FAILURE"); 04340 return 0; 04341 } 04342 trunk->chan = chan; 04343 04344 if (!(ringing_trunk = queue_ringing_trunk(trunk))) { 04345 pbx_builtin_setvar_helper(chan, "SLATRUNK_STATUS", "FAILURE"); 04346 return 0; 04347 } 04348 04349 snprintf(conf_name, sizeof(conf_name), "SLA_%s", trunk_name); 04350 conf = build_conf(conf_name, "", "", 1, 1, 1); 04351 if (!conf) { 04352 pbx_builtin_setvar_helper(chan, "SLATRUNK_STATUS", "FAILURE"); 04353 return 0; 04354 } 04355 ast_set_flag(&conf_flags, 04356 CONFFLAG_QUIET | CONFFLAG_MARKEDEXIT | CONFFLAG_MARKEDUSER | CONFFLAG_PASS_DTMF); 04357 ast_indicate(chan, AST_CONTROL_RINGING); 04358 conf_run(chan, conf, conf_flags.flags, NULL); 04359 dispose_conf(conf); 04360 conf = NULL; 04361 trunk->chan = NULL; 04362 trunk->on_hold = 0; 04363 04364 if (!pbx_builtin_getvar_helper(chan, "SLATRUNK_STATUS")) 04365 pbx_builtin_setvar_helper(chan, "SLATRUNK_STATUS", "SUCCESS"); 04366 04367 /* Remove the entry from the list of ringing trunks if it is still there. */ 04368 ast_mutex_lock(&sla.lock); 04369 AST_LIST_TRAVERSE_SAFE_BEGIN(&sla.ringing_trunks, ringing_trunk, entry) { 04370 if (ringing_trunk->trunk == trunk) { 04371 AST_LIST_REMOVE_CURRENT(&sla.ringing_trunks, entry); 04372 break; 04373 } 04374 } 04375 AST_LIST_TRAVERSE_SAFE_END 04376 ast_mutex_unlock(&sla.lock); 04377 if (ringing_trunk) { 04378 sla_change_trunk_state(ringing_trunk->trunk, SLA_TRUNK_STATE_IDLE, ALL_TRUNK_REFS, NULL); 04379 free(ringing_trunk); 04380 pbx_builtin_setvar_helper(chan, "SLATRUNK_STATUS", "UNANSWERED"); 04381 /* Queue reprocessing of ringing trunks to make stations stop ringing 04382 * that shouldn't be ringing after this trunk stopped. */ 04383 sla_queue_event(SLA_EVENT_RINGING_TRUNK); 04384 } 04385 04386 return 0; 04387 }
static const char* trunkstate2str | ( | enum sla_trunk_state | state | ) | [static] |
Definition at line 1095 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().
01096 { 01097 #define S(e) case e: return # e; 01098 switch (state) { 01099 S(SLA_TRUNK_STATE_IDLE) 01100 S(SLA_TRUNK_STATE_RINGING) 01101 S(SLA_TRUNK_STATE_UP) 01102 S(SLA_TRUNK_STATE_ONHOLD) 01103 S(SLA_TRUNK_STATE_ONHOLD_BYME) 01104 } 01105 return "Uknown State"; 01106 #undef S 01107 }
static void tweak_listen_volume | ( | struct ast_conf_user * | user, | |
enum volume_action | action | |||
) | [static] |
Definition at line 672 of file app_meetme.c.
References volume::actual, volume::desired, ast_conf_user::listen, set_listen_volume(), and tweak_volume().
Referenced by admin_exec(), and conf_run().
00673 { 00674 tweak_volume(&user->listen, action); 00675 /* attempt to make the adjustment in the channel driver; 00676 if successful, don't adjust in the frame reading routine 00677 */ 00678 if (!set_listen_volume(user, user->listen.desired)) 00679 user->listen.actual = 0; 00680 else 00681 user->listen.actual = user->listen.desired; 00682 }
static void tweak_talk_volume | ( | struct ast_conf_user * | user, | |
enum volume_action | action | |||
) | [static] |
Definition at line 660 of file app_meetme.c.
References volume::actual, volume::desired, set_talk_volume(), ast_conf_user::talk, and tweak_volume().
Referenced by admin_exec(), and conf_run().
00661 { 00662 tweak_volume(&user->talk, action); 00663 /* attempt to make the adjustment in the channel driver; 00664 if successful, don't adjust in the frame reading routine 00665 */ 00666 if (!set_talk_volume(user, user->talk.desired)) 00667 user->talk.actual = 0; 00668 else 00669 user->talk.actual = user->talk.desired; 00670 }
static void tweak_volume | ( | struct volume * | vol, | |
enum volume_action | action | |||
) | [static] |
Definition at line 625 of file app_meetme.c.
References volume::desired, VOL_DOWN, and VOL_UP.
Referenced by tweak_listen_volume(), and tweak_talk_volume().
00626 { 00627 switch (action) { 00628 case VOL_UP: 00629 switch (vol->desired) { 00630 case 5: 00631 break; 00632 case 0: 00633 vol->desired = 2; 00634 break; 00635 case -2: 00636 vol->desired = 0; 00637 break; 00638 default: 00639 vol->desired++; 00640 break; 00641 } 00642 break; 00643 case VOL_DOWN: 00644 switch (vol->desired) { 00645 case -5: 00646 break; 00647 case 2: 00648 vol->desired = 0; 00649 break; 00650 case 0: 00651 vol->desired = -2; 00652 break; 00653 default: 00654 vol->desired--; 00655 break; 00656 } 00657 } 00658 }
static int unload_module | ( | void | ) | [static] |
Definition at line 4818 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(), and sla_destroy().
04819 { 04820 int res = 0; 04821 04822 ast_cli_unregister_multiple(cli_meetme, ARRAY_LEN(cli_meetme)); 04823 res = ast_manager_unregister("MeetmeMute"); 04824 res |= ast_manager_unregister("MeetmeUnmute"); 04825 res |= ast_unregister_application(app3); 04826 res |= ast_unregister_application(app2); 04827 res |= ast_unregister_application(app); 04828 res |= ast_unregister_application(slastation_app); 04829 res |= ast_unregister_application(slatrunk_app); 04830 04831 ast_devstate_prov_del("Meetme"); 04832 ast_devstate_prov_del("SLA"); 04833 04834 ast_module_user_hangup_all(); 04835 04836 sla_destroy(); 04837 04838 return res; 04839 }
const char* app = "MeetMe" [static] |
Definition at line 200 of file app_meetme.c.
const char* app2 = "MeetMeCount" [static] |
Definition at line 201 of file app_meetme.c.
const char* app3 = "MeetMeAdmin" [static] |
Definition at line 202 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 538 of file app_meetme.c.
struct ast_cli_entry cli_meetme[] [static] |
Definition at line 1182 of file app_meetme.c.
Definition at line 522 of file app_meetme.c.
Referenced by _macro_exec(), and ast_safe_sleep_conditional().
unsigned int conf_map[1024] = {0, } [static] |
Definition at line 349 of file app_meetme.c.
Referenced by build_conf(), conf_exec(), and dispose_conf().
const char* descrip [static] |
Definition at line 212 of file app_meetme.c.
const char* descrip2 [static] |
Definition at line 260 of file app_meetme.c.
const char* descrip3 [static] |
Definition at line 268 of file app_meetme.c.
char const gain_map[] [static] |
Map 'volume' levels from -5 through +5 into decibel (dB) settings for channel drivers Note: these are not a straight linear-to-dB conversion... the numbers have been modified to give the user a better level of adjustability
Definition at line 546 of file app_meetme.c.
Definition at line 523 of file app_meetme.c.
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 1032 of file app_meetme.c.
struct { ... } sla [static] |
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 467 of file app_meetme.c.
Referenced by destroy_station(), destroy_trunk(), sla_build_station(), sla_build_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 1178 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 1109 of file app_meetme.c.
const char* slastation_app = "SLAStation" [static] |
Definition at line 203 of file app_meetme.c.
const char* slastation_desc [static] |
Definition at line 291 of file app_meetme.c.
const char* slastation_synopsis = "Shared Line Appearance Station" [static] |
Definition at line 209 of file app_meetme.c.
const char* slatrunk_app = "SLATrunk" [static] |
Definition at line 204 of file app_meetme.c.
const char* slatrunk_desc [static] |
Definition at line 304 of file app_meetme.c.
const char* slatrunk_synopsis = "Shared Line Appearance Trunk" [static] |
Definition at line 210 of file app_meetme.c.
const char* synopsis = "MeetMe conference bridge" [static] |
Definition at line 206 of file app_meetme.c.
const char* synopsis2 = "MeetMe participant count" [static] |
Definition at line 207 of file app_meetme.c.
const char* synopsis3 = "MeetMe conference Administration" [static] |
Definition at line 208 of file app_meetme.c.
pthread_t thread |
The SLA thread ID
Definition at line 521 of file app_meetme.c.
Referenced by __schedule_action(), __unload_module(), ast_bridge_call_thread_launch(), find_idle_thread(), iax2_process_thread(), iax2_process_thread_cleanup(), iax2_show_threads(), launch_monitor_thread(), load_module(), socket_read(), and start_network_thread().