#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"
Include dependency graph for app_meetme.c:
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" |
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 |
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 3009 of file app_meetme.c.
References meetmemute(), and s.
Referenced by load_module().
03010 { 03011 return meetmemute(s, m, 1); 03012 }
static int action_meetmeunmute | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 3014 of file app_meetme.c.
References meetmemute(), and s.
Referenced by load_module().
03015 { 03016 return meetmemute(s, m, 0); 03017 }
static int admin_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
The MeetMeadmin application.
Definition at line 2795 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(), ast_conference::chan, ast_conference::confno, dispose_conf(), find_user(), ast_conference::locked, LOG_NOTICE, LOG_WARNING, ast_conference::refcount, reset_volumes(), tweak_listen_volume(), tweak_talk_volume(), ast_conf_user::userflags, and VOL_UP.
Referenced by load_module(), meetme_cmd(), run_station(), sla_station_exec(), and sla_stop_ringing_trunk().
02795 { 02796 char *params; 02797 struct ast_conference *cnf; 02798 struct ast_conf_user *user = NULL; 02799 struct ast_module_user *u; 02800 AST_DECLARE_APP_ARGS(args, 02801 AST_APP_ARG(confno); 02802 AST_APP_ARG(command); 02803 AST_APP_ARG(user); 02804 ); 02805 02806 if (ast_strlen_zero(data)) { 02807 ast_log(LOG_WARNING, "MeetMeAdmin requires an argument!\n"); 02808 return -1; 02809 } 02810 02811 u = ast_module_user_add(chan); 02812 02813 AST_LIST_LOCK(&confs); 02814 02815 params = ast_strdupa(data); 02816 AST_STANDARD_APP_ARGS(args, params); 02817 02818 if (!args.command) { 02819 ast_log(LOG_WARNING, "MeetmeAdmin requires a command!\n"); 02820 AST_LIST_UNLOCK(&confs); 02821 ast_module_user_remove(u); 02822 return -1; 02823 } 02824 AST_LIST_TRAVERSE(&confs, cnf, list) { 02825 if (!strcmp(cnf->confno, args.confno)) 02826 break; 02827 } 02828 02829 if (!cnf) { 02830 ast_log(LOG_WARNING, "Conference number '%s' not found!\n", args.confno); 02831 AST_LIST_UNLOCK(&confs); 02832 ast_module_user_remove(u); 02833 return 0; 02834 } 02835 02836 ast_atomic_fetchadd_int(&cnf->refcount, 1); 02837 02838 if (args.user) 02839 user = find_user(cnf, args.user); 02840 02841 switch (*args.command) { 02842 case 76: /* L: Lock */ 02843 cnf->locked = 1; 02844 break; 02845 case 108: /* l: Unlock */ 02846 cnf->locked = 0; 02847 break; 02848 case 75: /* K: kick all users */ 02849 AST_LIST_TRAVERSE(&cnf->userlist, user, list) 02850 user->adminflags |= ADMINFLAG_KICKME; 02851 break; 02852 case 101: /* e: Eject last user*/ 02853 user = AST_LIST_LAST(&cnf->userlist); 02854 if (!(user->userflags & CONFFLAG_ADMIN)) 02855 user->adminflags |= ADMINFLAG_KICKME; 02856 else 02857 ast_log(LOG_NOTICE, "Not kicking last user, is an Admin!\n"); 02858 break; 02859 case 77: /* M: Mute */ 02860 if (user) { 02861 user->adminflags |= ADMINFLAG_MUTED; 02862 } else 02863 ast_log(LOG_NOTICE, "Specified User not found!\n"); 02864 break; 02865 case 78: /* N: Mute all (non-admin) users */ 02866 AST_LIST_TRAVERSE(&cnf->userlist, user, list) { 02867 if (!(user->userflags & CONFFLAG_ADMIN)) 02868 user->adminflags |= ADMINFLAG_MUTED; 02869 } 02870 break; 02871 case 109: /* m: Unmute */ 02872 if (user) { 02873 user->adminflags &= ~(ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED); 02874 } else 02875 ast_log(LOG_NOTICE, "Specified User not found!\n"); 02876 break; 02877 case 110: /* n: Unmute all users */ 02878 AST_LIST_TRAVERSE(&cnf->userlist, user, list) 02879 user->adminflags &= ~(ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED); 02880 break; 02881 case 107: /* k: Kick user */ 02882 if (user) 02883 user->adminflags |= ADMINFLAG_KICKME; 02884 else 02885 ast_log(LOG_NOTICE, "Specified User not found!\n"); 02886 break; 02887 case 118: /* v: Lower all users listen volume */ 02888 AST_LIST_TRAVERSE(&cnf->userlist, user, list) 02889 tweak_listen_volume(user, VOL_DOWN); 02890 break; 02891 case 86: /* V: Raise all users listen volume */ 02892 AST_LIST_TRAVERSE(&cnf->userlist, user, list) 02893 tweak_listen_volume(user, VOL_UP); 02894 break; 02895 case 115: /* s: Lower all users speaking volume */ 02896 AST_LIST_TRAVERSE(&cnf->userlist, user, list) 02897 tweak_talk_volume(user, VOL_DOWN); 02898 break; 02899 case 83: /* S: Raise all users speaking volume */ 02900 AST_LIST_TRAVERSE(&cnf->userlist, user, list) 02901 tweak_talk_volume(user, VOL_UP); 02902 break; 02903 case 82: /* R: Reset all volume levels */ 02904 AST_LIST_TRAVERSE(&cnf->userlist, user, list) 02905 reset_volumes(user); 02906 break; 02907 case 114: /* r: Reset user's volume level */ 02908 if (user) 02909 reset_volumes(user); 02910 else 02911 ast_log(LOG_NOTICE, "Specified User not found!\n"); 02912 break; 02913 case 85: /* U: Raise user's listen volume */ 02914 if (user) 02915 tweak_listen_volume(user, VOL_UP); 02916 else 02917 ast_log(LOG_NOTICE, "Specified User not found!\n"); 02918 break; 02919 case 117: /* u: Lower user's listen volume */ 02920 if (user) 02921 tweak_listen_volume(user, VOL_DOWN); 02922 else 02923 ast_log(LOG_NOTICE, "Specified User not found!\n"); 02924 break; 02925 case 84: /* T: Raise user's talk volume */ 02926 if (user) 02927 tweak_talk_volume(user, VOL_UP); 02928 else 02929 ast_log(LOG_NOTICE, "Specified User not found!\n"); 02930 break; 02931 case 116: /* t: Lower user's talk volume */ 02932 if (user) 02933 tweak_talk_volume(user, VOL_DOWN); 02934 else 02935 ast_log(LOG_NOTICE, "Specified User not found!\n"); 02936 break; 02937 } 02938 02939 AST_LIST_UNLOCK(&confs); 02940 02941 dispose_conf(cnf); 02942 02943 ast_module_user_remove(u); 02944 02945 return 0; 02946 }
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] |
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(), conf_map, ast_conference::confno, free, LOG_WARNING, option_verbose, and VERBOSE_PREFIX_3.
Referenced by 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 2532 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(), ast_conference::chan, conf_map, conf_run(), CONFFLAG_ALWAYSPROMPT, CONFFLAG_DYNAMIC, CONFFLAG_DYNAMICPIN, CONFFLAG_EMPTY, CONFFLAG_EMPTYNOPIN, CONFIG_FILE_NAME, ast_conference::confno, dispose_conf(), find_conf(), find_conf_realtime(), ast_flags::flags, LOG_ERROR, LOG_WARNING, MAX_CONFNUM, MAX_PIN, OPT_ARG_ARRAY_SIZE, ast_conference::pin, ast_conference::pinadmin, strsep(), and var.
Referenced by load_module().
02533 { 02534 int res=-1; 02535 struct ast_module_user *u; 02536 char confno[MAX_CONFNUM] = ""; 02537 int allowretry = 0; 02538 int retrycnt = 0; 02539 struct ast_conference *cnf = NULL; 02540 struct ast_flags confflags = {0}; 02541 int dynamic = 0; 02542 int empty = 0, empty_no_pin = 0; 02543 int always_prompt = 0; 02544 char *notdata, *info, the_pin[MAX_PIN] = ""; 02545 AST_DECLARE_APP_ARGS(args, 02546 AST_APP_ARG(confno); 02547 AST_APP_ARG(options); 02548 AST_APP_ARG(pin); 02549 ); 02550 char *optargs[OPT_ARG_ARRAY_SIZE] = { NULL, }; 02551 02552 u = ast_module_user_add(chan); 02553 02554 if (ast_strlen_zero(data)) { 02555 allowretry = 1; 02556 notdata = ""; 02557 } else { 02558 notdata = data; 02559 } 02560 02561 if (chan->_state != AST_STATE_UP) 02562 ast_answer(chan); 02563 02564 info = ast_strdupa(notdata); 02565 02566 AST_STANDARD_APP_ARGS(args, info); 02567 02568 if (args.confno) { 02569 ast_copy_string(confno, args.confno, sizeof(confno)); 02570 if (ast_strlen_zero(confno)) { 02571 allowretry = 1; 02572 } 02573 } 02574 02575 if (args.pin) 02576 ast_copy_string(the_pin, args.pin, sizeof(the_pin)); 02577 02578 if (args.options) { 02579 ast_app_parse_options(meetme_opts, &confflags, optargs, args.options); 02580 dynamic = ast_test_flag(&confflags, CONFFLAG_DYNAMIC | CONFFLAG_DYNAMICPIN); 02581 if (ast_test_flag(&confflags, CONFFLAG_DYNAMICPIN) && !args.pin) 02582 strcpy(the_pin, "q"); 02583 02584 empty = ast_test_flag(&confflags, CONFFLAG_EMPTY | CONFFLAG_EMPTYNOPIN); 02585 empty_no_pin = ast_test_flag(&confflags, CONFFLAG_EMPTYNOPIN); 02586 always_prompt = ast_test_flag(&confflags, CONFFLAG_ALWAYSPROMPT); 02587 } 02588 02589 do { 02590 if (retrycnt > 3) 02591 allowretry = 0; 02592 if (empty) { 02593 int i; 02594 struct ast_config *cfg; 02595 struct ast_variable *var; 02596 int confno_int; 02597 02598 /* We only need to load the config file for static and empty_no_pin (otherwise we don't care) */ 02599 if ((empty_no_pin) || (!dynamic)) { 02600 cfg = ast_config_load(CONFIG_FILE_NAME); 02601 if (cfg) { 02602 var = ast_variable_browse(cfg, "rooms"); 02603 while (var) { 02604 if (!strcasecmp(var->name, "conf")) { 02605 char *stringp = ast_strdupa(var->value); 02606 if (stringp) { 02607 char *confno_tmp = strsep(&stringp, "|,"); 02608 int found = 0; 02609 if (!dynamic) { 02610 /* For static: run through the list and see if this conference is empty */ 02611 AST_LIST_LOCK(&confs); 02612 AST_LIST_TRAVERSE(&confs, cnf, list) { 02613 if (!strcmp(confno_tmp, cnf->confno)) { 02614 /* The conference exists, therefore it's not empty */ 02615 found = 1; 02616 break; 02617 } 02618 } 02619 AST_LIST_UNLOCK(&confs); 02620 if (!found) { 02621 /* At this point, we have a confno_tmp (static conference) that is empty */ 02622 if ((empty_no_pin && ast_strlen_zero(stringp)) || (!empty_no_pin)) { 02623 /* Case 1: empty_no_pin and pin is nonexistent (NULL) 02624 * Case 2: empty_no_pin and pin is blank (but not NULL) 02625 * Case 3: not empty_no_pin 02626 */ 02627 ast_copy_string(confno, confno_tmp, sizeof(confno)); 02628 break; 02629 /* XXX the map is not complete (but we do have a confno) */ 02630 } 02631 } 02632 } 02633 } 02634 } 02635 var = var->next; 02636 } 02637 ast_config_destroy(cfg); 02638 } 02639 } 02640 02641 /* Select first conference number not in use */ 02642 if (ast_strlen_zero(confno) && dynamic) { 02643 AST_LIST_LOCK(&confs); 02644 for (i = 0; i < sizeof(conf_map) / sizeof(conf_map[0]); i++) { 02645 if (!conf_map[i]) { 02646 snprintf(confno, sizeof(confno), "%d", i); 02647 conf_map[i] = 1; 02648 break; 02649 } 02650 } 02651 AST_LIST_UNLOCK(&confs); 02652 } 02653 02654 /* Not found? */ 02655 if (ast_strlen_zero(confno)) { 02656 res = ast_streamfile(chan, "conf-noempty", chan->language); 02657 if (!res) 02658 ast_waitstream(chan, ""); 02659 } else { 02660 if (sscanf(confno, "%d", &confno_int) == 1) { 02661 res = ast_streamfile(chan, "conf-enteringno", chan->language); 02662 if (!res) { 02663 ast_waitstream(chan, ""); 02664 res = ast_say_digits(chan, confno_int, "", chan->language); 02665 } 02666 } else { 02667 ast_log(LOG_ERROR, "Could not scan confno '%s'\n", confno); 02668 } 02669 } 02670 } 02671 02672 while (allowretry && (ast_strlen_zero(confno)) && (++retrycnt < 4)) { 02673 /* Prompt user for conference number */ 02674 res = ast_app_getdata(chan, "conf-getconfno", confno, sizeof(confno) - 1, 0); 02675 if (res < 0) { 02676 /* Don't try to validate when we catch an error */ 02677 confno[0] = '\0'; 02678 allowretry = 0; 02679 break; 02680 } 02681 } 02682 if (!ast_strlen_zero(confno)) { 02683 /* Check the validity of the conference */ 02684 cnf = find_conf(chan, confno, 1, dynamic, the_pin, 02685 sizeof(the_pin), 1, &confflags); 02686 if (!cnf) { 02687 cnf = find_conf_realtime(chan, confno, 1, dynamic, 02688 the_pin, sizeof(the_pin), 1, &confflags); 02689 } 02690 02691 if (!cnf) { 02692 res = ast_streamfile(chan, "conf-invalid", chan->language); 02693 if (!res) 02694 ast_waitstream(chan, ""); 02695 res = -1; 02696 if (allowretry) 02697 confno[0] = '\0'; 02698 } else { 02699 if ((!ast_strlen_zero(cnf->pin) && 02700 !ast_test_flag(&confflags, CONFFLAG_ADMIN)) || 02701 (!ast_strlen_zero(cnf->pinadmin) && 02702 ast_test_flag(&confflags, CONFFLAG_ADMIN))) { 02703 char pin[MAX_PIN] = ""; 02704 int j; 02705 02706 /* Allow the pin to be retried up to 3 times */ 02707 for (j = 0; j < 3; j++) { 02708 if (*the_pin && (always_prompt == 0)) { 02709 ast_copy_string(pin, the_pin, sizeof(pin)); 02710 res = 0; 02711 } else { 02712 /* Prompt user for pin if pin is required */ 02713 res = ast_app_getdata(chan, "conf-getpin", pin + strlen(pin), sizeof(pin) - 1 - strlen(pin), 0); 02714 } 02715 if (res >= 0) { 02716 if (!strcasecmp(pin, cnf->pin) || 02717 (!ast_strlen_zero(cnf->pinadmin) && 02718 !strcasecmp(pin, cnf->pinadmin))) { 02719 /* Pin correct */ 02720 allowretry = 0; 02721 if (!ast_strlen_zero(cnf->pinadmin) && !strcasecmp(pin, cnf->pinadmin)) 02722 ast_set_flag(&confflags, CONFFLAG_ADMIN); 02723 /* Run the conference */ 02724 res = conf_run(chan, cnf, confflags.flags, optargs); 02725 break; 02726 } else { 02727 /* Pin invalid */ 02728 if (!ast_streamfile(chan, "conf-invalidpin", chan->language)) { 02729 res = ast_waitstream(chan, AST_DIGIT_ANY); 02730 ast_stopstream(chan); 02731 } 02732 else { 02733 ast_log(LOG_WARNING, "Couldn't play invalid pin msg!\n"); 02734 break; 02735 } 02736 if (res < 0) 02737 break; 02738 pin[0] = res; 02739 pin[1] = '\0'; 02740 res = -1; 02741 if (allowretry) 02742 confno[0] = '\0'; 02743 } 02744 } else { 02745 /* failed when getting the pin */ 02746 res = -1; 02747 allowretry = 0; 02748 /* see if we need to get rid of the conference */ 02749 break; 02750 } 02751 02752 /* Don't retry pin with a static pin */ 02753 if (*the_pin && (always_prompt==0)) { 02754 break; 02755 } 02756 } 02757 } else { 02758 /* No pin required */ 02759 allowretry = 0; 02760 02761 /* Run the conference */ 02762 res = conf_run(chan, cnf, confflags.flags, optargs); 02763 } 02764 dispose_conf(cnf); 02765 cnf = NULL; 02766 } 02767 } 02768 } while (allowretry); 02769 02770 if (cnf) 02771 dispose_conf(cnf); 02772 02773 ast_module_user_remove(u); 02774 02775 return res; 02776 }
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(), ast_conference::chan, 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, 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(), ast_conference::chan, enter, ENTER, ast_conference::fd, 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, f, 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 ADMINFLAG_KICKME, ADMINFLAG_MUTED, ADMINFLAG_SELFMUTED, ast_conf_user::adminflags, app, 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_new(), ast_dsp_silence(), 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_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_conf_user::chan, ast_conference::chan, 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, ENTER, errno, EVENT_FLAG_CALL, exitcontext, f, ast_conference::fd, ast_channel::fds, ast_frame::flags, ast_frame::frametype, ast_conference::lchan, ast_conference::listenlock, ast_conference::locked, LOG_DEBUG, LOG_NOTICE, LOG_WARNING, ast_channel::macrocontext, manager_event(), ast_conference::markedusers, MEETME_DELAYDETECTENDTALK, MEETME_DELAYDETECTTALK, ast_channel::monitor, OPT_ARG_WAITMARKED, option_debug, ast_conference::origframe, pbx_builtin_getvar_helper(), pbx_exec(), pbx_findapp(), ast_conference::playlock, ast_channel::rawwriteformat, ast_conference::recordingfilename, ast_conference::recordingformat, ast_conference::recordthread, ast_conference::recordthreadlock, s, set_talk_volume(), SLA_EVENT_HOLD, sla_queue_event_conf(), ast_channel::tech, ast_conference::transframe, ast_conference::transpath, tweak_listen_volume(), tweak_talk_volume(), ast_channel_tech::type, ast_conf_user::userflags, ast_conference::users, VERBOSE_PREFIX_4, VOL_UP, and ast_conference::zapconf.
Referenced by conf_exec(), 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 int dyna_buff = CONF_SIZE; 01409 ZT_BUFFERINFO bi; 01410 char __buf[ZT_MAX_BUF_SPACE / ZT_DEFAULT_NUM_BUFS + AST_FRIENDLY_OFFSET]; 01411 char *buf = __buf + AST_FRIENDLY_OFFSET; 01412 int setusercount = 0; 01413 01414 if (!(user = ast_calloc(1, sizeof(*user)))) 01415 return ret; 01416 01417 /* Possible timeout waiting for marked user */ 01418 if ((confflags & CONFFLAG_WAITMARKED) && 01419 !ast_strlen_zero(optargs[OPT_ARG_WAITMARKED]) && 01420 (sscanf(optargs[OPT_ARG_WAITMARKED], "%d", &opt_waitmarked_timeout) == 1) && 01421 (opt_waitmarked_timeout > 0)) { 01422 timeout = time(NULL) + opt_waitmarked_timeout; 01423 } 01424 01425 if (confflags & CONFFLAG_RECORDCONF) { 01426 if (!conf->recordingfilename) { 01427 conf->recordingfilename = pbx_builtin_getvar_helper(chan, "MEETME_RECORDINGFILE"); 01428 if (!conf->recordingfilename) { 01429 snprintf(recordingtmp, sizeof(recordingtmp), "meetme-conf-rec-%s-%s", conf->confno, chan->uniqueid); 01430 conf->recordingfilename = ast_strdupa(recordingtmp); 01431 } 01432 conf->recordingformat = pbx_builtin_getvar_helper(chan, "MEETME_RECORDINGFORMAT"); 01433 if (!conf->recordingformat) { 01434 snprintf(recordingtmp, sizeof(recordingtmp), "wav"); 01435 conf->recordingformat = ast_strdupa(recordingtmp); 01436 } 01437 ast_verbose(VERBOSE_PREFIX_4 "Starting recording of MeetMe Conference %s into file %s.%s.\n", 01438 conf->confno, conf->recordingfilename, conf->recordingformat); 01439 } 01440 } 01441 01442 ast_mutex_lock(&conf->recordthreadlock); 01443 if ((conf->recordthread == AST_PTHREADT_NULL) && (confflags & CONFFLAG_RECORDCONF) && ((conf->lchan = ast_request("zap", AST_FORMAT_SLINEAR, "pseudo", NULL)))) { 01444 ast_set_read_format(conf->lchan, AST_FORMAT_SLINEAR); 01445 ast_set_write_format(conf->lchan, AST_FORMAT_SLINEAR); 01446 ztc.chan = 0; 01447 ztc.confno = conf->zapconf; 01448 ztc.confmode = ZT_CONF_CONFANN | ZT_CONF_CONFANNMON; 01449 if (ioctl(conf->lchan->fds[0], ZT_SETCONF, &ztc)) { 01450 ast_log(LOG_WARNING, "Error starting listen channel\n"); 01451 ast_hangup(conf->lchan); 01452 conf->lchan = NULL; 01453 } else { 01454 pthread_attr_init(&conf->attr); 01455 pthread_attr_setdetachstate(&conf->attr, PTHREAD_CREATE_DETACHED); 01456 ast_pthread_create_background(&conf->recordthread, &conf->attr, recordthread, conf); 01457 pthread_attr_destroy(&conf->attr); 01458 } 01459 } 01460 ast_mutex_unlock(&conf->recordthreadlock); 01461 01462 time(&user->jointime); 01463 01464 if (conf->locked && (!(confflags & CONFFLAG_ADMIN))) { 01465 /* Sorry, but this confernce is locked! */ 01466 if (!ast_streamfile(chan, "conf-locked", chan->language)) 01467 ast_waitstream(chan, ""); 01468 goto outrun; 01469 } 01470 01471 ast_mutex_lock(&conf->playlock); 01472 01473 if (AST_LIST_EMPTY(&conf->userlist)) 01474 user->user_no = 1; 01475 else 01476 user->user_no = AST_LIST_LAST(&conf->userlist)->user_no + 1; 01477 01478 AST_LIST_INSERT_TAIL(&conf->userlist, user, list); 01479 01480 user->chan = chan; 01481 user->userflags = confflags; 01482 user->adminflags = (confflags & CONFFLAG_STARTMUTED) ? ADMINFLAG_SELFMUTED : 0; 01483 user->talking = -1; 01484 01485 ast_mutex_unlock(&conf->playlock); 01486 01487 if (!(confflags & CONFFLAG_QUIET) && ((confflags & CONFFLAG_INTROUSER) || (confflags & CONFFLAG_INTROUSERNOREVIEW))) { 01488 char destdir[PATH_MAX]; 01489 01490 snprintf(destdir, sizeof(destdir), "%s/meetme", ast_config_AST_SPOOL_DIR); 01491 01492 if (mkdir(destdir, 0777) && errno != EEXIST) { 01493 ast_log(LOG_WARNING, "mkdir '%s' failed: %s\n", destdir, strerror(errno)); 01494 goto outrun; 01495 } 01496 01497 snprintf(user->namerecloc, sizeof(user->namerecloc), 01498 "%s/meetme-username-%s-%d", destdir, 01499 conf->confno, user->user_no); 01500 if (confflags & CONFFLAG_INTROUSERNOREVIEW) 01501 res = ast_play_and_record(chan, "vm-rec-name", user->namerecloc, 10, "sln", &duration, 128, 0, NULL); 01502 else 01503 res = ast_record_review(chan, "vm-rec-name", user->namerecloc, 10, "sln", &duration, NULL); 01504 if (res == -1) 01505 goto outrun; 01506 } 01507 01508 ast_mutex_lock(&conf->playlock); 01509 01510 if (confflags & CONFFLAG_MARKEDUSER) 01511 conf->markedusers++; 01512 conf->users++; 01513 /* Update table */ 01514 snprintf(members, sizeof(members), "%d", conf->users); 01515 ast_update_realtime("meetme", "confno", conf->confno, "members", members , NULL); 01516 setusercount = 1; 01517 01518 /* This device changed state now - if this is the first user */ 01519 if (conf->users == 1) 01520 ast_device_state_changed("meetme:%s", conf->confno); 01521 01522 ast_mutex_unlock(&conf->playlock); 01523 01524 if (confflags & CONFFLAG_EXIT_CONTEXT) { 01525 if ((agifile = pbx_builtin_getvar_helper(chan, "MEETME_EXIT_CONTEXT"))) 01526 ast_copy_string(exitcontext, agifile, sizeof(exitcontext)); 01527 else if (!ast_strlen_zero(chan->macrocontext)) 01528 ast_copy_string(exitcontext, chan->macrocontext, sizeof(exitcontext)); 01529 else 01530 ast_copy_string(exitcontext, chan->context, sizeof(exitcontext)); 01531 } 01532 01533 if ( !(confflags & (CONFFLAG_QUIET | CONFFLAG_NOONLYPERSON)) ) { 01534 if (conf->users == 1 && !(confflags & CONFFLAG_WAITMARKED)) 01535 if (!ast_streamfile(chan, "conf-onlyperson", chan->language)) 01536 ast_waitstream(chan, ""); 01537 if ((confflags & CONFFLAG_WAITMARKED) && conf->markedusers == 0) 01538 if (!ast_streamfile(chan, "conf-waitforleader", chan->language)) 01539 ast_waitstream(chan, ""); 01540 } 01541 01542 if (!(confflags & CONFFLAG_QUIET) && (confflags & CONFFLAG_ANNOUNCEUSERCOUNT) && conf->users > 1) { 01543 int keepplaying = 1; 01544 01545 if (conf->users == 2) { 01546 if (!ast_streamfile(chan,"conf-onlyone",chan->language)) { 01547 res = ast_waitstream(chan, AST_DIGIT_ANY); 01548 ast_stopstream(chan); 01549 if (res > 0) 01550 keepplaying=0; 01551 else if (res == -1) 01552 goto outrun; 01553 } 01554 } else { 01555 if (!ast_streamfile(chan, "conf-thereare", chan->language)) { 01556 res = ast_waitstream(chan, AST_DIGIT_ANY); 01557 ast_stopstream(chan); 01558 if (res > 0) 01559 keepplaying=0; 01560 else if (res == -1) 01561 goto outrun; 01562 } 01563 if (keepplaying) { 01564 res = ast_say_number(chan, conf->users - 1, AST_DIGIT_ANY, chan->language, (char *) NULL); 01565 if (res > 0) 01566 keepplaying=0; 01567 else if (res == -1) 01568 goto outrun; 01569 } 01570 if (keepplaying && !ast_streamfile(chan, "conf-otherinparty", chan->language)) { 01571 res = ast_waitstream(chan, AST_DIGIT_ANY); 01572 ast_stopstream(chan); 01573 if (res > 0) 01574 keepplaying=0; 01575 else if (res == -1) 01576 goto outrun; 01577 } 01578 } 01579 } 01580 01581 ast_indicate(chan, -1); 01582 01583 if (ast_set_write_format(chan, AST_FORMAT_SLINEAR) < 0) { 01584 ast_log(LOG_WARNING, "Unable to set '%s' to write linear mode\n", chan->name); 01585 goto outrun; 01586 } 01587 01588 if (ast_set_read_format(chan, AST_FORMAT_SLINEAR) < 0) { 01589 ast_log(LOG_WARNING, "Unable to set '%s' to read linear mode\n", chan->name); 01590 goto outrun; 01591 } 01592 01593 retryzap = (strcasecmp(chan->tech->type, "Zap") || (chan->audiohooks || chan->monitor) ? 1 : 0); 01594 user->zapchannel = !retryzap; 01595 01596 zapretry: 01597 origfd = chan->fds[0]; 01598 if (retryzap) { 01599 fd = open("/dev/zap/pseudo", O_RDWR); 01600 if (fd < 0) { 01601 ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno)); 01602 goto outrun; 01603 } 01604 using_pseudo = 1; 01605 /* Make non-blocking */ 01606 flags = fcntl(fd, F_GETFL); 01607 if (flags < 0) { 01608 ast_log(LOG_WARNING, "Unable to get flags: %s\n", strerror(errno)); 01609 close(fd); 01610 goto outrun; 01611 } 01612 if (fcntl(fd, F_SETFL, flags | O_NONBLOCK)) { 01613 ast_log(LOG_WARNING, "Unable to set flags: %s\n", strerror(errno)); 01614 close(fd); 01615 goto outrun; 01616 } 01617 /* Setup buffering information */ 01618 memset(&bi, 0, sizeof(bi)); 01619 bi.bufsize = dyna_buff / 2; 01620 bi.txbufpolicy = ZT_POLICY_IMMEDIATE; 01621 bi.rxbufpolicy = ZT_POLICY_IMMEDIATE; 01622 bi.numbufs = audio_buffers; 01623 if (ioctl(fd, ZT_SET_BUFINFO, &bi)) { 01624 ast_log(LOG_WARNING, "Unable to set buffering information: %s\n", strerror(errno)); 01625 close(fd); 01626 goto outrun; 01627 } 01628 x = 1; 01629 if (ioctl(fd, ZT_SETLINEAR, &x)) { 01630 ast_log(LOG_WARNING, "Unable to set linear mode: %s\n", strerror(errno)); 01631 close(fd); 01632 goto outrun; 01633 } 01634 nfds = 1; 01635 } else { 01636 /* XXX Make sure we're not running on a pseudo channel XXX */ 01637 fd = chan->fds[0]; 01638 nfds = 0; 01639 } 01640 memset(&ztc, 0, sizeof(ztc)); 01641 memset(&ztc_empty, 0, sizeof(ztc_empty)); 01642 /* Check to see if we're in a conference... */ 01643 ztc.chan = 0; 01644 if (ioctl(fd, ZT_GETCONF, &ztc)) { 01645 ast_log(LOG_WARNING, "Error getting conference\n"); 01646 close(fd); 01647 goto outrun; 01648 } 01649 if (ztc.confmode) { 01650 /* Whoa, already in a conference... Retry... */ 01651 if (!retryzap) { 01652 ast_log(LOG_DEBUG, "Zap channel is in a conference already, retrying with pseudo\n"); 01653 retryzap = 1; 01654 goto zapretry; 01655 } 01656 } 01657 memset(&ztc, 0, sizeof(ztc)); 01658 /* Add us to the conference */ 01659 ztc.chan = 0; 01660 ztc.confno = conf->zapconf; 01661 01662 ast_mutex_lock(&conf->playlock); 01663 01664 if (!(confflags & CONFFLAG_QUIET) && ((confflags & CONFFLAG_INTROUSER) || (confflags & CONFFLAG_INTROUSERNOREVIEW)) && conf->users > 1) { 01665 if (conf->chan && ast_fileexists(user->namerecloc, NULL, NULL)) { 01666 if (!ast_streamfile(conf->chan, user->namerecloc, chan->language)) 01667 ast_waitstream(conf->chan, ""); 01668 if (!ast_streamfile(conf->chan, "conf-hasjoin", chan->language)) 01669 ast_waitstream(conf->chan, ""); 01670 } 01671 } 01672 01673 if (confflags & CONFFLAG_WAITMARKED && !conf->markedusers) 01674 ztc.confmode = ZT_CONF_CONF; 01675 else if (confflags & CONFFLAG_MONITOR) 01676 ztc.confmode = ZT_CONF_CONFMON | ZT_CONF_LISTENER; 01677 else if (confflags & CONFFLAG_TALKER) 01678 ztc.confmode = ZT_CONF_CONF | ZT_CONF_TALKER; 01679 else 01680 ztc.confmode = ZT_CONF_CONF | ZT_CONF_TALKER | ZT_CONF_LISTENER; 01681 01682 if (ioctl(fd, ZT_SETCONF, &ztc)) { 01683 ast_log(LOG_WARNING, "Error setting conference\n"); 01684 close(fd); 01685 ast_mutex_unlock(&conf->playlock); 01686 goto outrun; 01687 } 01688 ast_log(LOG_DEBUG, "Placed channel %s in ZAP conf %d\n", chan->name, conf->zapconf); 01689 01690 if (!sent_event) { 01691 manager_event(EVENT_FLAG_CALL, "MeetmeJoin", 01692 "Channel: %s\r\n" 01693 "Uniqueid: %s\r\n" 01694 "Meetme: %s\r\n" 01695 "Usernum: %d\r\n", 01696 chan->name, chan->uniqueid, conf->confno, user->user_no); 01697 sent_event = 1; 01698 } 01699 01700 if (!firstpass && !(confflags & CONFFLAG_MONITOR) && !(confflags & CONFFLAG_ADMIN)) { 01701 firstpass = 1; 01702 if (!(confflags & CONFFLAG_QUIET)) 01703 if (!(confflags & CONFFLAG_WAITMARKED) || ((confflags & CONFFLAG_MARKEDUSER) && (conf->markedusers >= 1))) 01704 conf_play(chan, conf, ENTER); 01705 } 01706 01707 ast_mutex_unlock(&conf->playlock); 01708 01709 conf_flush(fd, chan); 01710 01711 if (confflags & CONFFLAG_AGI) { 01712 /* Get name of AGI file to run from $(MEETME_AGI_BACKGROUND) 01713 or use default filename of conf-background.agi */ 01714 01715 agifile = pbx_builtin_getvar_helper(chan, "MEETME_AGI_BACKGROUND"); 01716 if (!agifile) 01717 agifile = agifiledefault; 01718 01719 if (user->zapchannel) { 01720 /* Set CONFMUTE mode on Zap channel to mute DTMF tones */ 01721 x = 1; 01722 ast_channel_setoption(chan, AST_OPTION_TONE_VERIFY, &x, sizeof(char), 0); 01723 } 01724 /* Find a pointer to the agi app and execute the script */ 01725 app = pbx_findapp("agi"); 01726 if (app) { 01727 char *s = ast_strdupa(agifile); 01728 ret = pbx_exec(chan, app, s); 01729 } else { 01730 ast_log(LOG_WARNING, "Could not find application (agi)\n"); 01731 ret = -2; 01732 } 01733 if (user->zapchannel) { 01734 /* Remove CONFMUTE mode on Zap channel */ 01735 x = 0; 01736 ast_channel_setoption(chan, AST_OPTION_TONE_VERIFY, &x, sizeof(char), 0); 01737 } 01738 } else { 01739 if (user->zapchannel && (confflags & CONFFLAG_STARMENU)) { 01740 /* Set CONFMUTE mode on Zap channel to mute DTMF tones when the menu is enabled */ 01741 x = 1; 01742 ast_channel_setoption(chan, AST_OPTION_TONE_VERIFY, &x, sizeof(char), 0); 01743 } 01744 if (confflags & (CONFFLAG_MONITORTALKER | CONFFLAG_OPTIMIZETALKER) && !(dsp = ast_dsp_new())) { 01745 ast_log(LOG_WARNING, "Unable to allocate DSP!\n"); 01746 res = -1; 01747 } 01748 for(;;) { 01749 int menu_was_active = 0; 01750 01751 outfd = -1; 01752 ms = -1; 01753 01754 if (timeout && time(NULL) >= timeout) 01755 break; 01756 01757 /* if we have just exited from the menu, and the user had a channel-driver 01758 volume adjustment, restore it 01759 */ 01760 if (!menu_active && menu_was_active && user->listen.desired && !user->listen.actual) 01761 set_talk_volume(user, user->listen.desired); 01762 01763 menu_was_active = menu_active; 01764 01765 currentmarked = conf->markedusers; 01766 if (!(confflags & CONFFLAG_QUIET) && 01767 (confflags & CONFFLAG_MARKEDUSER) && 01768 (confflags & CONFFLAG_WAITMARKED) && 01769 lastmarked == 0) { 01770 if (currentmarked == 1 && conf->users > 1) { 01771 ast_say_number(chan, conf->users - 1, AST_DIGIT_ANY, chan->language, (char *) NULL); 01772 if (conf->users - 1 == 1) { 01773 if (!ast_streamfile(chan, "conf-userwilljoin", chan->language)) 01774 ast_waitstream(chan, ""); 01775 } else { 01776 if (!ast_streamfile(chan, "conf-userswilljoin", chan->language)) 01777 ast_waitstream(chan, ""); 01778 } 01779 } 01780 if (conf->users == 1 && ! (confflags & CONFFLAG_MARKEDUSER)) 01781 if (!ast_streamfile(chan, "conf-onlyperson", chan->language)) 01782 ast_waitstream(chan, ""); 01783 } 01784 01785 c = ast_waitfor_nandfds(&chan, 1, &fd, nfds, NULL, &outfd, &ms); 01786 01787 01788 /* Update the struct with the actual confflags */ 01789 user->userflags = confflags; 01790 01791 if (confflags & CONFFLAG_WAITMARKED) { 01792 if(currentmarked == 0) { 01793 if (lastmarked != 0) { 01794 if (!(confflags & CONFFLAG_QUIET)) 01795 if (!ast_streamfile(chan, "conf-leaderhasleft", chan->language)) 01796 ast_waitstream(chan, ""); 01797 if(confflags & CONFFLAG_MARKEDEXIT) 01798 break; 01799 else { 01800 ztc.confmode = ZT_CONF_CONF; 01801 if (ioctl(fd, ZT_SETCONF, &ztc)) { 01802 ast_log(LOG_WARNING, "Error setting conference\n"); 01803 close(fd); 01804 goto outrun; 01805 } 01806 } 01807 } 01808 if (musiconhold == 0 && (confflags & CONFFLAG_MOH)) { 01809 ast_moh_start(chan, NULL, NULL); 01810 musiconhold = 1; 01811 } 01812 } else if(currentmarked >= 1 && lastmarked == 0) { 01813 /* Marked user entered, so cancel timeout */ 01814 timeout = 0; 01815 if (confflags & CONFFLAG_MONITOR) 01816 ztc.confmode = ZT_CONF_CONFMON | ZT_CONF_LISTENER; 01817 else if (confflags & CONFFLAG_TALKER) 01818 ztc.confmode = ZT_CONF_CONF | ZT_CONF_TALKER; 01819 else 01820 ztc.confmode = ZT_CONF_CONF | ZT_CONF_TALKER | ZT_CONF_LISTENER; 01821 if (ioctl(fd, ZT_SETCONF, &ztc)) { 01822 ast_log(LOG_WARNING, "Error setting conference\n"); 01823 close(fd); 01824 goto outrun; 01825 } 01826 if (musiconhold && (confflags & CONFFLAG_MOH)) { 01827 ast_moh_stop(chan); 01828 musiconhold = 0; 01829 } 01830 if ( !(confflags & CONFFLAG_QUIET) && !(confflags & CONFFLAG_MARKEDUSER)) { 01831 if (!ast_streamfile(chan, "conf-placeintoconf", chan->language)) 01832 ast_waitstream(chan, ""); 01833 conf_play(chan, conf, ENTER); 01834 } 01835 } 01836 } 01837 01838 /* trying to add moh for single person conf */ 01839 if ((confflags & CONFFLAG_MOH) && !(confflags & CONFFLAG_WAITMARKED)) { 01840 if (conf->users == 1) { 01841 if (musiconhold == 0) { 01842 ast_moh_start(chan, NULL, NULL); 01843 musiconhold = 1; 01844 } 01845 } else { 01846 if (musiconhold) { 01847 ast_moh_stop(chan); 01848 musiconhold = 0; 01849 } 01850 } 01851 } 01852 01853 /* Leave if the last marked user left */ 01854 if (currentmarked == 0 && lastmarked != 0 && (confflags & CONFFLAG_MARKEDEXIT)) { 01855 ret = -1; 01856 break; 01857 } 01858 01859 /* Check if my modes have changed */ 01860 01861 /* If I should be muted but am still talker, mute me */ 01862 if ((user->adminflags & (ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED)) && (ztc.confmode & ZT_CONF_TALKER)) { 01863 ztc.confmode ^= ZT_CONF_TALKER; 01864 if (ioctl(fd, ZT_SETCONF, &ztc)) { 01865 ast_log(LOG_WARNING, "Error setting conference - Un/Mute \n"); 01866 ret = -1; 01867 break; 01868 } 01869 01870 manager_event(EVENT_FLAG_CALL, "MeetmeMute", 01871 "Channel: %s\r\n" 01872 "Uniqueid: %s\r\n" 01873 "Meetme: %s\r\n" 01874 "Usernum: %i\r\n" 01875 "Status: on\r\n", 01876 chan->name, chan->uniqueid, conf->confno, user->user_no); 01877 } 01878 01879 /* If I should be un-muted but am not talker, un-mute me */ 01880 if (!(user->adminflags & (ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED)) && !(confflags & CONFFLAG_MONITOR) && !(ztc.confmode & ZT_CONF_TALKER)) { 01881 ztc.confmode |= ZT_CONF_TALKER; 01882 if (ioctl(fd, ZT_SETCONF, &ztc)) { 01883 ast_log(LOG_WARNING, "Error setting conference - Un/Mute \n"); 01884 ret = -1; 01885 break; 01886 } 01887 01888 manager_event(EVENT_FLAG_CALL, "MeetmeMute", 01889 "Channel: %s\r\n" 01890 "Uniqueid: %s\r\n" 01891 "Meetme: %s\r\n" 01892 "Usernum: %i\r\n" 01893 "Status: off\r\n", 01894 chan->name, chan->uniqueid, conf->confno, user->user_no); 01895 } 01896 01897 /* If I have been kicked, exit the conference */ 01898 if (user->adminflags & ADMINFLAG_KICKME) { 01899 //You have been kicked. 01900 if (!(confflags & CONFFLAG_QUIET) && 01901 !ast_streamfile(chan, "conf-kicked", chan->language)) { 01902 ast_waitstream(chan, ""); 01903 } 01904 ret = 0; 01905 break; 01906 } 01907 01908 /* Perform an extra hangup check just in case */ 01909 if (ast_check_hangup(chan)) 01910 break; 01911 01912 if (c) { 01913 if (c->fds[0] != origfd || (user->zapchannel && (c->audiohooks || c->monitor))) { 01914 if (using_pseudo) { 01915 /* Kill old pseudo */ 01916 close(fd); 01917 using_pseudo = 0; 01918 } 01919 ast_log(LOG_DEBUG, "Ooh, something swapped out under us, starting over\n"); 01920 retryzap = (strcasecmp(c->tech->type, "Zap") || (c->audiohooks || c->monitor) ? 1 : 0); 01921 user->zapchannel = !retryzap; 01922 goto zapretry; 01923 } 01924 if ((confflags & CONFFLAG_MONITOR) || (user->adminflags & (ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED))) 01925 f = ast_read_noaudio(c); 01926 else 01927 f = ast_read(c); 01928 if (!f) 01929 break; 01930 if (f->datalen && f->datalen != dyna_buff) { 01931 ast_log(LOG_NOTICE, "Audio bytes: %d Buffer size: %d\n", f->datalen, dyna_buff); 01932 if (f->datalen < ZT_MAX_BUF_SPACE/audio_buffers) { /* skip too large frame to avoid overflow */ 01933 dyna_buff = f->datalen; 01934 close(fd); 01935 goto zapretry; 01936 } 01937 } 01938 if ((f->frametype == AST_FRAME_VOICE) && (f->subclass == AST_FORMAT_SLINEAR)) { 01939 if (user->talk.actual) 01940 ast_frame_adjust_volume(f, user->talk.actual); 01941 01942 if (confflags & (CONFFLAG_MONITORTALKER | CONFFLAG_OPTIMIZETALKER)) { 01943 int totalsilence; 01944 01945 if (user->talking == -1) 01946 user->talking = 0; 01947 01948 res = ast_dsp_silence(dsp, f, &totalsilence); 01949 if (!user->talking && totalsilence < MEETME_DELAYDETECTTALK) { 01950 user->talking = 1; 01951 if (confflags & CONFFLAG_MONITORTALKER) 01952 manager_event(EVENT_FLAG_CALL, "MeetmeTalking", 01953 "Channel: %s\r\n" 01954 "Uniqueid: %s\r\n" 01955 "Meetme: %s\r\n" 01956 "Usernum: %d\r\n" 01957 "Status: on\r\n", 01958 chan->name, chan->uniqueid, conf->confno, user->user_no); 01959 } 01960 if (user->talking && totalsilence > MEETME_DELAYDETECTENDTALK) { 01961 user->talking = 0; 01962 if (confflags & CONFFLAG_MONITORTALKER) 01963 manager_event(EVENT_FLAG_CALL, "MeetmeTalking", 01964 "Channel: %s\r\n" 01965 "Uniqueid: %s\r\n" 01966 "Meetme: %s\r\n" 01967 "Usernum: %d\r\n" 01968 "Status: off\r\n", 01969 chan->name, chan->uniqueid, conf->confno, user->user_no); 01970 } 01971 } 01972 if (using_pseudo) { 01973 /* Absolutely do _not_ use careful_write here... 01974 it is important that we read data from the channel 01975 as fast as it arrives, and feed it into the conference. 01976 The buffering in the pseudo channel will take care of any 01977 timing differences, unless they are so drastic as to lose 01978 audio frames (in which case carefully writing would only 01979 have delayed the audio even further). 01980 */ 01981 /* As it turns out, we do want to use careful write. We just 01982 don't want to block, but we do want to at least *try* 01983 to write out all the samples. 01984 */ 01985 if (user->talking || !(confflags & CONFFLAG_OPTIMIZETALKER)) 01986 careful_write(fd, f->data, f->datalen, 0); 01987 } 01988 } else if ((f->frametype == AST_FRAME_DTMF) && (confflags & CONFFLAG_EXIT_CONTEXT)) { 01989 char tmp[2]; 01990 01991 if (confflags & CONFFLAG_PASS_DTMF) 01992 conf_queue_dtmf(conf, user, f); 01993 01994 tmp[0] = f->subclass; 01995 tmp[1] = '\0'; 01996 if (!ast_goto_if_exists(chan, exitcontext, tmp, 1)) { 01997 ast_log(LOG_DEBUG, "Got DTMF %c, goto context %s\n", tmp[0], exitcontext); 01998 ret = 0; 01999 ast_frfree(f); 02000 break; 02001 } else if (option_debug > 1) 02002 ast_log(LOG_DEBUG, "Exit by single digit did not work in meetme. Extension %s does not exist in context %s\n", tmp, exitcontext); 02003 } else if ((f->frametype == AST_FRAME_DTMF) && (f->subclass == '#') && (confflags & CONFFLAG_POUNDEXIT)) { 02004 if (confflags & CONFFLAG_PASS_DTMF) 02005 conf_queue_dtmf(conf, user, f); 02006 ret = 0; 02007 ast_frfree(f); 02008 break; 02009 } else if (((f->frametype == AST_FRAME_DTMF) && (f->subclass == '*') && (confflags & CONFFLAG_STARMENU)) || ((f->frametype == AST_FRAME_DTMF) && menu_active)) { 02010 if (confflags & CONFFLAG_PASS_DTMF) 02011 conf_queue_dtmf(conf, user, f); 02012 if (ioctl(fd, ZT_SETCONF, &ztc_empty)) { 02013 ast_log(LOG_WARNING, "Error setting conference\n"); 02014 close(fd); 02015 ast_frfree(f); 02016 goto outrun; 02017 } 02018 02019 /* if we are entering the menu, and the user has a channel-driver 02020 volume adjustment, clear it 02021 */ 02022 if (!menu_active && user->talk.desired && !user->talk.actual) 02023 set_talk_volume(user, 0); 02024 02025 if (musiconhold) { 02026 ast_moh_stop(chan); 02027 } 02028 if ((confflags & CONFFLAG_ADMIN)) { 02029 /* Admin menu */ 02030 if (!menu_active) { 02031 menu_active = 1; 02032 /* Record this sound! */ 02033 if (!ast_streamfile(chan, "conf-adminmenu", chan->language)) { 02034 dtmf = ast_waitstream(chan, AST_DIGIT_ANY); 02035 ast_stopstream(chan); 02036 } else 02037 dtmf = 0; 02038 } else 02039 dtmf = f->subclass; 02040 if (dtmf) { 02041 switch(dtmf) { 02042 case '1': /* Un/Mute */ 02043 menu_active = 0; 02044 02045 /* for admin, change both admin and use flags */ 02046 if (user->adminflags & (ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED)) 02047 user->adminflags &= ~(ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED); 02048 else 02049 user->adminflags |= (ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED); 02050 02051 if ((confflags & CONFFLAG_MONITOR) || (user->adminflags & (ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED))) { 02052 if (!ast_streamfile(chan, "conf-muted", chan->language)) 02053 ast_waitstream(chan, ""); 02054 } else { 02055 if (!ast_streamfile(chan, "conf-unmuted", chan->language)) 02056 ast_waitstream(chan, ""); 02057 } 02058 break; 02059 case '2': /* Un/Lock the Conference */ 02060 menu_active = 0; 02061 if (conf->locked) { 02062 conf->locked = 0; 02063 if (!ast_streamfile(chan, "conf-unlockednow", chan->language)) 02064 ast_waitstream(chan, ""); 02065 } else { 02066 conf->locked = 1; 02067 if (!ast_streamfile(chan, "conf-lockednow", chan->language)) 02068 ast_waitstream(chan, ""); 02069 } 02070 break; 02071 case '3': /* Eject last user */ 02072 menu_active = 0; 02073 usr = AST_LIST_LAST(&conf->userlist); 02074 if ((usr->chan->name == chan->name)||(usr->userflags & CONFFLAG_ADMIN)) { 02075 if(!ast_streamfile(chan, "conf-errormenu", chan->language)) 02076 ast_waitstream(chan, ""); 02077 } else 02078 usr->adminflags |= ADMINFLAG_KICKME; 02079 ast_stopstream(chan); 02080 break; 02081 case '4': 02082 tweak_listen_volume(user, VOL_DOWN); 02083 break; 02084 case '6': 02085 tweak_listen_volume(user, VOL_UP); 02086 break; 02087 case '7': 02088 tweak_talk_volume(user, VOL_DOWN); 02089 break; 02090 case '8': 02091 menu_active = 0; 02092 break; 02093 case '9': 02094 tweak_talk_volume(user, VOL_UP); 02095 break; 02096 default: 02097 menu_active = 0; 02098 /* Play an error message! */ 02099 if (!ast_streamfile(chan, "conf-errormenu", chan->language)) 02100 ast_waitstream(chan, ""); 02101 break; 02102 } 02103 } 02104 } else { 02105 /* User menu */ 02106 if (!menu_active) { 02107 menu_active = 1; 02108 if (!ast_streamfile(chan, "conf-usermenu", chan->language)) { 02109 dtmf = ast_waitstream(chan, AST_DIGIT_ANY); 02110 ast_stopstream(chan); 02111 } else 02112 dtmf = 0; 02113 } else 02114 dtmf = f->subclass; 02115 if (dtmf) { 02116 switch(dtmf) { 02117 case '1': /* Un/Mute */ 02118 menu_active = 0; 02119 02120 /* user can only toggle the self-muted state */ 02121 user->adminflags ^= ADMINFLAG_SELFMUTED; 02122 02123 /* they can't override the admin mute state */ 02124 if ((confflags & CONFFLAG_MONITOR) || (user->adminflags & (ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED))) { 02125 if (!ast_streamfile(chan, "conf-muted", chan->language)) 02126 ast_waitstream(chan, ""); 02127 } else { 02128 if (!ast_streamfile(chan, "conf-unmuted", chan->language)) 02129 ast_waitstream(chan, ""); 02130 } 02131 break; 02132 case '4': 02133 tweak_listen_volume(user, VOL_DOWN); 02134 break; 02135 case '6': 02136 tweak_listen_volume(user, VOL_UP); 02137 break; 02138 case '7': 02139 tweak_talk_volume(user, VOL_DOWN); 02140 break; 02141 case '8': 02142 menu_active = 0; 02143 break; 02144 case '9': 02145 tweak_talk_volume(user, VOL_UP); 02146 break; 02147 default: 02148 menu_active = 0; 02149 if (!ast_streamfile(chan, "conf-errormenu", chan->language)) 02150 ast_waitstream(chan, ""); 02151 break; 02152 } 02153 } 02154 } 02155 if (musiconhold) 02156 ast_moh_start(chan, NULL, NULL); 02157 02158 if (ioctl(fd, ZT_SETCONF, &ztc)) { 02159 ast_log(LOG_WARNING, "Error setting conference\n"); 02160 close(fd); 02161 ast_frfree(f); 02162 goto outrun; 02163 } 02164 02165 conf_flush(fd, chan); 02166 } else if ((f->frametype == AST_FRAME_DTMF_BEGIN || f->frametype == AST_FRAME_DTMF_END) 02167 && confflags & CONFFLAG_PASS_DTMF) { 02168 conf_queue_dtmf(conf, user, f); 02169 } else if ((confflags & CONFFLAG_SLA_STATION) && f->frametype == AST_FRAME_CONTROL) { 02170 switch (f->subclass) { 02171 case AST_CONTROL_HOLD: 02172 sla_queue_event_conf(SLA_EVENT_HOLD, chan, conf); 02173 break; 02174 default: 02175 break; 02176 } 02177 } else if (f->frametype == AST_FRAME_NULL) { 02178 /* Ignore NULL frames. It is perfectly normal to get these if the person is muted. */ 02179 } else if (option_debug) { 02180 ast_log(LOG_DEBUG, 02181 "Got unrecognized frame on channel %s, f->frametype=%d,f->subclass=%d\n", 02182 chan->name, f->frametype, f->subclass); 02183 } 02184 ast_frfree(f); 02185 } else if (outfd > -1) { 02186 res = read(outfd, buf, CONF_SIZE); 02187 if (res > 0) { 02188 memset(&fr, 0, sizeof(fr)); 02189 fr.frametype = AST_FRAME_VOICE; 02190 fr.subclass = AST_FORMAT_SLINEAR; 02191 fr.datalen = res; 02192 fr.samples = res/2; 02193 fr.data = buf; 02194 fr.offset = AST_FRIENDLY_OFFSET; 02195 if (!user->listen.actual && 02196 ((confflags & CONFFLAG_MONITOR) || 02197 (user->adminflags & (ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED)) || 02198 (!user->talking && (confflags & CONFFLAG_OPTIMIZETALKER)) 02199 )) { 02200 int index; 02201 for (index=0;index<AST_FRAME_BITS;index++) 02202 if (chan->rawwriteformat & (1 << index)) 02203 break; 02204 if (index >= AST_FRAME_BITS) 02205 goto bailoutandtrynormal; 02206 ast_mutex_lock(&conf->listenlock); 02207 if (!conf->transframe[index]) { 02208 if (conf->origframe) { 02209 if (!conf->transpath[index]) 02210 conf->transpath[index] = ast_translator_build_path((1 << index), AST_FORMAT_SLINEAR); 02211 if (conf->transpath[index]) { 02212 conf->transframe[index] = ast_translate(conf->transpath[index], conf->origframe, 0); 02213 if (!conf->transframe[index]) 02214 conf->transframe[index] = &ast_null_frame; 02215 } 02216 } 02217 } 02218 if (conf->transframe[index]) { 02219 if (conf->transframe[index]->frametype != AST_FRAME_NULL) { 02220 if (ast_write(chan, conf->transframe[index])) 02221 ast_log(LOG_WARNING, "Unable to write frame to channel %s\n", chan->name); 02222 } 02223 } else { 02224 ast_mutex_unlock(&conf->listenlock); 02225 goto bailoutandtrynormal; 02226 } 02227 ast_mutex_unlock(&conf->listenlock); 02228 } else { 02229 bailoutandtrynormal: 02230 if (user->listen.actual) 02231 ast_frame_adjust_volume(&fr, user->listen.actual); 02232 if (ast_write(chan, &fr) < 0) { 02233 ast_log(LOG_WARNING, "Unable to write frame to channel %s\n", chan->name); 02234 } 02235 } 02236 } else 02237 ast_log(LOG_WARNING, "Failed to read frame: %s\n", strerror(errno)); 02238 } 02239 lastmarked = currentmarked; 02240 } 02241 } 02242 02243 if (musiconhold) 02244 ast_moh_stop(chan); 02245 02246 if (using_pseudo) 02247 close(fd); 02248 else { 02249 /* Take out of conference */ 02250 ztc.chan = 0; 02251 ztc.confno = 0; 02252 ztc.confmode = 0; 02253 if (ioctl(fd, ZT_SETCONF, &ztc)) { 02254 ast_log(LOG_WARNING, "Error setting conference\n"); 02255 } 02256 } 02257 02258 reset_volumes(user); 02259 02260 AST_LIST_LOCK(&confs); 02261 if (!(confflags & CONFFLAG_QUIET) && !(confflags & CONFFLAG_MONITOR) && !(confflags & CONFFLAG_ADMIN)) 02262 conf_play(chan, conf, LEAVE); 02263 02264 if (!(confflags & CONFFLAG_QUIET) && ((confflags & CONFFLAG_INTROUSER) || (confflags & CONFFLAG_INTROUSERNOREVIEW))) { 02265 if (ast_fileexists(user->namerecloc, NULL, NULL)) { 02266 if ((conf->chan) && (conf->users > 1)) { 02267 if (!ast_streamfile(conf->chan, user->namerecloc, chan->language)) 02268 ast_waitstream(conf->chan, ""); 02269 if (!ast_streamfile(conf->chan, "conf-hasleft", chan->language)) 02270 ast_waitstream(conf->chan, ""); 02271 } 02272 ast_filedelete(user->namerecloc, NULL); 02273 } 02274 } 02275 AST_LIST_UNLOCK(&confs); 02276 02277 outrun: 02278 AST_LIST_LOCK(&confs); 02279 02280 if (dsp) 02281 ast_dsp_free(dsp); 02282 02283 if (user->user_no) { /* Only cleanup users who really joined! */ 02284 now = time(NULL); 02285 hr = (now - user->jointime) / 3600; 02286 min = ((now - user->jointime) % 3600) / 60; 02287 sec = (now - user->jointime) % 60; 02288 02289 if (sent_event) { 02290 manager_event(EVENT_FLAG_CALL, "MeetmeLeave", 02291 "Channel: %s\r\n" 02292 "Uniqueid: %s\r\n" 02293 "Meetme: %s\r\n" 02294 "Usernum: %d\r\n" 02295 "CallerIDnum: %s\r\n" 02296 "CallerIDname: %s\r\n" 02297 "Duration: %ld\r\n", 02298 chan->name, chan->uniqueid, conf->confno, 02299 user->user_no, 02300 S_OR(user->chan->cid.cid_num, "<unknown>"), 02301 S_OR(user->chan->cid.cid_name, "<unknown>"), 02302 (long)(now - user->jointime)); 02303 } 02304 02305 if (setusercount) { 02306 conf->users--; 02307 /* Update table */ 02308 snprintf(members, sizeof(members), "%d", conf->users); 02309 ast_update_realtime("meetme", "confno", conf->confno, "members", members, NULL); 02310 if (confflags & CONFFLAG_MARKEDUSER) 02311 conf->markedusers--; 02312 } 02313 /* Remove ourselves from the list */ 02314 AST_LIST_REMOVE(&conf->userlist, user, list); 02315 02316 /* Change any states */ 02317 if (!conf->users) 02318 ast_device_state_changed("meetme:%s", conf->confno); 02319 02320 /* Return the number of seconds the user was in the conf */ 02321 snprintf(meetmesecs, sizeof(meetmesecs), "%d", (int) (time(NULL) - user->jointime)); 02322 pbx_builtin_setvar_helper(chan, "MEETMESECS", meetmesecs); 02323 } 02324 free(user); 02325 AST_LIST_UNLOCK(&confs); 02326 02327 return ret; 02328 }
static int count_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
The MeetmeCount application.
Definition at line 2481 of file app_meetme.c.
References ast_channel::_state, ast_answer(), AST_APP_ARG, AST_DECLARE_APP_ARGS, ast_log(), ast_module_user_add, ast_module_user_remove, ast_say_number(), AST_STANDARD_APP_ARGS, AST_STATE_UP, ast_strdupa, ast_strlen_zero(), ast_conference::chan, ast_conference::confno, dispose_conf(), find_conf(), LOG_WARNING, pbx_builtin_setvar_helper(), and ast_conference::users.
Referenced by load_module().
02482 { 02483 struct ast_module_user *u; 02484 int res = 0; 02485 struct ast_conference *conf; 02486 int count; 02487 char *localdata; 02488 char val[80] = "0"; 02489 AST_DECLARE_APP_ARGS(args, 02490 AST_APP_ARG(confno); 02491 AST_APP_ARG(varname); 02492 ); 02493 02494 if (ast_strlen_zero(data)) { 02495 ast_log(LOG_WARNING, "MeetMeCount requires an argument (conference number)\n"); 02496 return -1; 02497 } 02498 02499 u = ast_module_user_add(chan); 02500 02501 if (!(localdata = ast_strdupa(data))) { 02502 ast_module_user_remove(u); 02503 return -1; 02504 } 02505 02506 AST_STANDARD_APP_ARGS(args, localdata); 02507 02508 conf = find_conf(chan, args.confno, 0, 0, NULL, 0, 1, NULL); 02509 02510 if (conf) { 02511 count = conf->users; 02512 dispose_conf(conf); 02513 conf = NULL; 02514 } else 02515 count = 0; 02516 02517 if (!ast_strlen_zero(args.varname)){ 02518 /* have var so load it and exit */ 02519 snprintf(val, sizeof(val), "%d",count); 02520 pbx_builtin_setvar_helper(chan, args.varname, val); 02521 } else { 02522 if (chan->_state != AST_STATE_UP) 02523 ast_answer(chan); 02524 res = ast_say_number(chan, count, "", chan->language, (char *) NULL); /* Needs gender */ 02525 } 02526 ast_module_user_remove(u); 02527 02528 return res; 02529 }
static struct sla_trunk_ref* create_trunk_ref | ( | struct sla_trunk * | trunk | ) | [static] |
Definition at line 4299 of file app_meetme.c.
References ast_calloc.
Referenced by sla_add_trunk_to_station().
04300 { 04301 struct sla_trunk_ref *trunk_ref; 04302 04303 if (!(trunk_ref = ast_calloc(1, sizeof(*trunk_ref)))) 04304 return NULL; 04305 04306 trunk_ref->trunk = trunk; 04307 04308 return trunk_ref; 04309 }
static void destroy_station | ( | struct sla_station * | station | ) | [static] |
Definition at line 4467 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_destroy().
04468 { 04469 struct sla_trunk_ref *trunk_ref; 04470 04471 if (!ast_strlen_zero(station->autocontext)) { 04472 AST_RWLIST_RDLOCK(&sla_trunks); 04473 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) { 04474 char exten[AST_MAX_EXTENSION]; 04475 char hint[AST_MAX_APP]; 04476 snprintf(exten, sizeof(exten), "%s_%s", station->name, trunk_ref->trunk->name); 04477 snprintf(hint, sizeof(hint), "SLA:%s", exten); 04478 ast_context_remove_extension(station->autocontext, exten, 04479 1, sla_registrar); 04480 ast_context_remove_extension(station->autocontext, hint, 04481 PRIORITY_HINT, sla_registrar); 04482 } 04483 AST_RWLIST_UNLOCK(&sla_trunks); 04484 } 04485 04486 while ((trunk_ref = AST_LIST_REMOVE_HEAD(&station->trunks, entry))) 04487 free(trunk_ref); 04488 04489 ast_string_field_free_memory(station); 04490 free(station); 04491 }
static void destroy_trunk | ( | struct sla_trunk * | trunk | ) | [static] |
Definition at line 4453 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_destroy().
04454 { 04455 struct sla_station_ref *station_ref; 04456 04457 if (!ast_strlen_zero(trunk->autocontext)) 04458 ast_context_remove_extension(trunk->autocontext, "s", 1, sla_registrar); 04459 04460 while ((station_ref = AST_LIST_REMOVE_HEAD(&trunk->stations, entry))) 04461 free(station_ref); 04462 04463 ast_string_field_free_memory(trunk); 04464 free(trunk); 04465 }
static void* dial_trunk | ( | void * | data | ) | [static] |
Definition at line 4018 of file app_meetme.c.
References ast_cond_signal(), ast_dial_answered(), ast_dial_append(), ast_dial_create(), ast_dial_destroy(), ast_dial_join(), AST_DIAL_RESULT_ANSWERED, AST_DIAL_RESULT_FAILED, AST_DIAL_RESULT_HANGUP, AST_DIAL_RESULT_INVALID, AST_DIAL_RESULT_PROCEEDING, AST_DIAL_RESULT_PROGRESS, AST_DIAL_RESULT_RINGING, AST_DIAL_RESULT_TIMEOUT, AST_DIAL_RESULT_TRYING, AST_DIAL_RESULT_UNANSWERED, ast_dial_run(), ast_dial_state(), ast_mutex_lock(), ast_mutex_unlock(), ast_strdup, ast_strdupa, ast_strlen_zero(), cid_name, cid_num, dial_trunk_args::cond, dial_trunk_args::cond_lock, free, MAX_CONFNUM, sla, strsep(), and dial_trunk_args::trunk_ref.
Referenced by sla_station_exec().
04019 { 04020 struct dial_trunk_args *args = data; 04021 struct ast_dial *dial; 04022 char *tech, *tech_data; 04023 enum ast_dial_result dial_res; 04024 char conf_name[MAX_CONFNUM]; 04025 struct ast_conference *conf; 04026 struct ast_flags conf_flags = { 0 }; 04027 struct sla_trunk_ref *trunk_ref = args->trunk_ref; 04028 const char *cid_name = NULL, *cid_num = NULL; 04029 04030 if (!(dial = ast_dial_create())) { 04031 ast_mutex_lock(args->cond_lock); 04032 ast_cond_signal(args->cond); 04033 ast_mutex_unlock(args->cond_lock); 04034 return NULL; 04035 } 04036 04037 tech_data = ast_strdupa(trunk_ref->trunk->device); 04038 tech = strsep(&tech_data, "/"); 04039 if (ast_dial_append(dial, tech, tech_data) == -1) { 04040 ast_mutex_lock(args->cond_lock); 04041 ast_cond_signal(args->cond); 04042 ast_mutex_unlock(args->cond_lock); 04043 ast_dial_destroy(dial); 04044 return NULL; 04045 } 04046 04047 if (!sla.attempt_callerid && !ast_strlen_zero(trunk_ref->chan->cid.cid_name)) { 04048 cid_name = ast_strdupa(trunk_ref->chan->cid.cid_name); 04049 free(trunk_ref->chan->cid.cid_name); 04050 trunk_ref->chan->cid.cid_name = NULL; 04051 } 04052 if (!sla.attempt_callerid && !ast_strlen_zero(trunk_ref->chan->cid.cid_num)) { 04053 cid_num = ast_strdupa(trunk_ref->chan->cid.cid_num); 04054 free(trunk_ref->chan->cid.cid_num); 04055 trunk_ref->chan->cid.cid_num = NULL; 04056 } 04057 04058 dial_res = ast_dial_run(dial, trunk_ref->chan, 1); 04059 04060 if (cid_name) 04061 trunk_ref->chan->cid.cid_name = ast_strdup(cid_name); 04062 if (cid_num) 04063 trunk_ref->chan->cid.cid_num = ast_strdup(cid_num); 04064 04065 if (dial_res != AST_DIAL_RESULT_TRYING) { 04066 ast_mutex_lock(args->cond_lock); 04067 ast_cond_signal(args->cond); 04068 ast_mutex_unlock(args->cond_lock); 04069 ast_dial_destroy(dial); 04070 return NULL; 04071 } 04072 04073 for (;;) { 04074 unsigned int done = 0; 04075 switch ((dial_res = ast_dial_state(dial))) { 04076 case AST_DIAL_RESULT_ANSWERED: 04077 trunk_ref->trunk->chan = ast_dial_answered(dial); 04078 case AST_DIAL_RESULT_HANGUP: 04079 case AST_DIAL_RESULT_INVALID: 04080 case AST_DIAL_RESULT_FAILED: 04081 case AST_DIAL_RESULT_TIMEOUT: 04082 case AST_DIAL_RESULT_UNANSWERED: 04083 done = 1; 04084 case AST_DIAL_RESULT_TRYING: 04085 case AST_DIAL_RESULT_RINGING: 04086 case AST_DIAL_RESULT_PROGRESS: 04087 case AST_DIAL_RESULT_PROCEEDING: 04088 break; 04089 } 04090 if (done) 04091 break; 04092 } 04093 04094 if (!trunk_ref->trunk->chan) { 04095 ast_mutex_lock(args->cond_lock); 04096 ast_cond_signal(args->cond); 04097 ast_mutex_unlock(args->cond_lock); 04098 ast_dial_join(dial); 04099 ast_dial_destroy(dial); 04100 return NULL; 04101 } 04102 04103 snprintf(conf_name, sizeof(conf_name), "SLA_%s", trunk_ref->trunk->name); 04104 ast_set_flag(&conf_flags, 04105 CONFFLAG_QUIET | CONFFLAG_MARKEDEXIT | CONFFLAG_MARKEDUSER | 04106 CONFFLAG_PASS_DTMF | CONFFLAG_SLA_TRUNK); 04107 conf = build_conf(conf_name, "", "", 1, 1, 1); 04108 04109 ast_mutex_lock(args->cond_lock); 04110 ast_cond_signal(args->cond); 04111 ast_mutex_unlock(args->cond_lock); 04112 04113 if (conf) { 04114 conf_run(trunk_ref->trunk->chan, conf, conf_flags.flags, NULL); 04115 dispose_conf(conf); 04116 conf = NULL; 04117 } 04118 04119 /* If the trunk is going away, it is definitely now IDLE. */ 04120 sla_change_trunk_state(trunk_ref->trunk, SLA_TRUNK_STATE_IDLE, ALL_TRUNK_REFS, NULL); 04121 04122 trunk_ref->trunk->chan = NULL; 04123 trunk_ref->trunk->on_hold = 0; 04124 04125 ast_dial_join(dial); 04126 ast_dial_destroy(dial); 04127 04128 return NULL; 04129 }
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(), 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] |
Definition at line 2387 of file app_meetme.c.
References AST_APP_ARG, ast_app_getdata(), 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_variable_browse(), build_conf(), ast_conference::chan, CONFIG_FILE_NAME, ast_conference::confno, LOG_DEBUG, LOG_WARNING, parse(), ast_conference::pin, ast_conference::pinadmin, ast_conference::refcount, S_OR, and var.
Referenced by conf_exec(), and count_exec().
02389 { 02390 struct ast_config *cfg; 02391 struct ast_variable *var; 02392 struct ast_conference *cnf; 02393 char *parse; 02394 AST_DECLARE_APP_ARGS(args, 02395 AST_APP_ARG(confno); 02396 AST_APP_ARG(pin); 02397 AST_APP_ARG(pinadmin); 02398 ); 02399 02400 /* Check first in the conference list */ 02401 AST_LIST_LOCK(&confs); 02402 AST_LIST_TRAVERSE(&confs, cnf, list) { 02403 if (!strcmp(confno, cnf->confno)) 02404 break; 02405 } 02406 if (cnf){ 02407 cnf->refcount += refcount; 02408 } 02409 AST_LIST_UNLOCK(&confs); 02410 02411 if (!cnf) { 02412 if (dynamic) { 02413 /* No need to parse meetme.conf */ 02414 ast_log(LOG_DEBUG, "Building dynamic conference '%s'\n", confno); 02415 if (dynamic_pin) { 02416 if (dynamic_pin[0] == 'q') { 02417 /* Query the user to enter a PIN */ 02418 if (ast_app_getdata(chan, "conf-getpin", dynamic_pin, pin_buf_len - 1, 0) < 0) 02419 return NULL; 02420 } 02421 cnf = build_conf(confno, dynamic_pin, "", make, dynamic, refcount); 02422 } else { 02423 cnf = build_conf(confno, "", "", make, dynamic, refcount); 02424 } 02425 } else { 02426 /* Check the config */ 02427 cfg = ast_config_load(CONFIG_FILE_NAME); 02428 if (!cfg) { 02429 ast_log(LOG_WARNING, "No %s file :(\n", CONFIG_FILE_NAME); 02430 return NULL; 02431 } 02432 for (var = ast_variable_browse(cfg, "rooms"); var; var = var->next) { 02433 if (strcasecmp(var->name, "conf")) 02434 continue; 02435 02436 if (!(parse = ast_strdupa(var->value))) 02437 return NULL; 02438 02439 AST_NONSTANDARD_APP_ARGS(args, parse, ','); 02440 if (!strcasecmp(args.confno, confno)) { 02441 /* Bingo it's a valid conference */ 02442 cnf = build_conf(args.confno, 02443 S_OR(args.pin, ""), 02444 S_OR(args.pinadmin, ""), 02445 make, dynamic, refcount); 02446 break; 02447 } 02448 } 02449 if (!var) { 02450 ast_log(LOG_DEBUG, "%s isn't a valid conference\n", confno); 02451 } 02452 ast_config_destroy(cfg); 02453 } 02454 } else if (dynamic_pin) { 02455 /* Correct for the user selecting 'D' instead of 'd' to have 02456 someone join into a conference that has already been created 02457 with a pin. */ 02458 if (dynamic_pin[0] == 'q') 02459 dynamic_pin[0] = '\0'; 02460 } 02461 02462 if (cnf) { 02463 if (confflags && !cnf->chan && 02464 !ast_test_flag(confflags, CONFFLAG_QUIET) && 02465 ast_test_flag(confflags, CONFFLAG_INTROUSER)) { 02466 ast_log(LOG_WARNING, "No Zap channel available for conference, user introduction disabled (is chan_zap loaded?)\n"); 02467 ast_clear_flag(confflags, CONFFLAG_INTROUSER); 02468 } 02469 02470 if (confflags && !cnf->chan && 02471 ast_test_flag(confflags, CONFFLAG_RECORDCONF)) { 02472 ast_log(LOG_WARNING, "No Zap channel available for conference, conference recording disabled (is chan_zap loaded?)\n"); 02473 ast_clear_flag(confflags, CONFFLAG_RECORDCONF); 02474 } 02475 } 02476 02477 return cnf; 02478 }
static struct ast_conference* find_conf_realtime | ( | struct ast_channel * | chan, | |
char * | confno, | |||
int | make, | |||
int | dynamic, | |||
char * | dynamic_pin, | |||
size_t | pin_buf_len, | |||
int | refcount, | |||
struct ast_flags * | confflags | |||
) | [static] |
Definition at line 2330 of file app_meetme.c.
References ast_clear_flag, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_load_realtime(), ast_log(), ast_strdupa, ast_test_flag, ast_variables_destroy(), build_conf(), ast_conference::chan, CONFFLAG_RECORDCONF, ast_conference::confno, LOG_WARNING, ast_conference::pin, ast_conference::pinadmin, ast_conference::refcount, and var.
Referenced by conf_exec().
02332 { 02333 struct ast_variable *var; 02334 struct ast_conference *cnf; 02335 02336 /* Check first in the conference list */ 02337 AST_LIST_LOCK(&confs); 02338 AST_LIST_TRAVERSE(&confs, cnf, list) { 02339 if (!strcmp(confno, cnf->confno)) 02340 break; 02341 } 02342 if (cnf) { 02343 cnf->refcount += refcount; 02344 } 02345 AST_LIST_UNLOCK(&confs); 02346 02347 if (!cnf) { 02348 char *pin = NULL, *pinadmin = NULL; /* For temp use */ 02349 02350 var = ast_load_realtime("meetme", "confno", confno, NULL); 02351 02352 if (!var) 02353 return NULL; 02354 02355 while (var) { 02356 if (!strcasecmp(var->name, "pin")) { 02357 pin = ast_strdupa(var->value); 02358 } else if (!strcasecmp(var->name, "adminpin")) { 02359 pinadmin = ast_strdupa(var->value); 02360 } 02361 var = var->next; 02362 } 02363 ast_variables_destroy(var); 02364 02365 cnf = build_conf(confno, pin ? pin : "", pinadmin ? pinadmin : "", make, dynamic, refcount); 02366 } 02367 02368 if (cnf) { 02369 if (confflags && !cnf->chan && 02370 !ast_test_flag(confflags, CONFFLAG_QUIET) && 02371 ast_test_flag(confflags, CONFFLAG_INTROUSER)) { 02372 ast_log(LOG_WARNING, "No Zap channel available for conference, user introduction disabled (is chan_zap loaded?)\n"); 02373 ast_clear_flag(confflags, CONFFLAG_INTROUSER); 02374 } 02375 02376 if (confflags && !cnf->chan && 02377 ast_test_flag(confflags, CONFFLAG_RECORDCONF)) { 02378 ast_log(LOG_WARNING, "No Zap channel available for conference, conference recording disabled (is chan_zap loaded?)\n"); 02379 ast_clear_flag(confflags, CONFFLAG_RECORDCONF); 02380 } 02381 } 02382 02383 return cnf; 02384 }
static struct ast_conf_user* find_user | ( | struct ast_conference * | conf, | |
char * | callerident | |||
) | [static] |
Definition at line 2778 of file app_meetme.c.
References AST_LIST_TRAVERSE, and ast_conf_user::user_no.
02779 { 02780 struct ast_conf_user *user = NULL; 02781 int cid; 02782 02783 sscanf(callerident, "%i", &cid); 02784 if (conf && callerident) { 02785 AST_LIST_TRAVERSE(&conf->userlist, user, list) { 02786 if (cid == user->user_no) 02787 return user; 02788 } 02789 } 02790 return NULL; 02791 }
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 4822 of file app_meetme.c.
References load_config_meetme(), and sla_load_config().
04823 { 04824 int res = 0; 04825 04826 load_config_meetme(); 04827 if (!reload) 04828 res = sla_load_config(); 04829 04830 return res; 04831 }
static void load_config_meetme | ( | void | ) | [static] |
Definition at line 3106 of file app_meetme.c.
References ast_config_destroy(), ast_config_load(), ast_log(), ast_variable_retrieve(), audio_buffers, CONFIG_FILE_NAME, DEFAULT_AUDIO_BUFFERS, LOG_NOTICE, and LOG_WARNING.
Referenced by load_config().
03107 { 03108 struct ast_config *cfg; 03109 const char *val; 03110 03111 audio_buffers = DEFAULT_AUDIO_BUFFERS; 03112 03113 if (!(cfg = ast_config_load(CONFIG_FILE_NAME))) 03114 return; 03115 03116 if ((val = ast_variable_retrieve(cfg, "general", "audiobuffers"))) { 03117 if ((sscanf(val, "%d", &audio_buffers) != 1)) { 03118 ast_log(LOG_WARNING, "audiobuffers setting must be a number, not '%s'\n", val); 03119 audio_buffers = DEFAULT_AUDIO_BUFFERS; 03120 } else if ((audio_buffers < ZT_DEFAULT_NUM_BUFS) || (audio_buffers > ZT_MAX_NUM_BUFS)) { 03121 ast_log(LOG_WARNING, "audiobuffers setting must be between %d and %d\n", 03122 ZT_DEFAULT_NUM_BUFS, ZT_MAX_NUM_BUFS); 03123 audio_buffers = DEFAULT_AUDIO_BUFFERS; 03124 } 03125 if (audio_buffers != DEFAULT_AUDIO_BUFFERS) 03126 ast_log(LOG_NOTICE, "Audio buffers per channel set to %d\n", audio_buffers); 03127 } 03128 03129 ast_config_destroy(cfg); 03130 }
static int load_module | ( | void | ) | [static] |
Definition at line 4856 of file app_meetme.c.
References action_meetmemute(), action_meetmeunmute(), admin_exec(), ARRAY_LEN, ast_cli_register_multiple(), ast_devstate_prov_add(), ast_manager_register, ast_register_application(), cli_meetme, conf_exec(), count_exec(), load_config(), meetmestate(), sla_state(), sla_station_exec(), and sla_trunk_exec().
04857 { 04858 int res = 0; 04859 04860 res |= load_config(0); 04861 04862 ast_cli_register_multiple(cli_meetme, ARRAY_LEN(cli_meetme)); 04863 res |= ast_manager_register("MeetmeMute", EVENT_FLAG_CALL, 04864 action_meetmemute, "Mute a Meetme user"); 04865 res |= ast_manager_register("MeetmeUnmute", EVENT_FLAG_CALL, 04866 action_meetmeunmute, "Unmute a Meetme user"); 04867 res |= ast_register_application(app3, admin_exec, synopsis3, descrip3); 04868 res |= ast_register_application(app2, count_exec, synopsis2, descrip2); 04869 res |= ast_register_application(app, conf_exec, synopsis, descrip); 04870 res |= ast_register_application(slastation_app, sla_station_exec, 04871 slastation_synopsis, slastation_desc); 04872 res |= ast_register_application(slatrunk_app, sla_trunk_exec, 04873 slatrunk_synopsis, slatrunk_desc); 04874 04875 res |= ast_devstate_prov_add("Meetme", meetmestate); 04876 res |= ast_devstate_prov_add("SLA", sla_state); 04877 04878 return res; 04879 }
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 2948 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, s, and ast_conf_user::user_no.
Referenced by action_meetmemute(), and action_meetmeunmute().
02949 { 02950 struct ast_conference *conf; 02951 struct ast_conf_user *user; 02952 const char *confid = astman_get_header(m, "Meetme"); 02953 char *userid = ast_strdupa(astman_get_header(m, "Usernum")); 02954 int userno; 02955 02956 if (ast_strlen_zero(confid)) { 02957 astman_send_error(s, m, "Meetme conference not specified"); 02958 return 0; 02959 } 02960 02961 if (ast_strlen_zero(userid)) { 02962 astman_send_error(s, m, "Meetme user number not specified"); 02963 return 0; 02964 } 02965 02966 userno = strtoul(userid, &userid, 10); 02967 02968 if (*userid) { 02969 astman_send_error(s, m, "Invalid user number"); 02970 return 0; 02971 } 02972 02973 /* Look in the conference list */ 02974 AST_LIST_LOCK(&confs); 02975 AST_LIST_TRAVERSE(&confs, conf, list) { 02976 if (!strcmp(confid, conf->confno)) 02977 break; 02978 } 02979 02980 if (!conf) { 02981 AST_LIST_UNLOCK(&confs); 02982 astman_send_error(s, m, "Meetme conference does not exist"); 02983 return 0; 02984 } 02985 02986 AST_LIST_TRAVERSE(&conf->userlist, user, list) 02987 if (user->user_no == userno) 02988 break; 02989 02990 if (!user) { 02991 AST_LIST_UNLOCK(&confs); 02992 astman_send_error(s, m, "User number not found"); 02993 return 0; 02994 } 02995 02996 if (mute) 02997 user->adminflags |= ADMINFLAG_MUTED; /* request user muting */ 02998 else 02999 user->adminflags &= ~(ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED); /* request user unmuting */ 03000 03001 AST_LIST_UNLOCK(&confs); 03002 03003 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); 03004 03005 astman_send_ack(s, m, mute ? "User muted" : "User unmuted"); 03006 return 0; 03007 }
static int meetmestate | ( | const char * | data | ) | [static] |
Callback for devicestate providers.
Definition at line 3084 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().
03085 { 03086 struct ast_conference *conf; 03087 03088 /* Find conference */ 03089 AST_LIST_LOCK(&confs); 03090 AST_LIST_TRAVERSE(&confs, conf, list) { 03091 if (!strcmp(data, conf->confno)) 03092 break; 03093 } 03094 AST_LIST_UNLOCK(&confs); 03095 if (!conf) 03096 return AST_DEVICE_INVALID; 03097 03098 03099 /* SKREP to fill */ 03100 if (!conf->users) 03101 return AST_DEVICE_NOT_INUSE; 03102 03103 return AST_DEVICE_INUSE; 03104 }
static struct sla_ringing_trunk* queue_ringing_trunk | ( | struct sla_trunk * | trunk | ) | [static] |
Definition at line 4311 of file app_meetme.c.
References ALL_TRUNK_REFS, ast_calloc, AST_LIST_INSERT_HEAD, ast_mutex_lock(), ast_mutex_unlock(), 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().
04312 { 04313 struct sla_ringing_trunk *ringing_trunk; 04314 04315 if (!(ringing_trunk = ast_calloc(1, sizeof(*ringing_trunk)))) 04316 return NULL; 04317 04318 ringing_trunk->trunk = trunk; 04319 ringing_trunk->ring_begin = ast_tvnow(); 04320 04321 sla_change_trunk_state(trunk, SLA_TRUNK_STATE_RINGING, ALL_TRUNK_REFS, NULL); 04322 04323 ast_mutex_lock(&sla.lock); 04324 AST_LIST_INSERT_HEAD(&sla.ringing_trunks, ringing_trunk, entry); 04325 ast_mutex_unlock(&sla.lock); 04326 04327 sla_queue_event(SLA_EVENT_RINGING_TRUNK); 04328 04329 return ringing_trunk; 04330 }
static void * recordthread | ( | void * | args | ) | [static] |
Definition at line 3019 of file app_meetme.c.
References AST_FRAME_BITS, AST_FRAME_VOICE, ast_frdup(), ast_frfree, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_mutex_lock(), ast_mutex_unlock(), ast_read(), ast_stopstream(), ast_waitfor(), ast_writefile(), ast_writestream(), f, ast_frame::flags, ast_conference::lchan, ast_conference::listenlock, MEETME_RECORD_ACTIVE, ast_conference::origframe, ast_conference::recordingfilename, ast_conference::recordingformat, s, and ast_conference::transframe.
03020 { 03021 struct ast_conference *cnf = args; 03022 struct ast_frame *f=NULL; 03023 int flags; 03024 struct ast_filestream *s=NULL; 03025 int res=0; 03026 int x; 03027 const char *oldrecordingfilename = NULL; 03028 03029 if (!cnf || !cnf->lchan) { 03030 pthread_exit(0); 03031 } 03032 03033 ast_stopstream(cnf->lchan); 03034 flags = O_CREAT|O_TRUNC|O_WRONLY; 03035 03036 03037 cnf->recording = MEETME_RECORD_ACTIVE; 03038 while (ast_waitfor(cnf->lchan, -1) > -1) { 03039 if (cnf->recording == MEETME_RECORD_TERMINATE) { 03040 AST_LIST_LOCK(&confs); 03041 AST_LIST_UNLOCK(&confs); 03042 break; 03043 } 03044 if (!s && cnf->recordingfilename && (cnf->recordingfilename != oldrecordingfilename)) { 03045 s = ast_writefile(cnf->recordingfilename, cnf->recordingformat, NULL, flags, 0, 0644); 03046 oldrecordingfilename = cnf->recordingfilename; 03047 } 03048 03049 f = ast_read(cnf->lchan); 03050 if (!f) { 03051 res = -1; 03052 break; 03053 } 03054 if (f->frametype == AST_FRAME_VOICE) { 03055 ast_mutex_lock(&cnf->listenlock); 03056 for (x=0;x<AST_FRAME_BITS;x++) { 03057 /* Free any translations that have occured */ 03058 if (cnf->transframe[x]) { 03059 ast_frfree(cnf->transframe[x]); 03060 cnf->transframe[x] = NULL; 03061 } 03062 } 03063 if (cnf->origframe) 03064 ast_frfree(cnf->origframe); 03065 cnf->origframe = ast_frdup(f); 03066 ast_mutex_unlock(&cnf->listenlock); 03067 if (s) 03068 res = ast_writestream(s, f); 03069 if (res) { 03070 ast_frfree(f); 03071 break; 03072 } 03073 } 03074 ast_frfree(f); 03075 } 03076 cnf->recording = MEETME_RECORD_OFF; 03077 if (s) 03078 ast_closestream(s); 03079 03080 pthread_exit(0); 03081 }
static int reload | ( | void | ) | [static] |
Definition at line 4881 of file app_meetme.c.
References load_config().
04882 { 04883 return load_config(1); 04884 }
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().
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 3265 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_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().
03266 { 03267 struct sla_station *station; 03268 struct sla_trunk_ref *trunk_ref; 03269 char conf_name[MAX_CONFNUM]; 03270 struct ast_flags conf_flags = { 0 }; 03271 struct ast_conference *conf; 03272 03273 { 03274 struct run_station_args *args = data; 03275 station = args->station; 03276 trunk_ref = args->trunk_ref; 03277 ast_mutex_lock(args->cond_lock); 03278 ast_cond_signal(args->cond); 03279 ast_mutex_unlock(args->cond_lock); 03280 /* args is no longer valid here. */ 03281 } 03282 03283 ast_atomic_fetchadd_int((int *) &trunk_ref->trunk->active_stations, 1); 03284 snprintf(conf_name, sizeof(conf_name), "SLA_%s", trunk_ref->trunk->name); 03285 ast_set_flag(&conf_flags, 03286 CONFFLAG_QUIET | CONFFLAG_MARKEDEXIT | CONFFLAG_PASS_DTMF | CONFFLAG_SLA_STATION); 03287 ast_answer(trunk_ref->chan); 03288 conf = build_conf(conf_name, "", "", 0, 0, 1); 03289 if (conf) { 03290 conf_run(trunk_ref->chan, conf, conf_flags.flags, NULL); 03291 dispose_conf(conf); 03292 conf = NULL; 03293 } 03294 trunk_ref->chan = NULL; 03295 if (ast_atomic_dec_and_test((int *) &trunk_ref->trunk->active_stations) && 03296 trunk_ref->state != SLA_TRUNK_STATE_ONHOLD_BYME) { 03297 strncat(conf_name, "|K", sizeof(conf_name) - strlen(conf_name) - 1); 03298 admin_exec(NULL, conf_name); 03299 trunk_ref->trunk->hold_stations = 0; 03300 sla_change_trunk_state(trunk_ref->trunk, SLA_TRUNK_STATE_IDLE, ALL_TRUNK_REFS, NULL); 03301 } 03302 03303 ast_dial_join(station->dial); 03304 ast_dial_destroy(station->dial); 03305 station->dial = NULL; 03306 03307 return NULL; 03308 }
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 4614 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_WARNING, name, sla_create_station_ref(), SLA_TRUNK_STATE_IDLE, strsep(), and var.
Referenced by sla_build_station().
04615 { 04616 struct sla_trunk *trunk; 04617 struct sla_trunk_ref *trunk_ref; 04618 struct sla_station_ref *station_ref; 04619 char *trunk_name, *options, *cur; 04620 04621 options = ast_strdupa(var->value); 04622 trunk_name = strsep(&options, ","); 04623 04624 AST_RWLIST_RDLOCK(&sla_trunks); 04625 AST_RWLIST_TRAVERSE(&sla_trunks, trunk, entry) { 04626 if (!strcasecmp(trunk->name, trunk_name)) 04627 break; 04628 } 04629 04630 AST_RWLIST_UNLOCK(&sla_trunks); 04631 if (!trunk) { 04632 ast_log(LOG_ERROR, "Trunk '%s' not found!\n", var->value); 04633 return; 04634 } 04635 if (!(trunk_ref = create_trunk_ref(trunk))) 04636 return; 04637 trunk_ref->state = SLA_TRUNK_STATE_IDLE; 04638 04639 while ((cur = strsep(&options, ","))) { 04640 char *name, *value = cur; 04641 name = strsep(&value, "="); 04642 if (!strcasecmp(name, "ringtimeout")) { 04643 if (sscanf(value, "%u", &trunk_ref->ring_timeout) != 1) { 04644 ast_log(LOG_WARNING, "Invalid ringtimeout value '%s' for " 04645 "trunk '%s' on station '%s'\n", value, trunk->name, station->name); 04646 trunk_ref->ring_timeout = 0; 04647 } 04648 } else if (!strcasecmp(name, "ringdelay")) { 04649 if (sscanf(value, "%u", &trunk_ref->ring_delay) != 1) { 04650 ast_log(LOG_WARNING, "Invalid ringdelay value '%s' for " 04651 "trunk '%s' on station '%s'\n", value, trunk->name, station->name); 04652 trunk_ref->ring_delay = 0; 04653 } 04654 } else { 04655 ast_log(LOG_WARNING, "Invalid option '%s' for " 04656 "trunk '%s' on station '%s'\n", name, trunk->name, station->name); 04657 } 04658 } 04659 04660 if (!(station_ref = sla_create_station_ref(station))) { 04661 free(trunk_ref); 04662 return; 04663 } 04664 ast_atomic_fetchadd_int((int *) &trunk->num_stations, 1); 04665 AST_RWLIST_WRLOCK(&sla_trunks); 04666 AST_LIST_INSERT_TAIL(&trunk->stations, station_ref, entry); 04667 AST_RWLIST_UNLOCK(&sla_trunks); 04668 AST_LIST_INSERT_TAIL(&station->trunks, trunk_ref, entry); 04669 }
static int sla_build_station | ( | struct ast_config * | cfg, | |
const char * | cat | |||
) | [static] |
Definition at line 4671 of file app_meetme.c.
References ast_calloc, ast_log(), ast_string_field_init, ast_string_field_set, ast_variable_browse(), ast_variable_retrieve(), free, LOG_WARNING, name, sla_add_trunk_to_station(), and var.
Referenced by sla_load_config().
04672 { 04673 struct sla_station *station; 04674 struct ast_variable *var; 04675 const char *dev; 04676 04677 if (!(dev = ast_variable_retrieve(cfg, cat, "device"))) { 04678 ast_log(LOG_ERROR, "SLA Station '%s' defined with no device!\n", cat); 04679 return -1; 04680 } 04681 04682 if (!(station = ast_calloc(1, sizeof(*station)))) 04683 return -1; 04684 if (ast_string_field_init(station, 32)) { 04685 free(station); 04686 return -1; 04687 } 04688 04689 ast_string_field_set(station, name, cat); 04690 ast_string_field_set(station, device, dev); 04691 04692 for (var = ast_variable_browse(cfg, cat); var; var = var->next) { 04693 if (!strcasecmp(var->name, "trunk")) 04694 sla_add_trunk_to_station(station, var); 04695 else if (!strcasecmp(var->name, "autocontext")) 04696 ast_string_field_set(station, autocontext, var->value); 04697 else if (!strcasecmp(var->name, "ringtimeout")) { 04698 if (sscanf(var->value, "%u", &station->ring_timeout) != 1) { 04699 ast_log(LOG_WARNING, "Invalid ringtimeout '%s' specified for station '%s'\n", 04700 var->value, station->name); 04701 station->ring_timeout = 0; 04702 } 04703 } else if (!strcasecmp(var->name, "ringdelay")) { 04704 if (sscanf(var->value, "%u", &station->ring_delay) != 1) { 04705 ast_log(LOG_WARNING, "Invalid ringdelay '%s' specified for station '%s'\n", 04706 var->value, station->name); 04707 station->ring_delay = 0; 04708 } 04709 } else if (!strcasecmp(var->name, "hold")) { 04710 if (!strcasecmp(var->value, "private")) 04711 station->hold_access = SLA_HOLD_PRIVATE; 04712 else if (!strcasecmp(var->value, "open")) 04713 station->hold_access = SLA_HOLD_OPEN; 04714 else { 04715 ast_log(LOG_WARNING, "Invalid value '%s' for hold on station %s\n", 04716 var->value, station->name); 04717 } 04718 04719 } else if (strcasecmp(var->name, "type") && strcasecmp(var->name, "device")) { 04720 ast_log(LOG_ERROR, "Invalid option '%s' specified at line %d of %s!\n", 04721 var->name, var->lineno, SLA_CONFIG_FILE); 04722 } 04723 } 04724 04725 if (!ast_strlen_zero(station->autocontext)) { 04726 struct ast_context *context; 04727 struct sla_trunk_ref *trunk_ref; 04728 context = ast_context_find_or_create(NULL, station->autocontext, sla_registrar); 04729 if (!context) { 04730 ast_log(LOG_ERROR, "Failed to automatically find or create " 04731 "context '%s' for SLA!\n", station->autocontext); 04732 destroy_station(station); 04733 return -1; 04734 } 04735 /* The extension for when the handset goes off-hook. 04736 * exten => station1,1,SLAStation(station1) */ 04737 if (ast_add_extension2(context, 0 /* don't replace */, station->name, 1, 04738 NULL, NULL, slastation_app, ast_strdup(station->name), ast_free, sla_registrar)) { 04739 ast_log(LOG_ERROR, "Failed to automatically create extension " 04740 "for trunk '%s'!\n", station->name); 04741 destroy_station(station); 04742 return -1; 04743 } 04744 AST_RWLIST_RDLOCK(&sla_trunks); 04745 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) { 04746 char exten[AST_MAX_EXTENSION]; 04747 char hint[AST_MAX_APP]; 04748 snprintf(exten, sizeof(exten), "%s_%s", station->name, trunk_ref->trunk->name); 04749 snprintf(hint, sizeof(hint), "SLA:%s", exten); 04750 /* Extension for this line button 04751 * exten => station1_line1,1,SLAStation(station1_line1) */ 04752 if (ast_add_extension2(context, 0 /* don't replace */, exten, 1, 04753 NULL, NULL, slastation_app, ast_strdup(exten), ast_free, sla_registrar)) { 04754 ast_log(LOG_ERROR, "Failed to automatically create extension " 04755 "for trunk '%s'!\n", station->name); 04756 destroy_station(station); 04757 return -1; 04758 } 04759 /* Hint for this line button 04760 * exten => station1_line1,hint,SLA:station1_line1 */ 04761 if (ast_add_extension2(context, 0 /* don't replace */, exten, PRIORITY_HINT, 04762 NULL, NULL, hint, NULL, NULL, sla_registrar)) { 04763 ast_log(LOG_ERROR, "Failed to automatically create hint " 04764 "for trunk '%s'!\n", station->name); 04765 destroy_station(station); 04766 return -1; 04767 } 04768 } 04769 AST_RWLIST_UNLOCK(&sla_trunks); 04770 } 04771 04772 AST_RWLIST_WRLOCK(&sla_stations); 04773 AST_RWLIST_INSERT_TAIL(&sla_stations, station, entry); 04774 AST_RWLIST_UNLOCK(&sla_stations); 04775 04776 return 0; 04777 }
static int sla_build_trunk | ( | struct ast_config * | cfg, | |
const char * | cat | |||
) | [static] |
Definition at line 4536 of file app_meetme.c.
References ast_calloc, ast_log(), ast_string_field_init, ast_string_field_set, ast_variable_browse(), ast_variable_retrieve(), free, LOG_ERROR, LOG_WARNING, name, sla_check_device(), and var.
Referenced by sla_load_config().
04537 { 04538 struct sla_trunk *trunk; 04539 struct ast_variable *var; 04540 const char *dev; 04541 04542 if (!(dev = ast_variable_retrieve(cfg, cat, "device"))) { 04543 ast_log(LOG_ERROR, "SLA Trunk '%s' defined with no device!\n", cat); 04544 return -1; 04545 } 04546 04547 if (sla_check_device(dev)) { 04548 ast_log(LOG_ERROR, "SLA Trunk '%s' define with invalid device '%s'!\n", 04549 cat, dev); 04550 return -1; 04551 } 04552 04553 if (!(trunk = ast_calloc(1, sizeof(*trunk)))) 04554 return -1; 04555 if (ast_string_field_init(trunk, 32)) { 04556 free(trunk); 04557 return -1; 04558 } 04559 04560 ast_string_field_set(trunk, name, cat); 04561 ast_string_field_set(trunk, device, dev); 04562 04563 for (var = ast_variable_browse(cfg, cat); var; var = var->next) { 04564 if (!strcasecmp(var->name, "autocontext")) 04565 ast_string_field_set(trunk, autocontext, var->value); 04566 else if (!strcasecmp(var->name, "ringtimeout")) { 04567 if (sscanf(var->value, "%u", &trunk->ring_timeout) != 1) { 04568 ast_log(LOG_WARNING, "Invalid ringtimeout '%s' specified for trunk '%s'\n", 04569 var->value, trunk->name); 04570 trunk->ring_timeout = 0; 04571 } 04572 } else if (!strcasecmp(var->name, "barge")) 04573 trunk->barge_disabled = ast_false(var->value); 04574 else if (!strcasecmp(var->name, "hold")) { 04575 if (!strcasecmp(var->value, "private")) 04576 trunk->hold_access = SLA_HOLD_PRIVATE; 04577 else if (!strcasecmp(var->value, "open")) 04578 trunk->hold_access = SLA_HOLD_OPEN; 04579 else { 04580 ast_log(LOG_WARNING, "Invalid value '%s' for hold on trunk %s\n", 04581 var->value, trunk->name); 04582 } 04583 } else if (strcasecmp(var->name, "type") && strcasecmp(var->name, "device")) { 04584 ast_log(LOG_ERROR, "Invalid option '%s' specified at line %d of %s!\n", 04585 var->name, var->lineno, SLA_CONFIG_FILE); 04586 } 04587 } 04588 04589 if (!ast_strlen_zero(trunk->autocontext)) { 04590 struct ast_context *context; 04591 context = ast_context_find_or_create(NULL, trunk->autocontext, sla_registrar); 04592 if (!context) { 04593 ast_log(LOG_ERROR, "Failed to automatically find or create " 04594 "context '%s' for SLA!\n", trunk->autocontext); 04595 destroy_trunk(trunk); 04596 return -1; 04597 } 04598 if (ast_add_extension2(context, 0 /* don't replace */, "s", 1, 04599 NULL, NULL, slatrunk_app, ast_strdup(trunk->name), ast_free, sla_registrar)) { 04600 ast_log(LOG_ERROR, "Failed to automatically create extension " 04601 "for trunk '%s'!\n", trunk->name); 04602 destroy_trunk(trunk); 04603 return -1; 04604 } 04605 } 04606 04607 AST_RWLIST_WRLOCK(&sla_trunks); 04608 AST_RWLIST_INSERT_TAIL(&sla_trunks, trunk, entry); 04609 AST_RWLIST_UNLOCK(&sla_trunks); 04610 04611 return 0; 04612 }
static int sla_calc_station_delays | ( | unsigned int * | timeout | ) | [static] |
Calculate the ring delay for a station.
Definition at line 3882 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().
03883 { 03884 struct sla_station *station; 03885 int res = 0; 03886 03887 AST_LIST_TRAVERSE(&sla_stations, station, entry) { 03888 struct sla_ringing_trunk *ringing_trunk; 03889 int time_left; 03890 03891 /* Ignore stations already ringing */ 03892 if (sla_check_ringing_station(station)) 03893 continue; 03894 03895 /* Ignore stations already on a call */ 03896 if (sla_check_inuse_station(station)) 03897 continue; 03898 03899 /* Ignore stations that don't have one of their trunks ringing */ 03900 if (!(ringing_trunk = sla_choose_ringing_trunk(station, NULL, 0))) 03901 continue; 03902 03903 if ((time_left = sla_check_station_delay(station, ringing_trunk)) == INT_MAX) 03904 continue; 03905 03906 /* If there is no time left, then the station needs to start ringing. 03907 * Return non-zero so that an event will be queued up an event to 03908 * make that happen. */ 03909 if (time_left <= 0) { 03910 res = 1; 03911 continue; 03912 } 03913 03914 if (time_left < *timeout) 03915 *timeout = time_left; 03916 } 03917 03918 return res; 03919 }
static int sla_calc_station_timeouts | ( | unsigned int * | timeout | ) | [static] |
Process station ring timeouts.
Definition at line 3799 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().
03800 { 03801 struct sla_ringing_trunk *ringing_trunk; 03802 struct sla_ringing_station *ringing_station; 03803 int res = 0; 03804 03805 AST_LIST_TRAVERSE_SAFE_BEGIN(&sla.ringing_stations, ringing_station, entry) { 03806 unsigned int ring_timeout = 0; 03807 int time_elapsed, time_left = INT_MAX, final_trunk_time_left = INT_MIN; 03808 struct sla_trunk_ref *trunk_ref; 03809 03810 /* If there are any ring timeouts specified for a specific trunk 03811 * on the station, then use the highest per-trunk ring timeout. 03812 * Otherwise, use the ring timeout set for the entire station. */ 03813 AST_LIST_TRAVERSE(&ringing_station->station->trunks, trunk_ref, entry) { 03814 struct sla_station_ref *station_ref; 03815 int trunk_time_elapsed, trunk_time_left; 03816 03817 AST_LIST_TRAVERSE(&sla.ringing_trunks, ringing_trunk, entry) { 03818 if (ringing_trunk->trunk == trunk_ref->trunk) 03819 break; 03820 } 03821 if (!ringing_trunk) 03822 continue; 03823 03824 /* If there is a trunk that is ringing without a timeout, then the 03825 * only timeout that could matter is a global station ring timeout. */ 03826 if (!trunk_ref->ring_timeout) 03827 break; 03828 03829 /* This trunk on this station is ringing and has a timeout. 03830 * However, make sure this trunk isn't still ringing from a 03831 * previous timeout. If so, don't consider it. */ 03832 AST_LIST_TRAVERSE(&ringing_trunk->timed_out_stations, station_ref, entry) { 03833 if (station_ref->station == ringing_station->station) 03834 break; 03835 } 03836 if (station_ref) 03837 continue; 03838 03839 trunk_time_elapsed = ast_tvdiff_ms(ast_tvnow(), ringing_trunk->ring_begin); 03840 trunk_time_left = (trunk_ref->ring_timeout * 1000) - trunk_time_elapsed; 03841 if (trunk_time_left > final_trunk_time_left) 03842 final_trunk_time_left = trunk_time_left; 03843 } 03844 03845 /* No timeout was found for ringing trunks, and no timeout for the entire station */ 03846 if (final_trunk_time_left == INT_MIN && !ringing_station->station->ring_timeout) 03847 continue; 03848 03849 /* Compute how much time is left for a global station timeout */ 03850 if (ringing_station->station->ring_timeout) { 03851 ring_timeout = ringing_station->station->ring_timeout; 03852 time_elapsed = ast_tvdiff_ms(ast_tvnow(), ringing_station->ring_begin); 03853 time_left = (ring_timeout * 1000) - time_elapsed; 03854 } 03855 03856 /* If the time left based on the per-trunk timeouts is smaller than the 03857 * global station ring timeout, use that. */ 03858 if (final_trunk_time_left > INT_MIN && final_trunk_time_left < time_left) 03859 time_left = final_trunk_time_left; 03860 03861 /* If there is no time left, the station needs to stop ringing */ 03862 if (time_left <= 0) { 03863 AST_LIST_REMOVE_CURRENT(&sla.ringing_stations, entry); 03864 sla_stop_ringing_station(ringing_station, SLA_STATION_HANGUP_TIMEOUT); 03865 res = 1; 03866 continue; 03867 } 03868 03869 /* There is still some time left for this station to ring, so save that 03870 * timeout if it is the first event scheduled to occur */ 03871 if (time_left < *timeout) 03872 *timeout = time_left; 03873 } 03874 AST_LIST_TRAVERSE_SAFE_END 03875 03876 return res; 03877 }
static int sla_calc_trunk_timeouts | ( | unsigned int * | timeout | ) | [static] |
Process trunk ring timeouts.
Definition at line 3769 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().
03770 { 03771 struct sla_ringing_trunk *ringing_trunk; 03772 int res = 0; 03773 03774 AST_LIST_TRAVERSE_SAFE_BEGIN(&sla.ringing_trunks, ringing_trunk, entry) { 03775 int time_left, time_elapsed; 03776 if (!ringing_trunk->trunk->ring_timeout) 03777 continue; 03778 time_elapsed = ast_tvdiff_ms(ast_tvnow(), ringing_trunk->ring_begin); 03779 time_left = (ringing_trunk->trunk->ring_timeout * 1000) - time_elapsed; 03780 if (time_left <= 0) { 03781 pbx_builtin_setvar_helper(ringing_trunk->trunk->chan, "SLATRUNK_STATUS", "RINGTIMEOUT"); 03782 AST_LIST_REMOVE_CURRENT(&sla.ringing_trunks, entry); 03783 sla_stop_ringing_trunk(ringing_trunk); 03784 res = 1; 03785 continue; 03786 } 03787 if (time_left < *timeout) 03788 *timeout = time_left; 03789 } 03790 AST_LIST_TRAVERSE_SAFE_END 03791 03792 return res; 03793 }
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 3240 of file app_meetme.c.
References ast_device_state_changed(), and AST_LIST_TRAVERSE.
Referenced by queue_ringing_trunk(), run_station(), sla_handle_dial_state_event(), sla_handle_hold_event(), sla_station_exec(), sla_stop_ringing_trunk(), and sla_trunk_exec().
03242 { 03243 struct sla_station *station; 03244 struct sla_trunk_ref *trunk_ref; 03245 03246 AST_LIST_TRAVERSE(&sla_stations, station, entry) { 03247 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) { 03248 if (trunk_ref->trunk != trunk || (inactive_only ? trunk_ref->chan : 0) 03249 || trunk_ref == exclude) 03250 continue; 03251 trunk_ref->state = state; 03252 ast_device_state_changed("SLA:%s_%s", station->name, trunk->name); 03253 break; 03254 } 03255 } 03256 }
static int sla_check_device | ( | const char * | device | ) | [static] |
Definition at line 4523 of file app_meetme.c.
References ast_strdupa, ast_strlen_zero(), and strsep().
Referenced by sla_build_trunk().
04524 { 04525 char *tech, *tech_data; 04526 04527 tech_data = ast_strdupa(device); 04528 tech = strsep(&tech_data, "/"); 04529 04530 if (ast_strlen_zero(tech) || ast_strlen_zero(tech_data)) 04531 return -1; 04532 04533 return 0; 04534 }
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 3517 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().
03518 { 03519 struct sla_failed_station *failed_station; 03520 int res = 0; 03521 03522 AST_LIST_TRAVERSE_SAFE_BEGIN(&sla.failed_stations, failed_station, entry) { 03523 if (station != failed_station->station) 03524 continue; 03525 if (ast_tvdiff_ms(ast_tvnow(), failed_station->last_try) > 1000) { 03526 AST_LIST_REMOVE_CURRENT(&sla.failed_stations, entry); 03527 free(failed_station); 03528 break; 03529 } 03530 res = 1; 03531 } 03532 AST_LIST_TRAVERSE_SAFE_END 03533 03534 return res; 03535 }
static int sla_check_inuse_station | ( | const struct sla_station * | station | ) | [static] |
Check to see if a station is in use.
Definition at line 3603 of file app_meetme.c.
References AST_LIST_TRAVERSE.
Referenced by sla_calc_station_delays(), and sla_ring_stations().
03604 { 03605 struct sla_trunk_ref *trunk_ref; 03606 03607 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) { 03608 if (trunk_ref->chan) 03609 return 1; 03610 } 03611 03612 return 0; 03613 }
static int sla_check_ringing_station | ( | const struct sla_station * | station | ) | [static] |
Check to see if this station is already ringing.
Definition at line 3502 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().
03503 { 03504 struct sla_ringing_station *ringing_station; 03505 03506 AST_LIST_TRAVERSE(&sla.ringing_stations, ringing_station, entry) { 03507 if (station == ringing_station->station) 03508 return 1; 03509 } 03510 03511 return 0; 03512 }
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 3633 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().
03635 { 03636 struct sla_trunk_ref *trunk_ref; 03637 unsigned int delay = UINT_MAX; 03638 int time_left, time_elapsed; 03639 03640 if (!ringing_trunk) 03641 ringing_trunk = sla_choose_ringing_trunk(station, &trunk_ref, 0); 03642 else 03643 trunk_ref = sla_find_trunk_ref(station, ringing_trunk->trunk); 03644 03645 if (!ringing_trunk || !trunk_ref) 03646 return delay; 03647 03648 /* If this station has a ring delay specific to the highest priority 03649 * ringing trunk, use that. Otherwise, use the ring delay specified 03650 * globally for the station. */ 03651 delay = trunk_ref->ring_delay; 03652 if (!delay) 03653 delay = station->ring_delay; 03654 if (!delay) 03655 return INT_MAX; 03656 03657 time_elapsed = ast_tvdiff_ms(ast_tvnow(), ringing_trunk->ring_begin); 03658 time_left = (delay * 1000) - time_elapsed; 03659 03660 return time_left; 03661 }
static int sla_check_station_hold_access | ( | const struct sla_trunk * | trunk, | |
const struct sla_station * | station | |||
) | [static] |
Definition at line 3162 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().
03164 { 03165 struct sla_station_ref *station_ref; 03166 struct sla_trunk_ref *trunk_ref; 03167 03168 /* For each station that has this call on hold, check for private hold. */ 03169 AST_LIST_TRAVERSE(&trunk->stations, station_ref, entry) { 03170 AST_LIST_TRAVERSE(&station_ref->station->trunks, trunk_ref, entry) { 03171 if (trunk_ref->trunk != trunk || station_ref->station == station) 03172 continue; 03173 if (trunk_ref->state == SLA_TRUNK_STATE_ONHOLD_BYME && 03174 station_ref->station->hold_access == SLA_HOLD_PRIVATE) 03175 return 1; 03176 return 0; 03177 } 03178 } 03179 03180 return 0; 03181 }
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 3368 of file app_meetme.c.
References AST_LIST_TRAVERSE.
Referenced by sla_choose_ringing_trunk(), and sla_ring_stations().
03370 { 03371 struct sla_station_ref *timed_out_station; 03372 03373 AST_LIST_TRAVERSE(&ringing_trunk->timed_out_stations, timed_out_station, entry) { 03374 if (station == timed_out_station->station) 03375 return 1; 03376 } 03377 03378 return 0; 03379 }
static struct sla_trunk_ref* sla_choose_idle_trunk | ( | const struct sla_station * | station | ) | [static] |
For a given station, choose the highest priority idle trunk.
Definition at line 4133 of file app_meetme.c.
References AST_LIST_TRAVERSE, and SLA_TRUNK_STATE_IDLE.
Referenced by sla_station_exec().
04134 { 04135 struct sla_trunk_ref *trunk_ref = NULL; 04136 04137 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) { 04138 if (trunk_ref->state == SLA_TRUNK_STATE_IDLE) 04139 break; 04140 } 04141 04142 return trunk_ref; 04143 }
static struct sla_ringing_trunk* sla_choose_ringing_trunk | ( | struct sla_station * | station, | |
struct sla_trunk_ref ** | trunk_ref, | |||
int | remove | |||
) | [static] |
Choose the highest priority ringing trunk for a station.
station | the station | |
remove | remove the ringing trunk once selected | |
trunk_ref | a place to store the pointer to this stations reference to the selected trunk |
Definition at line 3389 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().
03391 { 03392 struct sla_trunk_ref *s_trunk_ref; 03393 struct sla_ringing_trunk *ringing_trunk = NULL; 03394 03395 AST_LIST_TRAVERSE(&station->trunks, s_trunk_ref, entry) { 03396 AST_LIST_TRAVERSE_SAFE_BEGIN(&sla.ringing_trunks, ringing_trunk, entry) { 03397 /* Make sure this is the trunk we're looking for */ 03398 if (s_trunk_ref->trunk != ringing_trunk->trunk) 03399 continue; 03400 03401 /* This trunk on the station is ringing. But, make sure this station 03402 * didn't already time out while this trunk was ringing. */ 03403 if (sla_check_timed_out_station(ringing_trunk, station)) 03404 continue; 03405 03406 if (remove) 03407 AST_LIST_REMOVE_CURRENT(&sla.ringing_trunks, entry); 03408 03409 if (trunk_ref) 03410 *trunk_ref = s_trunk_ref; 03411 03412 break; 03413 } 03414 AST_LIST_TRAVERSE_SAFE_END 03415 03416 if (ringing_trunk) 03417 break; 03418 } 03419 03420 return ringing_trunk; 03421 }
static struct sla_ringing_station* sla_create_ringing_station | ( | struct sla_station * | station | ) | [static] |
Definition at line 3227 of file app_meetme.c.
References ast_calloc, and sla_ringing_station::station.
Referenced by sla_ring_station().
03228 { 03229 struct sla_ringing_station *ringing_station; 03230 03231 if (!(ringing_station = ast_calloc(1, sizeof(*ringing_station)))) 03232 return NULL; 03233 03234 ringing_station->station = station; 03235 ringing_station->ring_begin = ast_tvnow(); 03236 03237 return ringing_station; 03238 }
static struct sla_station_ref* sla_create_station_ref | ( | struct sla_station * | station | ) | [static] |
Definition at line 3215 of file app_meetme.c.
References ast_calloc.
Referenced by sla_add_trunk_to_station(), and sla_stop_ringing_station().
03216 { 03217 struct sla_station_ref *station_ref; 03218 03219 if (!(station_ref = ast_calloc(1, sizeof(*station_ref)))) 03220 return NULL; 03221 03222 station_ref->station = station; 03223 03224 return station_ref; 03225 }
static void sla_destroy | ( | void | ) | [static] |
Definition at line 4493 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().
04494 { 04495 struct sla_trunk *trunk; 04496 struct sla_station *station; 04497 04498 AST_RWLIST_WRLOCK(&sla_trunks); 04499 while ((trunk = AST_RWLIST_REMOVE_HEAD(&sla_trunks, entry))) 04500 destroy_trunk(trunk); 04501 AST_RWLIST_UNLOCK(&sla_trunks); 04502 04503 AST_RWLIST_WRLOCK(&sla_stations); 04504 while ((station = AST_RWLIST_REMOVE_HEAD(&sla_stations, entry))) 04505 destroy_station(station); 04506 AST_RWLIST_UNLOCK(&sla_stations); 04507 04508 if (sla.thread != AST_PTHREADT_NULL) { 04509 ast_mutex_lock(&sla.lock); 04510 sla.stop = 1; 04511 ast_cond_signal(&sla.cond); 04512 ast_mutex_unlock(&sla.lock); 04513 pthread_join(sla.thread, NULL); 04514 } 04515 04516 /* Drop any created contexts from the dialplan */ 04517 ast_context_destroy(NULL, sla_registrar); 04518 04519 ast_mutex_destroy(&sla.lock); 04520 ast_cond_destroy(&sla.cond); 04521 }
static void sla_dial_state_callback | ( | struct ast_dial * | dial | ) | [static] |
Definition at line 3360 of file app_meetme.c.
References SLA_EVENT_DIAL_STATE, and sla_queue_event().
Referenced by sla_ring_station().
03361 { 03362 sla_queue_event(SLA_EVENT_DIAL_STATE); 03363 }
static struct sla_station* sla_find_station | ( | const char * | name | ) | [static] |
Find an SLA station by name.
Definition at line 3150 of file app_meetme.c.
References AST_RWLIST_TRAVERSE.
Referenced by sla_station_exec().
03151 { 03152 struct sla_station *station = NULL; 03153 03154 AST_RWLIST_TRAVERSE(&sla_stations, station, entry) { 03155 if (!strcasecmp(station->name, name)) 03156 break; 03157 } 03158 03159 return station; 03160 }
static struct sla_trunk* sla_find_trunk | ( | const char * | name | ) | [static] |
Find an SLA trunk by name.
Definition at line 3135 of file app_meetme.c.
References AST_RWLIST_TRAVERSE.
Referenced by sla_trunk_exec().
03136 { 03137 struct sla_trunk *trunk = NULL; 03138 03139 AST_RWLIST_TRAVERSE(&sla_trunks, trunk, entry) { 03140 if (!strcasecmp(trunk->name, name)) 03141 break; 03142 } 03143 03144 return trunk; 03145 }
static struct sla_trunk_ref* sla_find_trunk_ref | ( | const struct sla_station * | station, | |
const struct sla_trunk * | trunk | |||
) | [static] |
Definition at line 3615 of file app_meetme.c.
References AST_LIST_TRAVERSE.
Referenced by sla_check_station_delay().
03617 { 03618 struct sla_trunk_ref *trunk_ref = NULL; 03619 03620 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) { 03621 if (trunk_ref->trunk == trunk) 03622 break; 03623 } 03624 03625 return trunk_ref; 03626 }
static struct sla_trunk_ref* sla_find_trunk_ref_byname | ( | const struct sla_station * | station, | |
const char * | name | |||
) | [static] |
Find a trunk reference on a station by name.
station | the station | |
name | the trunk's name |
Definition at line 3190 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().
03192 { 03193 struct sla_trunk_ref *trunk_ref = NULL; 03194 03195 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) { 03196 if (strcasecmp(trunk_ref->trunk->name, name)) 03197 continue; 03198 03199 if ( (trunk_ref->trunk->barge_disabled 03200 && trunk_ref->state == SLA_TRUNK_STATE_UP) || 03201 (trunk_ref->trunk->hold_stations 03202 && trunk_ref->trunk->hold_access == SLA_HOLD_PRIVATE 03203 && trunk_ref->state != SLA_TRUNK_STATE_ONHOLD_BYME) || 03204 sla_check_station_hold_access(trunk_ref->trunk, station) ) 03205 { 03206 trunk_ref = NULL; 03207 } 03208 03209 break; 03210 } 03211 03212 return trunk_ref; 03213 }
static void sla_handle_dial_state_event | ( | void | ) | [static] |
Definition at line 3423 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, 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().
03424 { 03425 struct sla_ringing_station *ringing_station; 03426 03427 AST_LIST_TRAVERSE_SAFE_BEGIN(&sla.ringing_stations, ringing_station, entry) { 03428 struct sla_trunk_ref *s_trunk_ref = NULL; 03429 struct sla_ringing_trunk *ringing_trunk = NULL; 03430 struct run_station_args args; 03431 enum ast_dial_result dial_res; 03432 pthread_attr_t attr; 03433 pthread_t dont_care; 03434 ast_mutex_t cond_lock; 03435 ast_cond_t cond; 03436 03437 switch ((dial_res = ast_dial_state(ringing_station->station->dial))) { 03438 case AST_DIAL_RESULT_HANGUP: 03439 case AST_DIAL_RESULT_INVALID: 03440 case AST_DIAL_RESULT_FAILED: 03441 case AST_DIAL_RESULT_TIMEOUT: 03442 case AST_DIAL_RESULT_UNANSWERED: 03443 AST_LIST_REMOVE_CURRENT(&sla.ringing_stations, entry); 03444 sla_stop_ringing_station(ringing_station, SLA_STATION_HANGUP_NORMAL); 03445 break; 03446 case AST_DIAL_RESULT_ANSWERED: 03447 AST_LIST_REMOVE_CURRENT(&sla.ringing_stations, entry); 03448 /* Find the appropriate trunk to answer. */ 03449 ast_mutex_lock(&sla.lock); 03450 ringing_trunk = sla_choose_ringing_trunk(ringing_station->station, &s_trunk_ref, 1); 03451 ast_mutex_unlock(&sla.lock); 03452 if (!ringing_trunk) { 03453 ast_log(LOG_DEBUG, "Found no ringing trunk for station '%s' to answer!\n", 03454 ringing_station->station->name); 03455 break; 03456 } 03457 /* Track the channel that answered this trunk */ 03458 s_trunk_ref->chan = ast_dial_answered(ringing_station->station->dial); 03459 /* Actually answer the trunk */ 03460 ast_answer(ringing_trunk->trunk->chan); 03461 sla_change_trunk_state(ringing_trunk->trunk, SLA_TRUNK_STATE_UP, ALL_TRUNK_REFS, NULL); 03462 /* Now, start a thread that will connect this station to the trunk. The rest of 03463 * the code here sets up the thread and ensures that it is able to save the arguments 03464 * before they are no longer valid since they are allocated on the stack. */ 03465 args.trunk_ref = s_trunk_ref; 03466 args.station = ringing_station->station; 03467 args.cond = &cond; 03468 args.cond_lock = &cond_lock; 03469 free(ringing_trunk); 03470 free(ringing_station); 03471 ast_mutex_init(&cond_lock); 03472 ast_cond_init(&cond, NULL); 03473 pthread_attr_init(&attr); 03474 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 03475 ast_mutex_lock(&cond_lock); 03476 ast_pthread_create_background(&dont_care, &attr, run_station, &args); 03477 ast_cond_wait(&cond, &cond_lock); 03478 ast_mutex_unlock(&cond_lock); 03479 ast_mutex_destroy(&cond_lock); 03480 ast_cond_destroy(&cond); 03481 pthread_attr_destroy(&attr); 03482 break; 03483 case AST_DIAL_RESULT_TRYING: 03484 case AST_DIAL_RESULT_RINGING: 03485 case AST_DIAL_RESULT_PROGRESS: 03486 case AST_DIAL_RESULT_PROCEEDING: 03487 break; 03488 } 03489 if (dial_res == AST_DIAL_RESULT_ANSWERED) { 03490 /* Queue up reprocessing ringing trunks, and then ringing stations again */ 03491 sla_queue_event(SLA_EVENT_RINGING_TRUNK); 03492 sla_queue_event(SLA_EVENT_DIAL_STATE); 03493 break; 03494 } 03495 } 03496 AST_LIST_TRAVERSE_SAFE_END 03497 }
static void sla_handle_hold_event | ( | struct sla_event * | event | ) | [static] |
Definition at line 3745 of file app_meetme.c.
References AST_CAUSE_NORMAL, AST_CONTROL_HOLD, ast_device_state_changed(), ast_indicate(), ast_softhangup(), event, INACTIVE_TRUNK_REFS, sla_change_trunk_state(), SLA_TRUNK_STATE_ONHOLD, and SLA_TRUNK_STATE_ONHOLD_BYME.
Referenced by sla_thread().
03746 { 03747 ast_atomic_fetchadd_int((int *) &event->trunk_ref->trunk->hold_stations, 1); 03748 event->trunk_ref->state = SLA_TRUNK_STATE_ONHOLD_BYME; 03749 ast_device_state_changed("SLA:%s_%s", 03750 event->station->name, event->trunk_ref->trunk->name); 03751 sla_change_trunk_state(event->trunk_ref->trunk, SLA_TRUNK_STATE_ONHOLD, 03752 INACTIVE_TRUNK_REFS, event->trunk_ref); 03753 03754 if (event->trunk_ref->trunk->active_stations == 1) { 03755 /* The station putting it on hold is the only one on the call, so start 03756 * Music on hold to the trunk. */ 03757 event->trunk_ref->trunk->on_hold = 1; 03758 ast_indicate(event->trunk_ref->trunk->chan, AST_CONTROL_HOLD); 03759 } 03760 03761 ast_softhangup(event->trunk_ref->chan, AST_CAUSE_NORMAL); 03762 event->trunk_ref->chan = NULL; 03763 }
static void sla_handle_ringing_trunk_event | ( | void | ) | [static] |
Definition at line 3735 of file app_meetme.c.
References ast_mutex_lock(), ast_mutex_unlock(), sla, sla_hangup_stations(), and sla_ring_stations().
Referenced by sla_thread().
03736 { 03737 ast_mutex_lock(&sla.lock); 03738 sla_ring_stations(); 03739 ast_mutex_unlock(&sla.lock); 03740 03741 /* Find stations that shouldn't be ringing anymore. */ 03742 sla_hangup_stations(); 03743 }
static void sla_hangup_stations | ( | void | ) | [static] |
Definition at line 3707 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().
03708 { 03709 struct sla_trunk_ref *trunk_ref; 03710 struct sla_ringing_station *ringing_station; 03711 03712 AST_LIST_TRAVERSE_SAFE_BEGIN(&sla.ringing_stations, ringing_station, entry) { 03713 AST_LIST_TRAVERSE(&ringing_station->station->trunks, trunk_ref, entry) { 03714 struct sla_ringing_trunk *ringing_trunk; 03715 ast_mutex_lock(&sla.lock); 03716 AST_LIST_TRAVERSE(&sla.ringing_trunks, ringing_trunk, entry) { 03717 if (trunk_ref->trunk == ringing_trunk->trunk) 03718 break; 03719 } 03720 ast_mutex_unlock(&sla.lock); 03721 if (ringing_trunk) 03722 break; 03723 } 03724 if (!trunk_ref) { 03725 AST_LIST_REMOVE_CURRENT(&sla.ringing_stations, entry); 03726 ast_dial_join(ringing_station->station->dial); 03727 ast_dial_destroy(ringing_station->station->dial); 03728 ringing_station->station->dial = NULL; 03729 free(ringing_station); 03730 } 03731 } 03732 AST_LIST_TRAVERSE_SAFE_END 03733 }
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 4779 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().
04780 { 04781 struct ast_config *cfg; 04782 const char *cat = NULL; 04783 int res = 0; 04784 const char *val; 04785 04786 ast_mutex_init(&sla.lock); 04787 ast_cond_init(&sla.cond, NULL); 04788 04789 if (!(cfg = ast_config_load(SLA_CONFIG_FILE))) 04790 return 0; /* Treat no config as normal */ 04791 04792 if ((val = ast_variable_retrieve(cfg, "general", "attemptcallerid"))) 04793 sla.attempt_callerid = ast_true(val); 04794 04795 while ((cat = ast_category_browse(cfg, cat)) && !res) { 04796 const char *type; 04797 if (!strcasecmp(cat, "general")) 04798 continue; 04799 if (!(type = ast_variable_retrieve(cfg, cat, "type"))) { 04800 ast_log(LOG_WARNING, "Invalid entry in %s defined with no type!\n", 04801 SLA_CONFIG_FILE); 04802 continue; 04803 } 04804 if (!strcasecmp(type, "trunk")) 04805 res = sla_build_trunk(cfg, cat); 04806 else if (!strcasecmp(type, "station")) 04807 res = sla_build_station(cfg, cat); 04808 else { 04809 ast_log(LOG_WARNING, "Entry in %s defined with invalid type '%s'!\n", 04810 SLA_CONFIG_FILE, type); 04811 } 04812 } 04813 04814 ast_config_destroy(cfg); 04815 04816 if (!AST_LIST_EMPTY(&sla_stations) || !AST_LIST_EMPTY(&sla_stations)) 04817 ast_pthread_create(&sla.thread, NULL, sla_thread, NULL); 04818 04819 return res; 04820 }
static int sla_process_timers | ( | struct timespec * | ts | ) | [static] |
Calculate the time until the next known event.
Definition at line 3923 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().
03924 { 03925 unsigned int timeout = UINT_MAX; 03926 struct timeval tv; 03927 unsigned int change_made = 0; 03928 03929 /* Check for ring timeouts on ringing trunks */ 03930 if (sla_calc_trunk_timeouts(&timeout)) 03931 change_made = 1; 03932 03933 /* Check for ring timeouts on ringing stations */ 03934 if (sla_calc_station_timeouts(&timeout)) 03935 change_made = 1; 03936 03937 /* Check for station ring delays */ 03938 if (sla_calc_station_delays(&timeout)) 03939 change_made = 1; 03940 03941 /* queue reprocessing of ringing trunks */ 03942 if (change_made) 03943 sla_queue_event_nolock(SLA_EVENT_RINGING_TRUNK); 03944 03945 /* No timeout */ 03946 if (timeout == UINT_MAX) 03947 return 0; 03948 03949 if (ts) { 03950 tv = ast_tvadd(ast_tvnow(), ast_samp2tv(timeout, 1000)); 03951 ts->tv_sec = tv.tv_sec; 03952 ts->tv_nsec = tv.tv_usec * 1000; 03953 } 03954 03955 return 1; 03956 }
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::chan, 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, sla, sla_event::station, and sla_event::trunk_ref.
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 3540 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, sla_create_ringing_station(), sla_dial_state_callback(), sla_failed_station::station, sla_ringing_station::station, strsep(), and sla_ringing_trunk::trunk.
Referenced by sla_ring_stations().
03541 { 03542 char *tech, *tech_data; 03543 struct ast_dial *dial; 03544 struct sla_ringing_station *ringing_station; 03545 const char *cid_name = NULL, *cid_num = NULL; 03546 enum ast_dial_result res; 03547 03548 if (!(dial = ast_dial_create())) 03549 return -1; 03550 03551 ast_dial_set_state_callback(dial, sla_dial_state_callback); 03552 tech_data = ast_strdupa(station->device); 03553 tech = strsep(&tech_data, "/"); 03554 03555 if (ast_dial_append(dial, tech, tech_data) == -1) { 03556 ast_dial_destroy(dial); 03557 return -1; 03558 } 03559 03560 if (!sla.attempt_callerid && !ast_strlen_zero(ringing_trunk->trunk->chan->cid.cid_name)) { 03561 cid_name = ast_strdupa(ringing_trunk->trunk->chan->cid.cid_name); 03562 free(ringing_trunk->trunk->chan->cid.cid_name); 03563 ringing_trunk->trunk->chan->cid.cid_name = NULL; 03564 } 03565 if (!sla.attempt_callerid && !ast_strlen_zero(ringing_trunk->trunk->chan->cid.cid_num)) { 03566 cid_num = ast_strdupa(ringing_trunk->trunk->chan->cid.cid_num); 03567 free(ringing_trunk->trunk->chan->cid.cid_num); 03568 ringing_trunk->trunk->chan->cid.cid_num = NULL; 03569 } 03570 03571 res = ast_dial_run(dial, ringing_trunk->trunk->chan, 1); 03572 03573 if (cid_name) 03574 ringing_trunk->trunk->chan->cid.cid_name = ast_strdup(cid_name); 03575 if (cid_num) 03576 ringing_trunk->trunk->chan->cid.cid_num = ast_strdup(cid_num); 03577 03578 if (res != AST_DIAL_RESULT_TRYING) { 03579 struct sla_failed_station *failed_station; 03580 ast_dial_destroy(dial); 03581 if (!(failed_station = ast_calloc(1, sizeof(*failed_station)))) 03582 return -1; 03583 failed_station->station = station; 03584 failed_station->last_try = ast_tvnow(); 03585 AST_LIST_INSERT_HEAD(&sla.failed_stations, failed_station, entry); 03586 return -1; 03587 } 03588 if (!(ringing_station = sla_create_ringing_station(station))) { 03589 ast_dial_join(dial); 03590 ast_dial_destroy(dial); 03591 return -1; 03592 } 03593 03594 station->dial = dial; 03595 03596 AST_LIST_INSERT_HEAD(&sla.ringing_stations, ringing_station, entry); 03597 03598 return 0; 03599 }
static void sla_ring_stations | ( | void | ) | [static] |
Ring stations based on current set of ringing trunks.
Definition at line 3666 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().
03667 { 03668 struct sla_station_ref *station_ref; 03669 struct sla_ringing_trunk *ringing_trunk; 03670 03671 /* Make sure that every station that uses at least one of the ringing 03672 * trunks, is ringing. */ 03673 AST_LIST_TRAVERSE(&sla.ringing_trunks, ringing_trunk, entry) { 03674 AST_LIST_TRAVERSE(&ringing_trunk->trunk->stations, station_ref, entry) { 03675 int time_left; 03676 03677 /* Is this station already ringing? */ 03678 if (sla_check_ringing_station(station_ref->station)) 03679 continue; 03680 03681 /* Is this station already in a call? */ 03682 if (sla_check_inuse_station(station_ref->station)) 03683 continue; 03684 03685 /* Did we fail to dial this station earlier? If so, has it been 03686 * a minute since we tried? */ 03687 if (sla_check_failed_station(station_ref->station)) 03688 continue; 03689 03690 /* If this station already timed out while this trunk was ringing, 03691 * do not dial it again for this ringing trunk. */ 03692 if (sla_check_timed_out_station(ringing_trunk, station_ref->station)) 03693 continue; 03694 03695 /* Check for a ring delay in progress */ 03696 time_left = sla_check_station_delay(station_ref->station, ringing_trunk); 03697 if (time_left != INT_MAX && time_left > 0) 03698 continue; 03699 03700 /* It is time to make this station begin to ring. Do it! */ 03701 sla_ring_station(ringing_trunk, station_ref->station); 03702 } 03703 } 03704 /* Now, all of the stations that should be ringing, are ringing. */ 03705 }
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 4403 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().
04404 { 04405 char *buf, *station_name, *trunk_name; 04406 struct sla_station *station; 04407 struct sla_trunk_ref *trunk_ref; 04408 int res = AST_DEVICE_INVALID; 04409 04410 trunk_name = buf = ast_strdupa(data); 04411 station_name = strsep(&trunk_name, "_"); 04412 04413 AST_RWLIST_RDLOCK(&sla_stations); 04414 AST_LIST_TRAVERSE(&sla_stations, station, entry) { 04415 if (strcasecmp(station_name, station->name)) 04416 continue; 04417 AST_RWLIST_RDLOCK(&sla_trunks); 04418 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) { 04419 if (!strcasecmp(trunk_name, trunk_ref->trunk->name)) 04420 break; 04421 } 04422 if (!trunk_ref) { 04423 AST_RWLIST_UNLOCK(&sla_trunks); 04424 break; 04425 } 04426 switch (trunk_ref->state) { 04427 case SLA_TRUNK_STATE_IDLE: 04428 res = AST_DEVICE_NOT_INUSE; 04429 break; 04430 case SLA_TRUNK_STATE_RINGING: 04431 res = AST_DEVICE_RINGING; 04432 break; 04433 case SLA_TRUNK_STATE_UP: 04434 res = AST_DEVICE_INUSE; 04435 break; 04436 case SLA_TRUNK_STATE_ONHOLD: 04437 case SLA_TRUNK_STATE_ONHOLD_BYME: 04438 res = AST_DEVICE_ONHOLD; 04439 break; 04440 } 04441 AST_RWLIST_UNLOCK(&sla_trunks); 04442 } 04443 AST_RWLIST_UNLOCK(&sla_stations); 04444 04445 if (res == AST_DEVICE_INVALID) { 04446 ast_log(LOG_ERROR, "Could not determine state for trunk %s on station %s!\n", 04447 trunk_name, station_name); 04448 } 04449 04450 return res; 04451 }
static int sla_station_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Definition at line 4145 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(), ast_conference::chan, cond, conf_run(), CONFFLAG_MARKEDEXIT, CONFFLAG_PASS_DTMF, 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, dial_trunk_args::station, strsep(), sla_ringing_trunk::trunk, and dial_trunk_args::trunk_ref.
Referenced by load_module().
04146 { 04147 char *station_name, *trunk_name; 04148 struct sla_station *station; 04149 struct sla_trunk_ref *trunk_ref = NULL; 04150 char conf_name[MAX_CONFNUM]; 04151 struct ast_flags conf_flags = { 0 }; 04152 struct ast_conference *conf; 04153 04154 if (ast_strlen_zero(data)) { 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 trunk_name = ast_strdupa(data); 04161 station_name = strsep(&trunk_name, "_"); 04162 04163 if (ast_strlen_zero(station_name)) { 04164 ast_log(LOG_WARNING, "Invalid Arguments to SLAStation!\n"); 04165 pbx_builtin_setvar_helper(chan, "SLASTATION_STATUS", "FAILURE"); 04166 return 0; 04167 } 04168 04169 AST_RWLIST_RDLOCK(&sla_stations); 04170 station = sla_find_station(station_name); 04171 AST_RWLIST_UNLOCK(&sla_stations); 04172 04173 if (!station) { 04174 ast_log(LOG_WARNING, "Station '%s' not found!\n", station_name); 04175 pbx_builtin_setvar_helper(chan, "SLASTATION_STATUS", "FAILURE"); 04176 return 0; 04177 } 04178 04179 AST_RWLIST_RDLOCK(&sla_trunks); 04180 if (!ast_strlen_zero(trunk_name)) { 04181 trunk_ref = sla_find_trunk_ref_byname(station, trunk_name); 04182 } else 04183 trunk_ref = sla_choose_idle_trunk(station); 04184 AST_RWLIST_UNLOCK(&sla_trunks); 04185 04186 if (!trunk_ref) { 04187 if (ast_strlen_zero(trunk_name)) 04188 ast_log(LOG_NOTICE, "No trunks available for call.\n"); 04189 else { 04190 ast_log(LOG_NOTICE, "Can't join existing call on trunk " 04191 "'%s' due to access controls.\n", trunk_name); 04192 } 04193 pbx_builtin_setvar_helper(chan, "SLASTATION_STATUS", "CONGESTION"); 04194 return 0; 04195 } 04196 04197 if (trunk_ref->state == SLA_TRUNK_STATE_ONHOLD_BYME) { 04198 if (ast_atomic_dec_and_test((int *) &trunk_ref->trunk->hold_stations) == 1) 04199 sla_change_trunk_state(trunk_ref->trunk, SLA_TRUNK_STATE_UP, ALL_TRUNK_REFS, NULL); 04200 else { 04201 trunk_ref->state = SLA_TRUNK_STATE_UP; 04202 ast_device_state_changed("SLA:%s_%s", station->name, trunk_ref->trunk->name); 04203 } 04204 } else if (trunk_ref->state == SLA_TRUNK_STATE_RINGING) { 04205 struct sla_ringing_trunk *ringing_trunk; 04206 04207 ast_mutex_lock(&sla.lock); 04208 AST_LIST_TRAVERSE_SAFE_BEGIN(&sla.ringing_trunks, ringing_trunk, entry) { 04209 if (ringing_trunk->trunk == trunk_ref->trunk) { 04210 AST_LIST_REMOVE_CURRENT(&sla.ringing_trunks, entry); 04211 break; 04212 } 04213 } 04214 AST_LIST_TRAVERSE_SAFE_END 04215 ast_mutex_unlock(&sla.lock); 04216 04217 if (ringing_trunk) { 04218 ast_answer(ringing_trunk->trunk->chan); 04219 sla_change_trunk_state(ringing_trunk->trunk, SLA_TRUNK_STATE_UP, ALL_TRUNK_REFS, NULL); 04220 04221 free(ringing_trunk); 04222 04223 /* Queue up reprocessing ringing trunks, and then ringing stations again */ 04224 sla_queue_event(SLA_EVENT_RINGING_TRUNK); 04225 sla_queue_event(SLA_EVENT_DIAL_STATE); 04226 } 04227 } 04228 04229 trunk_ref->chan = chan; 04230 04231 if (!trunk_ref->trunk->chan) { 04232 ast_mutex_t cond_lock; 04233 ast_cond_t cond; 04234 pthread_t dont_care; 04235 pthread_attr_t attr; 04236 struct dial_trunk_args args = { 04237 .trunk_ref = trunk_ref, 04238 .station = station, 04239 .cond_lock = &cond_lock, 04240 .cond = &cond, 04241 }; 04242 sla_change_trunk_state(trunk_ref->trunk, SLA_TRUNK_STATE_UP, ALL_TRUNK_REFS, NULL); 04243 /* Create a thread to dial the trunk and dump it into the conference. 04244 * However, we want to wait until the trunk has been dialed and the 04245 * conference is created before continuing on here. */ 04246 ast_autoservice_start(chan); 04247 ast_mutex_init(&cond_lock); 04248 ast_cond_init(&cond, NULL); 04249 pthread_attr_init(&attr); 04250 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 04251 ast_mutex_lock(&cond_lock); 04252 ast_pthread_create_background(&dont_care, &attr, dial_trunk, &args); 04253 ast_cond_wait(&cond, &cond_lock); 04254 ast_mutex_unlock(&cond_lock); 04255 ast_mutex_destroy(&cond_lock); 04256 ast_cond_destroy(&cond); 04257 pthread_attr_destroy(&attr); 04258 ast_autoservice_stop(chan); 04259 if (!trunk_ref->trunk->chan) { 04260 ast_log(LOG_DEBUG, "Trunk didn't get created. chan: %lx\n", (long) trunk_ref->trunk->chan); 04261 pbx_builtin_setvar_helper(chan, "SLASTATION_STATUS", "CONGESTION"); 04262 sla_change_trunk_state(trunk_ref->trunk, SLA_TRUNK_STATE_IDLE, ALL_TRUNK_REFS, NULL); 04263 trunk_ref->chan = NULL; 04264 return 0; 04265 } 04266 } 04267 04268 if (ast_atomic_fetchadd_int((int *) &trunk_ref->trunk->active_stations, 1) == 0 && 04269 trunk_ref->trunk->on_hold) { 04270 trunk_ref->trunk->on_hold = 0; 04271 ast_indicate(trunk_ref->trunk->chan, AST_CONTROL_UNHOLD); 04272 sla_change_trunk_state(trunk_ref->trunk, SLA_TRUNK_STATE_UP, ALL_TRUNK_REFS, NULL); 04273 } 04274 04275 snprintf(conf_name, sizeof(conf_name), "SLA_%s", trunk_ref->trunk->name); 04276 ast_set_flag(&conf_flags, 04277 CONFFLAG_QUIET | CONFFLAG_MARKEDEXIT | CONFFLAG_PASS_DTMF | CONFFLAG_SLA_STATION); 04278 ast_answer(chan); 04279 conf = build_conf(conf_name, "", "", 0, 0, 1); 04280 if (conf) { 04281 conf_run(chan, conf, conf_flags.flags, NULL); 04282 dispose_conf(conf); 04283 conf = NULL; 04284 } 04285 trunk_ref->chan = NULL; 04286 if (ast_atomic_dec_and_test((int *) &trunk_ref->trunk->active_stations) && 04287 trunk_ref->state != SLA_TRUNK_STATE_ONHOLD_BYME) { 04288 strncat(conf_name, "|K", sizeof(conf_name) - strlen(conf_name) - 1); 04289 admin_exec(NULL, conf_name); 04290 trunk_ref->trunk->hold_stations = 0; 04291 sla_change_trunk_state(trunk_ref->trunk, SLA_TRUNK_STATE_IDLE, ALL_TRUNK_REFS, NULL); 04292 } 04293 04294 pbx_builtin_setvar_helper(chan, "SLASTATION_STATUS", "SUCCESS"); 04295 04296 return 0; 04297 }
static void sla_stop_ringing_station | ( | struct sla_ringing_station * | ringing_station, | |
enum sla_station_hangup | hangup | |||
) | [static] |
Definition at line 3325 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().
03327 { 03328 struct sla_ringing_trunk *ringing_trunk; 03329 struct sla_trunk_ref *trunk_ref; 03330 struct sla_station_ref *station_ref; 03331 03332 ast_dial_join(ringing_station->station->dial); 03333 ast_dial_destroy(ringing_station->station->dial); 03334 ringing_station->station->dial = NULL; 03335 03336 if (hangup == SLA_STATION_HANGUP_NORMAL) 03337 goto done; 03338 03339 /* If the station is being hung up because of a timeout, then add it to the 03340 * list of timed out stations on each of the ringing trunks. This is so 03341 * that when doing further processing to figure out which stations should be 03342 * ringing, which trunk to answer, determining timeouts, etc., we know which 03343 * ringing trunks we should ignore. */ 03344 AST_LIST_TRAVERSE(&sla.ringing_trunks, ringing_trunk, entry) { 03345 AST_LIST_TRAVERSE(&ringing_station->station->trunks, trunk_ref, entry) { 03346 if (ringing_trunk->trunk == trunk_ref->trunk) 03347 break; 03348 } 03349 if (!trunk_ref) 03350 continue; 03351 if (!(station_ref = sla_create_station_ref(ringing_station->station))) 03352 continue; 03353 AST_LIST_INSERT_TAIL(&ringing_trunk->timed_out_stations, station_ref, entry); 03354 } 03355 03356 done: 03357 free(ringing_station); 03358 }
static void sla_stop_ringing_trunk | ( | struct sla_ringing_trunk * | ringing_trunk | ) | [static] |
Definition at line 3310 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().
03311 { 03312 char buf[80]; 03313 struct sla_station_ref *station_ref; 03314 03315 snprintf(buf, sizeof(buf), "SLA_%s|K", ringing_trunk->trunk->name); 03316 admin_exec(NULL, buf); 03317 sla_change_trunk_state(ringing_trunk->trunk, SLA_TRUNK_STATE_IDLE, ALL_TRUNK_REFS, NULL); 03318 03319 while ((station_ref = AST_LIST_REMOVE_HEAD(&ringing_trunk->timed_out_stations, entry))) 03320 free(station_ref); 03321 03322 free(ringing_trunk); 03323 }
static void* sla_thread | ( | void * | data | ) | [static] |
Definition at line 3958 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(), and sla_process_timers().
Referenced by sla_load_config().
03959 { 03960 struct sla_failed_station *failed_station; 03961 struct sla_ringing_station *ringing_station; 03962 03963 ast_mutex_lock(&sla.lock); 03964 03965 while (!sla.stop) { 03966 struct sla_event *event; 03967 struct timespec ts = { 0, }; 03968 unsigned int have_timeout = 0; 03969 03970 if (AST_LIST_EMPTY(&sla.event_q)) { 03971 if ((have_timeout = sla_process_timers(&ts))) 03972 ast_cond_timedwait(&sla.cond, &sla.lock, &ts); 03973 else 03974 ast_cond_wait(&sla.cond, &sla.lock); 03975 if (sla.stop) 03976 break; 03977 } 03978 03979 if (have_timeout) 03980 sla_process_timers(NULL); 03981 03982 while ((event = AST_LIST_REMOVE_HEAD(&sla.event_q, entry))) { 03983 ast_mutex_unlock(&sla.lock); 03984 switch (event->type) { 03985 case SLA_EVENT_HOLD: 03986 sla_handle_hold_event(event); 03987 break; 03988 case SLA_EVENT_DIAL_STATE: 03989 sla_handle_dial_state_event(); 03990 break; 03991 case SLA_EVENT_RINGING_TRUNK: 03992 sla_handle_ringing_trunk_event(); 03993 break; 03994 } 03995 free(event); 03996 ast_mutex_lock(&sla.lock); 03997 } 03998 } 03999 04000 ast_mutex_unlock(&sla.lock); 04001 04002 while ((ringing_station = AST_LIST_REMOVE_HEAD(&sla.ringing_stations, entry))) 04003 free(ringing_station); 04004 04005 while ((failed_station = AST_LIST_REMOVE_HEAD(&sla.failed_stations, entry))) 04006 free(failed_station); 04007 04008 return NULL; 04009 }
static int sla_trunk_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Definition at line 4332 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(), ast_conference::chan, conf_run(), CONFFLAG_MARKEDEXIT, CONFFLAG_MARKEDUSER, CONFFLAG_PASS_DTMF, 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().
04333 { 04334 const char *trunk_name = data; 04335 char conf_name[MAX_CONFNUM]; 04336 struct ast_conference *conf; 04337 struct ast_flags conf_flags = { 0 }; 04338 struct sla_trunk *trunk; 04339 struct sla_ringing_trunk *ringing_trunk; 04340 04341 AST_RWLIST_RDLOCK(&sla_trunks); 04342 trunk = sla_find_trunk(trunk_name); 04343 AST_RWLIST_UNLOCK(&sla_trunks); 04344 if (!trunk) { 04345 ast_log(LOG_ERROR, "SLA Trunk '%s' not found!\n", trunk_name); 04346 pbx_builtin_setvar_helper(chan, "SLATRUNK_STATUS", "FAILURE"); 04347 return 0; 04348 } 04349 if (trunk->chan) { 04350 ast_log(LOG_ERROR, "Call came in on %s, but the trunk is already in use!\n", 04351 trunk_name); 04352 pbx_builtin_setvar_helper(chan, "SLATRUNK_STATUS", "FAILURE"); 04353 return 0; 04354 } 04355 trunk->chan = chan; 04356 04357 if (!(ringing_trunk = queue_ringing_trunk(trunk))) { 04358 pbx_builtin_setvar_helper(chan, "SLATRUNK_STATUS", "FAILURE"); 04359 return 0; 04360 } 04361 04362 snprintf(conf_name, sizeof(conf_name), "SLA_%s", trunk_name); 04363 conf = build_conf(conf_name, "", "", 1, 1, 1); 04364 if (!conf) { 04365 pbx_builtin_setvar_helper(chan, "SLATRUNK_STATUS", "FAILURE"); 04366 return 0; 04367 } 04368 ast_set_flag(&conf_flags, 04369 CONFFLAG_QUIET | CONFFLAG_MARKEDEXIT | CONFFLAG_MARKEDUSER | CONFFLAG_PASS_DTMF); 04370 ast_indicate(chan, AST_CONTROL_RINGING); 04371 conf_run(chan, conf, conf_flags.flags, NULL); 04372 dispose_conf(conf); 04373 conf = NULL; 04374 trunk->chan = NULL; 04375 trunk->on_hold = 0; 04376 04377 sla_change_trunk_state(trunk, SLA_TRUNK_STATE_IDLE, ALL_TRUNK_REFS, NULL); 04378 04379 if (!pbx_builtin_getvar_helper(chan, "SLATRUNK_STATUS")) 04380 pbx_builtin_setvar_helper(chan, "SLATRUNK_STATUS", "SUCCESS"); 04381 04382 /* Remove the entry from the list of ringing trunks if it is still there. */ 04383 ast_mutex_lock(&sla.lock); 04384 AST_LIST_TRAVERSE_SAFE_BEGIN(&sla.ringing_trunks, ringing_trunk, entry) { 04385 if (ringing_trunk->trunk == trunk) { 04386 AST_LIST_REMOVE_CURRENT(&sla.ringing_trunks, entry); 04387 break; 04388 } 04389 } 04390 AST_LIST_TRAVERSE_SAFE_END 04391 ast_mutex_unlock(&sla.lock); 04392 if (ringing_trunk) { 04393 free(ringing_trunk); 04394 pbx_builtin_setvar_helper(chan, "SLATRUNK_STATUS", "UNANSWERED"); 04395 /* Queue reprocessing of ringing trunks to make stations stop ringing 04396 * that shouldn't be ringing after this trunk stopped. */ 04397 sla_queue_event(SLA_EVENT_RINGING_TRUNK); 04398 } 04399 04400 return 0; 04401 }
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, 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 4833 of file app_meetme.c.
References ARRAY_LEN, ast_cli_unregister_multiple(), ast_devstate_prov_del(), ast_manager_unregister(), ast_module_user_hangup_all, ast_unregister_application(), cli_meetme, and sla_destroy().
04834 { 04835 int res = 0; 04836 04837 ast_cli_unregister_multiple(cli_meetme, ARRAY_LEN(cli_meetme)); 04838 res = ast_manager_unregister("MeetmeMute"); 04839 res |= ast_manager_unregister("MeetmeUnmute"); 04840 res |= ast_unregister_application(app3); 04841 res |= ast_unregister_application(app2); 04842 res |= ast_unregister_application(app); 04843 res |= ast_unregister_application(slastation_app); 04844 res |= ast_unregister_application(slatrunk_app); 04845 04846 ast_devstate_prov_del("Meetme"); 04847 ast_devstate_prov_del("SLA"); 04848 04849 ast_module_user_hangup_all(); 04850 04851 sla_destroy(); 04852 04853 return res; 04854 }
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.
Referenced by load_config_meetme().
struct ast_cli_entry cli_meetme[] [static] |
Definition at line 524 of file app_meetme.c.
Referenced by _macro_exec(), sla_handle_dial_state_event(), sla_station_exec(), and smdi_message_wait().
unsigned int conf_map[1024] = {0, } [static] |
Definition at line 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(), 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(), handle_deferred_full_frames(), iax2_process_thread(), iax2_process_thread_cleanup(), iax2_show_threads(), insert_idle_thread(), launch_monitor_thread(), load_module(), socket_process(), socket_read(), and start_network_thread().