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