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