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