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