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