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