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