#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 5064 of file app_meetme.c.
static void __unreg_module | ( | void | ) | [static] |
Definition at line 5064 of file app_meetme.c.
static int action_meetmemute | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 3177 of file app_meetme.c.
References meetmemute(), and s.
Referenced by load_module().
03178 { 03179 return meetmemute(s, m, 1); 03180 }
static int action_meetmeunmute | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 3182 of file app_meetme.c.
References meetmemute(), and s.
Referenced by load_module().
03183 { 03184 return meetmemute(s, m, 0); 03185 }
static int admin_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
The MeetMeadmin application.
Definition at line 2963 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().
02963 { 02964 char *params; 02965 struct ast_conference *cnf; 02966 struct ast_conf_user *user = NULL; 02967 struct ast_module_user *u; 02968 AST_DECLARE_APP_ARGS(args, 02969 AST_APP_ARG(confno); 02970 AST_APP_ARG(command); 02971 AST_APP_ARG(user); 02972 ); 02973 02974 if (ast_strlen_zero(data)) { 02975 ast_log(LOG_WARNING, "MeetMeAdmin requires an argument!\n"); 02976 return -1; 02977 } 02978 02979 u = ast_module_user_add(chan); 02980 02981 AST_LIST_LOCK(&confs); 02982 02983 params = ast_strdupa(data); 02984 AST_STANDARD_APP_ARGS(args, params); 02985 02986 if (!args.command) { 02987 ast_log(LOG_WARNING, "MeetmeAdmin requires a command!\n"); 02988 AST_LIST_UNLOCK(&confs); 02989 ast_module_user_remove(u); 02990 return -1; 02991 } 02992 AST_LIST_TRAVERSE(&confs, cnf, list) { 02993 if (!strcmp(cnf->confno, args.confno)) 02994 break; 02995 } 02996 02997 if (!cnf) { 02998 ast_log(LOG_WARNING, "Conference number '%s' not found!\n", args.confno); 02999 AST_LIST_UNLOCK(&confs); 03000 ast_module_user_remove(u); 03001 return 0; 03002 } 03003 03004 ast_atomic_fetchadd_int(&cnf->refcount, 1); 03005 03006 if (args.user) 03007 user = find_user(cnf, args.user); 03008 03009 switch (*args.command) { 03010 case 76: /* L: Lock */ 03011 cnf->locked = 1; 03012 break; 03013 case 108: /* l: Unlock */ 03014 cnf->locked = 0; 03015 break; 03016 case 75: /* K: kick all users */ 03017 AST_LIST_TRAVERSE(&cnf->userlist, user, list) 03018 user->adminflags |= ADMINFLAG_KICKME; 03019 break; 03020 case 101: /* e: Eject last user*/ 03021 user = AST_LIST_LAST(&cnf->userlist); 03022 if (!(user->userflags & CONFFLAG_ADMIN)) 03023 user->adminflags |= ADMINFLAG_KICKME; 03024 else 03025 ast_log(LOG_NOTICE, "Not kicking last user, is an Admin!\n"); 03026 break; 03027 case 77: /* M: Mute */ 03028 if (user) { 03029 user->adminflags |= ADMINFLAG_MUTED; 03030 } else 03031 ast_log(LOG_NOTICE, "Specified User not found!\n"); 03032 break; 03033 case 78: /* N: Mute all (non-admin) users */ 03034 AST_LIST_TRAVERSE(&cnf->userlist, user, list) { 03035 if (!(user->userflags & CONFFLAG_ADMIN)) 03036 user->adminflags |= ADMINFLAG_MUTED; 03037 } 03038 break; 03039 case 109: /* m: Unmute */ 03040 if (user) { 03041 user->adminflags &= ~(ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED); 03042 } else 03043 ast_log(LOG_NOTICE, "Specified User not found!\n"); 03044 break; 03045 case 110: /* n: Unmute all users */ 03046 AST_LIST_TRAVERSE(&cnf->userlist, user, list) 03047 user->adminflags &= ~(ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED); 03048 break; 03049 case 107: /* k: Kick user */ 03050 if (user) 03051 user->adminflags |= ADMINFLAG_KICKME; 03052 else 03053 ast_log(LOG_NOTICE, "Specified User not found!\n"); 03054 break; 03055 case 118: /* v: Lower all users listen volume */ 03056 AST_LIST_TRAVERSE(&cnf->userlist, user, list) 03057 tweak_listen_volume(user, VOL_DOWN); 03058 break; 03059 case 86: /* V: Raise all users listen volume */ 03060 AST_LIST_TRAVERSE(&cnf->userlist, user, list) 03061 tweak_listen_volume(user, VOL_UP); 03062 break; 03063 case 115: /* s: Lower all users speaking volume */ 03064 AST_LIST_TRAVERSE(&cnf->userlist, user, list) 03065 tweak_talk_volume(user, VOL_DOWN); 03066 break; 03067 case 83: /* S: Raise all users speaking volume */ 03068 AST_LIST_TRAVERSE(&cnf->userlist, user, list) 03069 tweak_talk_volume(user, VOL_UP); 03070 break; 03071 case 82: /* R: Reset all volume levels */ 03072 AST_LIST_TRAVERSE(&cnf->userlist, user, list) 03073 reset_volumes(user); 03074 break; 03075 case 114: /* r: Reset user's volume level */ 03076 if (user) 03077 reset_volumes(user); 03078 else 03079 ast_log(LOG_NOTICE, "Specified User not found!\n"); 03080 break; 03081 case 85: /* U: Raise user's listen volume */ 03082 if (user) 03083 tweak_listen_volume(user, VOL_UP); 03084 else 03085 ast_log(LOG_NOTICE, "Specified User not found!\n"); 03086 break; 03087 case 117: /* u: Lower user's listen volume */ 03088 if (user) 03089 tweak_listen_volume(user, VOL_DOWN); 03090 else 03091 ast_log(LOG_NOTICE, "Specified User not found!\n"); 03092 break; 03093 case 84: /* T: Raise user's talk volume */ 03094 if (user) 03095 tweak_talk_volume(user, VOL_UP); 03096 else 03097 ast_log(LOG_NOTICE, "Specified User not found!\n"); 03098 break; 03099 case 116: /* t: Lower user's talk volume */ 03100 if (user) 03101 tweak_talk_volume(user, VOL_DOWN); 03102 else 03103 ast_log(LOG_NOTICE, "Specified User not found!\n"); 03104 break; 03105 } 03106 03107 AST_LIST_UNLOCK(&confs); 03108 03109 dispose_conf(cnf); 03110 03111 ast_module_user_remove(u); 03112 03113 return 0; 03114 }
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 3433 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().
03434 { 03435 ast_answer(chan); 03436 ast_indicate(chan, -1); 03437 }
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 2700 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.
02701 { 02702 int res=-1; 02703 struct ast_module_user *u; 02704 char confno[MAX_CONFNUM] = ""; 02705 int allowretry = 0; 02706 int retrycnt = 0; 02707 struct ast_conference *cnf = NULL; 02708 struct ast_flags confflags = {0}; 02709 int dynamic = 0; 02710 int empty = 0, empty_no_pin = 0; 02711 int always_prompt = 0; 02712 char *notdata, *info, the_pin[MAX_PIN] = ""; 02713 AST_DECLARE_APP_ARGS(args, 02714 AST_APP_ARG(confno); 02715 AST_APP_ARG(options); 02716 AST_APP_ARG(pin); 02717 ); 02718 char *optargs[OPT_ARG_ARRAY_SIZE] = { NULL, }; 02719 02720 u = ast_module_user_add(chan); 02721 02722 if (ast_strlen_zero(data)) { 02723 allowretry = 1; 02724 notdata = ""; 02725 } else { 02726 notdata = data; 02727 } 02728 02729 if (chan->_state != AST_STATE_UP) 02730 ast_answer(chan); 02731 02732 info = ast_strdupa(notdata); 02733 02734 AST_STANDARD_APP_ARGS(args, info); 02735 02736 if (args.confno) { 02737 ast_copy_string(confno, args.confno, sizeof(confno)); 02738 if (ast_strlen_zero(confno)) { 02739 allowretry = 1; 02740 } 02741 } 02742 02743 if (args.pin) 02744 ast_copy_string(the_pin, args.pin, sizeof(the_pin)); 02745 02746 if (args.options) { 02747 ast_app_parse_options(meetme_opts, &confflags, optargs, args.options); 02748 dynamic = ast_test_flag(&confflags, CONFFLAG_DYNAMIC | CONFFLAG_DYNAMICPIN); 02749 if (ast_test_flag(&confflags, CONFFLAG_DYNAMICPIN) && ast_strlen_zero(args.pin)) 02750 strcpy(the_pin, "q"); 02751 02752 empty = ast_test_flag(&confflags, CONFFLAG_EMPTY | CONFFLAG_EMPTYNOPIN); 02753 empty_no_pin = ast_test_flag(&confflags, CONFFLAG_EMPTYNOPIN); 02754 always_prompt = ast_test_flag(&confflags, CONFFLAG_ALWAYSPROMPT | CONFFLAG_DYNAMICPIN); 02755 } 02756 02757 do { 02758 if (retrycnt > 3) 02759 allowretry = 0; 02760 if (empty) { 02761 int i; 02762 struct ast_config *cfg; 02763 struct ast_variable *var; 02764 int confno_int; 02765 02766 /* We only need to load the config file for static and empty_no_pin (otherwise we don't care) */ 02767 if ((empty_no_pin) || (!dynamic)) { 02768 cfg = ast_config_load(CONFIG_FILE_NAME); 02769 if (cfg) { 02770 var = ast_variable_browse(cfg, "rooms"); 02771 while (var) { 02772 if (!strcasecmp(var->name, "conf")) { 02773 char *stringp = ast_strdupa(var->value); 02774 if (stringp) { 02775 char *confno_tmp = strsep(&stringp, "|,"); 02776 int found = 0; 02777 if (!dynamic) { 02778 /* For static: run through the list and see if this conference is empty */ 02779 AST_LIST_LOCK(&confs); 02780 AST_LIST_TRAVERSE(&confs, cnf, list) { 02781 if (!strcmp(confno_tmp, cnf->confno)) { 02782 /* The conference exists, therefore it's not empty */ 02783 found = 1; 02784 break; 02785 } 02786 } 02787 AST_LIST_UNLOCK(&confs); 02788 if (!found) { 02789 /* At this point, we have a confno_tmp (static conference) that is empty */ 02790 if ((empty_no_pin && ast_strlen_zero(stringp)) || (!empty_no_pin)) { 02791 /* Case 1: empty_no_pin and pin is nonexistent (NULL) 02792 * Case 2: empty_no_pin and pin is blank (but not NULL) 02793 * Case 3: not empty_no_pin 02794 */ 02795 ast_copy_string(confno, confno_tmp, sizeof(confno)); 02796 break; 02797 /* XXX the map is not complete (but we do have a confno) */ 02798 } 02799 } 02800 } 02801 } 02802 } 02803 var = var->next; 02804 } 02805 ast_config_destroy(cfg); 02806 } 02807 } 02808 02809 /* Select first conference number not in use */ 02810 if (ast_strlen_zero(confno) && dynamic) { 02811 AST_LIST_LOCK(&confs); 02812 for (i = 0; i < sizeof(conf_map) / sizeof(conf_map[0]); i++) { 02813 if (!conf_map[i]) { 02814 snprintf(confno, sizeof(confno), "%d", i); 02815 conf_map[i] = 1; 02816 break; 02817 } 02818 } 02819 AST_LIST_UNLOCK(&confs); 02820 } 02821 02822 /* Not found? */ 02823 if (ast_strlen_zero(confno)) { 02824 res = ast_streamfile(chan, "conf-noempty", chan->language); 02825 if (!res) 02826 ast_waitstream(chan, ""); 02827 } else { 02828 if (sscanf(confno, "%30d", &confno_int) == 1) { 02829 res = ast_streamfile(chan, "conf-enteringno", chan->language); 02830 if (!res) { 02831 ast_waitstream(chan, ""); 02832 res = ast_say_digits(chan, confno_int, "", chan->language); 02833 } 02834 } else { 02835 ast_log(LOG_ERROR, "Could not scan confno '%s'\n", confno); 02836 } 02837 } 02838 } 02839 02840 while (allowretry && (ast_strlen_zero(confno)) && (++retrycnt < 4)) { 02841 /* Prompt user for conference number */ 02842 res = ast_app_getdata(chan, "conf-getconfno", confno, sizeof(confno) - 1, 0); 02843 if (res < 0) { 02844 /* Don't try to validate when we catch an error */ 02845 confno[0] = '\0'; 02846 allowretry = 0; 02847 break; 02848 } 02849 } 02850 if (!ast_strlen_zero(confno)) { 02851 /* Check the validity of the conference */ 02852 cnf = find_conf(chan, confno, 1, dynamic, the_pin, 02853 sizeof(the_pin), 1, &confflags); 02854 if (!cnf) { 02855 cnf = find_conf_realtime(chan, confno, 1, dynamic, 02856 the_pin, sizeof(the_pin), 1, &confflags); 02857 } 02858 02859 if (!cnf) { 02860 res = ast_streamfile(chan, "conf-invalid", chan->language); 02861 if (!res) 02862 ast_waitstream(chan, ""); 02863 res = -1; 02864 if (allowretry) 02865 confno[0] = '\0'; 02866 } else { 02867 if ((!ast_strlen_zero(cnf->pin) && 02868 !ast_test_flag(&confflags, CONFFLAG_ADMIN)) || 02869 (!ast_strlen_zero(cnf->pinadmin) && 02870 ast_test_flag(&confflags, CONFFLAG_ADMIN))) { 02871 char pin[MAX_PIN] = ""; 02872 int j; 02873 02874 /* Allow the pin to be retried up to 3 times */ 02875 for (j = 0; j < 3; j++) { 02876 if (*the_pin && (always_prompt == 0)) { 02877 ast_copy_string(pin, the_pin, sizeof(pin)); 02878 res = 0; 02879 } else { 02880 /* Prompt user for pin if pin is required */ 02881 res = ast_app_getdata(chan, "conf-getpin", pin + strlen(pin), sizeof(pin) - 1 - strlen(pin), 0); 02882 } 02883 if (res >= 0) { 02884 if (!strcasecmp(pin, cnf->pin) || 02885 (!ast_strlen_zero(cnf->pinadmin) && 02886 !strcasecmp(pin, cnf->pinadmin))) { 02887 /* Pin correct */ 02888 allowretry = 0; 02889 if (!ast_strlen_zero(cnf->pinadmin) && !strcasecmp(pin, cnf->pinadmin)) 02890 ast_set_flag(&confflags, CONFFLAG_ADMIN); 02891 /* Run the conference */ 02892 res = conf_run(chan, cnf, confflags.flags, optargs); 02893 break; 02894 } else { 02895 /* Pin invalid */ 02896 if (!ast_streamfile(chan, "conf-invalidpin", chan->language)) { 02897 res = ast_waitstream(chan, AST_DIGIT_ANY); 02898 ast_stopstream(chan); 02899 } 02900 else { 02901 ast_log(LOG_WARNING, "Couldn't play invalid pin msg!\n"); 02902 break; 02903 } 02904 if (res < 0) 02905 break; 02906 pin[0] = res; 02907 pin[1] = '\0'; 02908 res = -1; 02909 if (allowretry) 02910 confno[0] = '\0'; 02911 } 02912 } else { 02913 /* failed when getting the pin */ 02914 res = -1; 02915 allowretry = 0; 02916 /* see if we need to get rid of the conference */ 02917 break; 02918 } 02919 02920 /* Don't retry pin with a static pin */ 02921 if (*the_pin && (always_prompt==0)) { 02922 break; 02923 } 02924 } 02925 } else { 02926 /* No pin required */ 02927 allowretry = 0; 02928 02929 /* Run the conference */ 02930 res = conf_run(chan, cnf, confflags.flags, optargs); 02931 } 02932 dispose_conf(cnf); 02933 cnf = NULL; 02934 } 02935 } 02936 } while (allowretry); 02937 02938 if (cnf) 02939 dispose_conf(cnf); 02940 02941 ast_module_user_remove(u); 02942 02943 return res; 02944 }
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, mohtempstopped = 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 int confsilence = 0, totalsilence = 0; 01540 01541 if (!(user = ast_calloc(1, sizeof(*user)))) 01542 return ret; 01543 01544 /* Possible timeout waiting for marked user */ 01545 if ((confflags & CONFFLAG_WAITMARKED) && 01546 !ast_strlen_zero(optargs[OPT_ARG_WAITMARKED]) && 01547 (sscanf(optargs[OPT_ARG_WAITMARKED], "%30d", &opt_waitmarked_timeout) == 1) && 01548 (opt_waitmarked_timeout > 0)) { 01549 timeout = time(NULL) + opt_waitmarked_timeout; 01550 } 01551 01552 if (confflags & CONFFLAG_RECORDCONF) { 01553 if (!conf->recordingfilename) { 01554 conf->recordingfilename = pbx_builtin_getvar_helper(chan, "MEETME_RECORDINGFILE"); 01555 if (!conf->recordingfilename) { 01556 snprintf(recordingtmp, sizeof(recordingtmp), "meetme-conf-rec-%s-%s", conf->confno, chan->uniqueid); 01557 conf->recordingfilename = ast_strdupa(recordingtmp); 01558 } 01559 conf->recordingformat = pbx_builtin_getvar_helper(chan, "MEETME_RECORDINGFORMAT"); 01560 if (!conf->recordingformat) { 01561 snprintf(recordingtmp, sizeof(recordingtmp), "wav"); 01562 conf->recordingformat = ast_strdupa(recordingtmp); 01563 } 01564 ast_verbose(VERBOSE_PREFIX_4 "Starting recording of MeetMe Conference %s into file %s.%s.\n", 01565 conf->confno, conf->recordingfilename, conf->recordingformat); 01566 } 01567 } 01568 01569 ast_mutex_lock(&conf->recordthreadlock); 01570 if ((conf->recordthread == AST_PTHREADT_NULL) && (confflags & CONFFLAG_RECORDCONF) && ((conf->lchan = ast_request(dahdi_chan_name, AST_FORMAT_SLINEAR, "pseudo", NULL)))) { 01571 ast_set_read_format(conf->lchan, AST_FORMAT_SLINEAR); 01572 ast_set_write_format(conf->lchan, AST_FORMAT_SLINEAR); 01573 ztc.chan = 0; 01574 ztc.confno = conf->zapconf; 01575 ztc.confmode = DAHDI_CONF_CONFANN | DAHDI_CONF_CONFANNMON; 01576 if (ioctl(conf->lchan->fds[0], DAHDI_SETCONF, &ztc)) { 01577 ast_log(LOG_WARNING, "Error starting listen channel\n"); 01578 ast_hangup(conf->lchan); 01579 conf->lchan = NULL; 01580 } else { 01581 pthread_attr_init(&conf->attr); 01582 pthread_attr_setdetachstate(&conf->attr, PTHREAD_CREATE_DETACHED); 01583 ast_pthread_create_background(&conf->recordthread, &conf->attr, recordthread, conf); 01584 pthread_attr_destroy(&conf->attr); 01585 } 01586 } 01587 ast_mutex_unlock(&conf->recordthreadlock); 01588 01589 ast_mutex_lock(&conf->announcethreadlock); 01590 if ((conf->announcethread == AST_PTHREADT_NULL) && !(confflags & CONFFLAG_QUIET) && ((confflags & CONFFLAG_INTROUSER) || (confflags & CONFFLAG_INTROUSERNOREVIEW))) { 01591 ast_mutex_init(&conf->announcelistlock); 01592 AST_LIST_HEAD_INIT_NOLOCK(&conf->announcelist); 01593 ast_pthread_create_background(&conf->announcethread, NULL, announce_thread, conf); 01594 } 01595 ast_mutex_unlock(&conf->announcethreadlock); 01596 01597 time(&user->jointime); 01598 01599 if (conf->locked && (!(confflags & CONFFLAG_ADMIN))) { 01600 /* Sorry, but this confernce is locked! */ 01601 if (!ast_streamfile(chan, "conf-locked", chan->language)) 01602 ast_waitstream(chan, ""); 01603 goto outrun; 01604 } 01605 01606 ast_mutex_lock(&conf->playlock); 01607 01608 if (AST_LIST_EMPTY(&conf->userlist)) 01609 user->user_no = 1; 01610 else 01611 user->user_no = AST_LIST_LAST(&conf->userlist)->user_no + 1; 01612 01613 AST_LIST_INSERT_TAIL(&conf->userlist, user, list); 01614 01615 user->chan = chan; 01616 user->userflags = confflags; 01617 user->adminflags = (confflags & CONFFLAG_STARTMUTED) ? ADMINFLAG_SELFMUTED : 0; 01618 user->talking = -1; 01619 01620 ast_mutex_unlock(&conf->playlock); 01621 01622 if (!(confflags & CONFFLAG_QUIET) && ((confflags & CONFFLAG_INTROUSER) || (confflags & CONFFLAG_INTROUSERNOREVIEW))) { 01623 char destdir[PATH_MAX]; 01624 01625 snprintf(destdir, sizeof(destdir), "%s/meetme", ast_config_AST_SPOOL_DIR); 01626 01627 if (mkdir(destdir, 0777) && errno != EEXIST) { 01628 ast_log(LOG_WARNING, "mkdir '%s' failed: %s\n", destdir, strerror(errno)); 01629 goto outrun; 01630 } 01631 01632 snprintf(user->namerecloc, sizeof(user->namerecloc), 01633 "%s/meetme-username-%s-%d", destdir, 01634 conf->confno, user->user_no); 01635 if (confflags & CONFFLAG_INTROUSERNOREVIEW) 01636 res = ast_play_and_record(chan, "vm-rec-name", user->namerecloc, 10, "sln", &duration, 128, 0, NULL); 01637 else 01638 res = ast_record_review(chan, "vm-rec-name", user->namerecloc, 10, "sln", &duration, NULL); 01639 if (res == -1) 01640 goto outrun; 01641 } 01642 01643 ast_mutex_lock(&conf->playlock); 01644 01645 if (confflags & CONFFLAG_MARKEDUSER) 01646 conf->markedusers++; 01647 conf->users++; 01648 /* Update table */ 01649 snprintf(members, sizeof(members), "%d", conf->users); 01650 ast_update_realtime("meetme", "confno", conf->confno, "members", members , NULL); 01651 setusercount = 1; 01652 01653 /* This device changed state now - if this is the first user */ 01654 if (conf->users == 1) 01655 ast_device_state_changed("meetme:%s", conf->confno); 01656 01657 ast_mutex_unlock(&conf->playlock); 01658 01659 if (confflags & CONFFLAG_EXIT_CONTEXT) { 01660 if ((agifile = pbx_builtin_getvar_helper(chan, "MEETME_EXIT_CONTEXT"))) 01661 ast_copy_string(exitcontext, agifile, sizeof(exitcontext)); 01662 else if (!ast_strlen_zero(chan->macrocontext)) 01663 ast_copy_string(exitcontext, chan->macrocontext, sizeof(exitcontext)); 01664 else 01665 ast_copy_string(exitcontext, chan->context, sizeof(exitcontext)); 01666 } 01667 01668 /* Playback artbitrary intro message */ 01669 if ((confflags & CONFFLAG_INTROMSG) && 01670 !ast_strlen_zero(optargs[OPT_ARG_INTROMSG])) { 01671 if (!ast_streamfile(chan, optargs[OPT_ARG_INTROMSG], chan->language)) 01672 ast_waitstream(chan, ""); 01673 } 01674 01675 if ( !(confflags & (CONFFLAG_QUIET | CONFFLAG_NOONLYPERSON)) ) { 01676 if (conf->users == 1 && !(confflags & CONFFLAG_WAITMARKED)) 01677 if (!ast_streamfile(chan, "conf-onlyperson", chan->language)) 01678 ast_waitstream(chan, ""); 01679 if ((confflags & CONFFLAG_WAITMARKED) && conf->markedusers == 0) 01680 if (!ast_streamfile(chan, "conf-waitforleader", chan->language)) 01681 ast_waitstream(chan, ""); 01682 } 01683 01684 if (!(confflags & CONFFLAG_QUIET) && (confflags & CONFFLAG_ANNOUNCEUSERCOUNT) && conf->users > 1) { 01685 int keepplaying = 1; 01686 01687 if (conf->users == 2) { 01688 if (!ast_streamfile(chan,"conf-onlyone",chan->language)) { 01689 res = ast_waitstream(chan, AST_DIGIT_ANY); 01690 ast_stopstream(chan); 01691 if (res > 0) 01692 keepplaying=0; 01693 else if (res == -1) 01694 goto outrun; 01695 } 01696 } else { 01697 if (!ast_streamfile(chan, "conf-thereare", chan->language)) { 01698 res = ast_waitstream(chan, AST_DIGIT_ANY); 01699 ast_stopstream(chan); 01700 if (res > 0) 01701 keepplaying=0; 01702 else if (res == -1) 01703 goto outrun; 01704 } 01705 if (keepplaying) { 01706 res = ast_say_number(chan, conf->users - 1, AST_DIGIT_ANY, chan->language, (char *) NULL); 01707 if (res > 0) 01708 keepplaying=0; 01709 else if (res == -1) 01710 goto outrun; 01711 } 01712 if (keepplaying && !ast_streamfile(chan, "conf-otherinparty", chan->language)) { 01713 res = ast_waitstream(chan, AST_DIGIT_ANY); 01714 ast_stopstream(chan); 01715 if (res > 0) 01716 keepplaying=0; 01717 else if (res == -1) 01718 goto outrun; 01719 } 01720 } 01721 } 01722 01723 if (!(confflags & CONFFLAG_NO_AUDIO_UNTIL_UP)) { 01724 /* We're leaving this alone until the state gets changed to up */ 01725 ast_indicate(chan, -1); 01726 } 01727 01728 if (ast_set_write_format(chan, AST_FORMAT_SLINEAR) < 0) { 01729 ast_log(LOG_WARNING, "Unable to set '%s' to write linear mode\n", chan->name); 01730 goto outrun; 01731 } 01732 01733 if (ast_set_read_format(chan, AST_FORMAT_SLINEAR) < 0) { 01734 ast_log(LOG_WARNING, "Unable to set '%s' to read linear mode\n", chan->name); 01735 goto outrun; 01736 } 01737 01738 retryzap = (strcasecmp(chan->tech->type, dahdi_chan_name) || (chan->audiohooks || chan->monitor) ? 1 : 0); 01739 user->zapchannel = !retryzap; 01740 01741 zapretry: 01742 origfd = chan->fds[0]; 01743 if (retryzap) { 01744 /* open pseudo in non-blocking mode */ 01745 fd = open(DAHDI_FILE_PSEUDO, O_RDWR | O_NONBLOCK); 01746 if (fd < 0) { 01747 ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno)); 01748 goto outrun; 01749 } 01750 using_pseudo = 1; 01751 /* Setup buffering information */ 01752 memset(&bi, 0, sizeof(bi)); 01753 bi.bufsize = CONF_SIZE/2; 01754 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE; 01755 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE; 01756 bi.numbufs = audio_buffers; 01757 if (ioctl(fd, DAHDI_SET_BUFINFO, &bi)) { 01758 ast_log(LOG_WARNING, "Unable to set buffering information: %s\n", strerror(errno)); 01759 close(fd); 01760 goto outrun; 01761 } 01762 x = 1; 01763 if (ioctl(fd, DAHDI_SETLINEAR, &x)) { 01764 ast_log(LOG_WARNING, "Unable to set linear mode: %s\n", strerror(errno)); 01765 close(fd); 01766 goto outrun; 01767 } 01768 nfds = 1; 01769 } else { 01770 /* XXX Make sure we're not running on a pseudo channel XXX */ 01771 fd = chan->fds[0]; 01772 nfds = 0; 01773 } 01774 memset(&ztc, 0, sizeof(ztc)); 01775 memset(&ztc_empty, 0, sizeof(ztc_empty)); 01776 /* Check to see if we're in a conference... */ 01777 ztc.chan = 0; 01778 if (ioctl(fd, DAHDI_GETCONF, &ztc)) { 01779 ast_log(LOG_WARNING, "Error getting conference\n"); 01780 close(fd); 01781 goto outrun; 01782 } 01783 if (ztc.confmode) { 01784 /* Whoa, already in a conference... Retry... */ 01785 if (!retryzap) { 01786 ast_log(LOG_DEBUG, "%s channel is in a conference already, retrying with pseudo\n", dahdi_chan_name); 01787 retryzap = 1; 01788 goto zapretry; 01789 } 01790 } 01791 memset(&ztc, 0, sizeof(ztc)); 01792 /* Add us to the conference */ 01793 ztc.chan = 0; 01794 ztc.confno = conf->zapconf; 01795 01796 if (!(confflags & CONFFLAG_QUIET) && ((confflags & CONFFLAG_INTROUSER) || (confflags & CONFFLAG_INTROUSERNOREVIEW)) && conf->users > 1) { 01797 struct announce_listitem *item; 01798 if (!(item = ao2_alloc(sizeof(*item), NULL))) 01799 return -1; 01800 ast_copy_string(item->namerecloc, user->namerecloc, sizeof(item->namerecloc)); 01801 ast_copy_string(item->language, chan->language, sizeof(item->language)); 01802 item->confchan = conf->chan; 01803 item->confusers = conf->users; 01804 item->announcetype = CONF_HASJOIN; 01805 ast_mutex_lock(&conf->announcelistlock); 01806 ao2_ref(item, +1); /* add one more so we can determine when announce_thread is done playing it */ 01807 AST_LIST_INSERT_TAIL(&conf->announcelist, item, entry); 01808 ast_cond_signal(&conf->announcelist_addition); 01809 ast_mutex_unlock(&conf->announcelistlock); 01810 01811 while (!ast_check_hangup(conf->chan) && ao2_ref(item, 0) == 2 && !ast_safe_sleep(chan, 1000)) { 01812 ; 01813 } 01814 ao2_ref(item, -1); 01815 } 01816 01817 if (confflags & CONFFLAG_WAITMARKED && !conf->markedusers) 01818 ztc.confmode = DAHDI_CONF_CONF; 01819 else if (confflags & CONFFLAG_MONITOR) 01820 ztc.confmode = DAHDI_CONF_CONFMON | DAHDI_CONF_LISTENER; 01821 else if (confflags & CONFFLAG_TALKER) 01822 ztc.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER; 01823 else 01824 ztc.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER; 01825 01826 if (ioctl(fd, DAHDI_SETCONF, &ztc)) { 01827 ast_log(LOG_WARNING, "Error setting conference\n"); 01828 close(fd); 01829 goto outrun; 01830 } 01831 ast_log(LOG_DEBUG, "Placed channel %s in %s conf %d\n", chan->name, dahdi_chan_name, conf->zapconf); 01832 01833 if (!sent_event) { 01834 manager_event(EVENT_FLAG_CALL, "MeetmeJoin", 01835 "Channel: %s\r\n" 01836 "Uniqueid: %s\r\n" 01837 "Meetme: %s\r\n" 01838 "Usernum: %d\r\n", 01839 chan->name, chan->uniqueid, conf->confno, user->user_no); 01840 sent_event = 1; 01841 } 01842 01843 if (!firstpass && !(confflags & CONFFLAG_MONITOR) && !(confflags & CONFFLAG_ADMIN)) { 01844 firstpass = 1; 01845 if (!(confflags & CONFFLAG_QUIET)) 01846 if (!(confflags & CONFFLAG_WAITMARKED) || ((confflags & CONFFLAG_MARKEDUSER) && (conf->markedusers >= 1))) 01847 conf_play(chan, conf, ENTER); 01848 } 01849 01850 conf_flush(fd, chan); 01851 01852 if (!(dsp = ast_dsp_new())) { 01853 ast_log(LOG_WARNING, "Unable to allocate DSP!\n"); 01854 res = -1; 01855 } 01856 01857 if (confflags & CONFFLAG_AGI) { 01858 /* Get name of AGI file to run from $(MEETME_AGI_BACKGROUND) 01859 or use default filename of conf-background.agi */ 01860 01861 agifile = pbx_builtin_getvar_helper(chan, "MEETME_AGI_BACKGROUND"); 01862 if (!agifile) 01863 agifile = agifiledefault; 01864 01865 if (user->zapchannel) { 01866 /* Set CONFMUTE mode on Zap channel to mute DTMF tones */ 01867 x = 1; 01868 ast_channel_setoption(chan, AST_OPTION_TONE_VERIFY, &x, sizeof(char), 0); 01869 } 01870 /* Find a pointer to the agi app and execute the script */ 01871 app = pbx_findapp("agi"); 01872 if (app) { 01873 char *s = ast_strdupa(agifile); 01874 ret = pbx_exec(chan, app, s); 01875 } else { 01876 ast_log(LOG_WARNING, "Could not find application (agi)\n"); 01877 ret = -2; 01878 } 01879 if (user->zapchannel) { 01880 /* Remove CONFMUTE mode on Zap channel */ 01881 x = 0; 01882 ast_channel_setoption(chan, AST_OPTION_TONE_VERIFY, &x, sizeof(char), 0); 01883 } 01884 } else { 01885 if (user->zapchannel && (confflags & CONFFLAG_STARMENU)) { 01886 /* Set CONFMUTE mode on Zap channel to mute DTMF tones when the menu is enabled */ 01887 x = 1; 01888 ast_channel_setoption(chan, AST_OPTION_TONE_VERIFY, &x, sizeof(char), 0); 01889 } 01890 for(;;) { 01891 int menu_was_active = 0; 01892 01893 outfd = -1; 01894 ms = -1; 01895 01896 if (timeout && time(NULL) >= timeout) 01897 break; 01898 01899 /* if we have just exited from the menu, and the user had a channel-driver 01900 volume adjustment, restore it 01901 */ 01902 if (!menu_active && menu_was_active && user->listen.desired && !user->listen.actual) 01903 set_talk_volume(user, user->listen.desired); 01904 01905 menu_was_active = menu_active; 01906 01907 currentmarked = conf->markedusers; 01908 if (!(confflags & CONFFLAG_QUIET) && 01909 (confflags & CONFFLAG_MARKEDUSER) && 01910 (confflags & CONFFLAG_WAITMARKED) && 01911 lastmarked == 0) { 01912 if (currentmarked == 1 && conf->users > 1) { 01913 ast_say_number(chan, conf->users - 1, AST_DIGIT_ANY, chan->language, (char *) NULL); 01914 if (conf->users - 1 == 1) { 01915 if (!ast_streamfile(chan, "conf-userwilljoin", chan->language)) 01916 ast_waitstream(chan, ""); 01917 } else { 01918 if (!ast_streamfile(chan, "conf-userswilljoin", chan->language)) 01919 ast_waitstream(chan, ""); 01920 } 01921 } 01922 if (conf->users == 1 && ! (confflags & CONFFLAG_MARKEDUSER)) 01923 if (!ast_streamfile(chan, "conf-onlyperson", chan->language)) 01924 ast_waitstream(chan, ""); 01925 } 01926 01927 /* Update the struct with the actual confflags */ 01928 user->userflags = confflags; 01929 01930 if (confflags & CONFFLAG_WAITMARKED) { 01931 if(currentmarked == 0) { 01932 if (lastmarked != 0) { 01933 if (!(confflags & CONFFLAG_QUIET)) 01934 if (!ast_streamfile(chan, "conf-leaderhasleft", chan->language)) 01935 ast_waitstream(chan, ""); 01936 if(confflags & CONFFLAG_MARKEDEXIT) 01937 break; 01938 else { 01939 ztc.confmode = DAHDI_CONF_CONF; 01940 if (ioctl(fd, DAHDI_SETCONF, &ztc)) { 01941 ast_log(LOG_WARNING, "Error setting conference\n"); 01942 close(fd); 01943 goto outrun; 01944 } 01945 } 01946 } 01947 if (musiconhold == 0 && (confflags & CONFFLAG_MOH)) { 01948 ast_moh_start(chan, NULL, NULL); 01949 musiconhold = 1; 01950 } 01951 } else if(currentmarked >= 1 && lastmarked == 0) { 01952 /* Marked user entered, so cancel timeout */ 01953 timeout = 0; 01954 if (confflags & CONFFLAG_MONITOR) 01955 ztc.confmode = DAHDI_CONF_CONFMON | DAHDI_CONF_LISTENER; 01956 else if (confflags & CONFFLAG_TALKER) 01957 ztc.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER; 01958 else 01959 ztc.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER; 01960 if (ioctl(fd, DAHDI_SETCONF, &ztc)) { 01961 ast_log(LOG_WARNING, "Error setting conference\n"); 01962 close(fd); 01963 goto outrun; 01964 } 01965 if (musiconhold && (confflags & CONFFLAG_MOH)) { 01966 ast_moh_stop(chan); 01967 musiconhold = 0; 01968 } 01969 if ( !(confflags & CONFFLAG_QUIET) && !(confflags & CONFFLAG_MARKEDUSER)) { 01970 if (!ast_streamfile(chan, "conf-placeintoconf", chan->language)) 01971 ast_waitstream(chan, ""); 01972 conf_play(chan, conf, ENTER); 01973 } 01974 } 01975 } 01976 01977 /* trying to add moh for single person conf */ 01978 if ((confflags & CONFFLAG_MOH) && !(confflags & CONFFLAG_WAITMARKED)) { 01979 if (conf->users == 1) { 01980 if (musiconhold == 0) { 01981 ast_moh_start(chan, NULL, NULL); 01982 musiconhold = 1; 01983 } 01984 } else { 01985 if (musiconhold) { 01986 ast_moh_stop(chan); 01987 musiconhold = 0; 01988 } 01989 } 01990 } 01991 01992 /* Leave if the last marked user left */ 01993 if (currentmarked == 0 && lastmarked != 0 && (confflags & CONFFLAG_MARKEDEXIT)) { 01994 ret = -1; 01995 break; 01996 } 01997 01998 /* Check if my modes have changed */ 01999 02000 /* If I should be muted but am still talker, mute me */ 02001 if ((user->adminflags & (ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED)) && (ztc.confmode & DAHDI_CONF_TALKER)) { 02002 ztc.confmode ^= DAHDI_CONF_TALKER; 02003 if (ioctl(fd, DAHDI_SETCONF, &ztc)) { 02004 ast_log(LOG_WARNING, "Error setting conference - Un/Mute \n"); 02005 ret = -1; 02006 break; 02007 } 02008 02009 manager_event(EVENT_FLAG_CALL, "MeetmeMute", 02010 "Channel: %s\r\n" 02011 "Uniqueid: %s\r\n" 02012 "Meetme: %s\r\n" 02013 "Usernum: %i\r\n" 02014 "Status: on\r\n", 02015 chan->name, chan->uniqueid, conf->confno, user->user_no); 02016 } 02017 02018 /* If I should be un-muted but am not talker, un-mute me */ 02019 if (!(user->adminflags & (ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED)) && !(confflags & CONFFLAG_MONITOR) && !(ztc.confmode & DAHDI_CONF_TALKER)) { 02020 ztc.confmode |= DAHDI_CONF_TALKER; 02021 if (ioctl(fd, DAHDI_SETCONF, &ztc)) { 02022 ast_log(LOG_WARNING, "Error setting conference - Un/Mute \n"); 02023 ret = -1; 02024 break; 02025 } 02026 02027 manager_event(EVENT_FLAG_CALL, "MeetmeMute", 02028 "Channel: %s\r\n" 02029 "Uniqueid: %s\r\n" 02030 "Meetme: %s\r\n" 02031 "Usernum: %i\r\n" 02032 "Status: off\r\n", 02033 chan->name, chan->uniqueid, conf->confno, user->user_no); 02034 } 02035 02036 /* If I have been kicked, exit the conference */ 02037 if (user->adminflags & ADMINFLAG_KICKME) { 02038 //You have been kicked. 02039 if (!(confflags & CONFFLAG_QUIET) && 02040 !ast_streamfile(chan, "conf-kicked", chan->language)) { 02041 ast_waitstream(chan, ""); 02042 } 02043 ret = 0; 02044 break; 02045 } 02046 02047 /* Perform an extra hangup check just in case */ 02048 if (ast_check_hangup(chan)) 02049 break; 02050 02051 c = ast_waitfor_nandfds(&chan, 1, &fd, nfds, NULL, &outfd, &ms); 02052 02053 if (c) { 02054 char dtmfstr[2] = ""; 02055 02056 if (c->fds[0] != origfd || (user->zapchannel && (c->audiohooks || c->monitor))) { 02057 if (using_pseudo) { 02058 /* Kill old pseudo */ 02059 close(fd); 02060 using_pseudo = 0; 02061 } 02062 ast_log(LOG_DEBUG, "Ooh, something swapped out under us, starting over\n"); 02063 retryzap = (strcasecmp(c->tech->type, dahdi_chan_name) || (c->audiohooks || c->monitor) ? 1 : 0); 02064 user->zapchannel = !retryzap; 02065 goto zapretry; 02066 } 02067 if ((confflags & CONFFLAG_MONITOR) || (user->adminflags & (ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED))) 02068 f = ast_read_noaudio(c); 02069 else 02070 f = ast_read(c); 02071 if (!f) 02072 break; 02073 if (f->frametype == AST_FRAME_DTMF) { 02074 dtmfstr[0] = f->subclass; 02075 dtmfstr[1] = '\0'; 02076 } 02077 02078 if ((f->frametype == AST_FRAME_VOICE) && (f->subclass == AST_FORMAT_SLINEAR)) { 02079 if (user->talk.actual) 02080 ast_frame_adjust_volume(f, user->talk.actual); 02081 02082 if (confflags & (CONFFLAG_MONITORTALKER | CONFFLAG_OPTIMIZETALKER)) { 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 02282 if (ioctl(fd, DAHDI_SETCONF, &ztc)) { 02283 ast_log(LOG_WARNING, "Error setting conference\n"); 02284 close(fd); 02285 ast_frfree(f); 02286 goto outrun; 02287 } 02288 02289 conf_flush(fd, chan); 02290 /* Since this option could absorb dtmf for the previous, we have to check this one last */ 02291 } else if ((f->frametype == AST_FRAME_DTMF) && (confflags & CONFFLAG_EXIT_CONTEXT) && ast_exists_extension(chan, exitcontext, dtmfstr, 1, "")) { 02292 if (confflags & CONFFLAG_PASS_DTMF) 02293 conf_queue_dtmf(conf, user, f); 02294 02295 if (!ast_goto_if_exists(chan, exitcontext, dtmfstr, 1)) { 02296 ast_log(LOG_DEBUG, "Got DTMF %c, goto context %s\n", dtmfstr[0], exitcontext); 02297 ret = 0; 02298 ast_frfree(f); 02299 break; 02300 } else if (option_debug > 1) 02301 ast_log(LOG_DEBUG, "Exit by single digit did not work in meetme. Extension '%s' does not exist in context '%s'\n", dtmfstr, exitcontext); 02302 } else if ((f->frametype == AST_FRAME_DTMF_BEGIN || f->frametype == AST_FRAME_DTMF_END) 02303 && confflags & CONFFLAG_PASS_DTMF) { 02304 conf_queue_dtmf(conf, user, f); 02305 } else if ((confflags & CONFFLAG_SLA_STATION) && f->frametype == AST_FRAME_CONTROL) { 02306 switch (f->subclass) { 02307 case AST_CONTROL_HOLD: 02308 sla_queue_event_conf(SLA_EVENT_HOLD, chan, conf); 02309 break; 02310 default: 02311 break; 02312 } 02313 } else if (f->frametype == AST_FRAME_NULL) { 02314 /* Ignore NULL frames. It is perfectly normal to get these if the person is muted. */ 02315 } else if (option_debug) { 02316 ast_log(LOG_DEBUG, 02317 "Got unrecognized frame on channel %s, f->frametype=%d,f->subclass=%d\n", 02318 chan->name, f->frametype, f->subclass); 02319 } 02320 ast_frfree(f); 02321 } else if (outfd > -1) { 02322 res = read(outfd, buf, CONF_SIZE); 02323 if (res > 0) { 02324 memset(&fr, 0, sizeof(fr)); 02325 fr.frametype = AST_FRAME_VOICE; 02326 fr.subclass = AST_FORMAT_SLINEAR; 02327 fr.datalen = res; 02328 fr.samples = res/2; 02329 fr.data = buf; 02330 fr.offset = AST_FRIENDLY_OFFSET; 02331 if (!user->listen.actual && 02332 ((confflags & CONFFLAG_MONITOR) || 02333 (user->adminflags & (ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED)) || 02334 (!user->talking && (confflags & CONFFLAG_OPTIMIZETALKER)) 02335 )) { 02336 int index; 02337 for (index=0;index<AST_FRAME_BITS;index++) 02338 if (chan->rawwriteformat & (1 << index)) 02339 break; 02340 if (index >= AST_FRAME_BITS) 02341 goto bailoutandtrynormal; 02342 ast_mutex_lock(&conf->listenlock); 02343 if (!conf->transframe[index]) { 02344 if (conf->origframe) { 02345 if (!conf->transpath[index]) 02346 conf->transpath[index] = ast_translator_build_path((1 << index), AST_FORMAT_SLINEAR); 02347 if (conf->transpath[index]) { 02348 conf->transframe[index] = ast_translate(conf->transpath[index], conf->origframe, 0); 02349 if (!conf->transframe[index]) 02350 conf->transframe[index] = &ast_null_frame; 02351 } 02352 } 02353 } 02354 if (conf->transframe[index]) { 02355 if ((conf->transframe[index]->frametype != AST_FRAME_NULL) && 02356 can_write(chan, confflags)) { 02357 struct ast_frame *cur; 02358 if (musiconhold && !ast_dsp_silence(dsp, conf->transframe[index], &confsilence) && confsilence < MEETME_DELAYDETECTTALK) { 02359 ast_moh_stop(chan); 02360 mohtempstopped = 1; 02361 } 02362 02363 /* the translator may have returned a list of frames, so 02364 write each one onto the channel 02365 */ 02366 for (cur = conf->transframe[index]; cur; cur = AST_LIST_NEXT(cur, frame_list)) { 02367 if (ast_write(chan, cur)) { 02368 ast_log(LOG_WARNING, "Unable to write frame to channel %s\n", chan->name); 02369 break; 02370 } 02371 } 02372 if (musiconhold && mohtempstopped && confsilence > MEETME_DELAYDETECTENDTALK) { 02373 mohtempstopped = 0; 02374 ast_moh_start(chan, NULL, NULL); 02375 } 02376 } 02377 } else { 02378 ast_mutex_unlock(&conf->listenlock); 02379 goto bailoutandtrynormal; 02380 } 02381 ast_mutex_unlock(&conf->listenlock); 02382 } else { 02383 bailoutandtrynormal: 02384 if (musiconhold && !ast_dsp_silence(dsp, &fr, &confsilence) && confsilence < MEETME_DELAYDETECTTALK) { 02385 ast_moh_stop(chan); 02386 mohtempstopped = 1; 02387 } 02388 if (user->listen.actual) 02389 ast_frame_adjust_volume(&fr, user->listen.actual); 02390 if (can_write(chan, confflags) && ast_write(chan, &fr) < 0) { 02391 ast_log(LOG_WARNING, "Unable to write frame to channel %s\n", chan->name); 02392 } 02393 if (musiconhold && mohtempstopped && confsilence > MEETME_DELAYDETECTENDTALK) { 02394 mohtempstopped = 0; 02395 ast_moh_start(chan, NULL, NULL); 02396 } 02397 } 02398 } else 02399 ast_log(LOG_WARNING, "Failed to read frame: %s\n", strerror(errno)); 02400 } 02401 lastmarked = currentmarked; 02402 } 02403 } 02404 02405 if (musiconhold) { 02406 ast_moh_stop(chan); 02407 } 02408 02409 if (using_pseudo) 02410 close(fd); 02411 else { 02412 /* Take out of conference */ 02413 ztc.chan = 0; 02414 ztc.confno = 0; 02415 ztc.confmode = 0; 02416 if (ioctl(fd, DAHDI_SETCONF, &ztc)) { 02417 ast_log(LOG_WARNING, "Error setting conference\n"); 02418 } 02419 } 02420 02421 reset_volumes(user); 02422 02423 if (!(confflags & CONFFLAG_QUIET) && !(confflags & CONFFLAG_MONITOR) && !(confflags & CONFFLAG_ADMIN)) 02424 conf_play(chan, conf, LEAVE); 02425 02426 if (!(confflags & CONFFLAG_QUIET) && ((confflags & CONFFLAG_INTROUSER) || (confflags & CONFFLAG_INTROUSERNOREVIEW)) && conf->users > 1) { 02427 struct announce_listitem *item; 02428 if (!(item = ao2_alloc(sizeof(*item), NULL))) 02429 return -1; 02430 ast_copy_string(item->namerecloc, user->namerecloc, sizeof(item->namerecloc)); 02431 ast_copy_string(item->language, chan->language, sizeof(item->language)); 02432 item->confchan = conf->chan; 02433 item->confusers = conf->users; 02434 item->announcetype = CONF_HASLEFT; 02435 ast_mutex_lock(&conf->announcelistlock); 02436 AST_LIST_INSERT_TAIL(&conf->announcelist, item, entry); 02437 ast_cond_signal(&conf->announcelist_addition); 02438 ast_mutex_unlock(&conf->announcelistlock); 02439 } else if (!(confflags & CONFFLAG_QUIET) && ((confflags & CONFFLAG_INTROUSER) || (confflags & CONFFLAG_INTROUSERNOREVIEW)) && conf->users == 1) { 02440 /* Last person is leaving, so no reason to try and announce, but should delete the name recording */ 02441 ast_filedelete(user->namerecloc, NULL); 02442 } 02443 02444 outrun: 02445 AST_LIST_LOCK(&confs); 02446 02447 if (dsp) 02448 ast_dsp_free(dsp); 02449 02450 if (user->user_no) { /* Only cleanup users who really joined! */ 02451 now = time(NULL); 02452 hr = (now - user->jointime) / 3600; 02453 min = ((now - user->jointime) % 3600) / 60; 02454 sec = (now - user->jointime) % 60; 02455 02456 if (sent_event) { 02457 manager_event(EVENT_FLAG_CALL, "MeetmeLeave", 02458 "Channel: %s\r\n" 02459 "Uniqueid: %s\r\n" 02460 "Meetme: %s\r\n" 02461 "Usernum: %d\r\n" 02462 "CallerIDnum: %s\r\n" 02463 "CallerIDname: %s\r\n" 02464 "Duration: %ld\r\n", 02465 chan->name, chan->uniqueid, conf->confno, 02466 user->user_no, 02467 S_OR(user->chan->cid.cid_num, "<unknown>"), 02468 S_OR(user->chan->cid.cid_name, "<unknown>"), 02469 (long)(now - user->jointime)); 02470 } 02471 02472 if (setusercount) { 02473 conf->users--; 02474 /* Update table */ 02475 snprintf(members, sizeof(members), "%d", conf->users); 02476 ast_update_realtime("meetme", "confno", conf->confno, "members", members, NULL); 02477 if (confflags & CONFFLAG_MARKEDUSER) 02478 conf->markedusers--; 02479 } 02480 /* Remove ourselves from the list */ 02481 AST_LIST_REMOVE(&conf->userlist, user, list); 02482 02483 /* Change any states */ 02484 if (!conf->users) 02485 ast_device_state_changed("meetme:%s", conf->confno); 02486 02487 /* Return the number of seconds the user was in the conf */ 02488 snprintf(meetmesecs, sizeof(meetmesecs), "%d", (int) (time(NULL) - user->jointime)); 02489 pbx_builtin_setvar_helper(chan, "MEETMESECS", meetmesecs); 02490 } 02491 free(user); 02492 AST_LIST_UNLOCK(&confs); 02493 02494 return ret; 02495 }
static int count_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
The MeetmeCount application.
Definition at line 2649 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().
02650 { 02651 struct ast_module_user *u; 02652 int res = 0; 02653 struct ast_conference *conf; 02654 int count; 02655 char *localdata; 02656 char val[80] = "0"; 02657 AST_DECLARE_APP_ARGS(args, 02658 AST_APP_ARG(confno); 02659 AST_APP_ARG(varname); 02660 ); 02661 02662 if (ast_strlen_zero(data)) { 02663 ast_log(LOG_WARNING, "MeetMeCount requires an argument (conference number)\n"); 02664 return -1; 02665 } 02666 02667 u = ast_module_user_add(chan); 02668 02669 if (!(localdata = ast_strdupa(data))) { 02670 ast_module_user_remove(u); 02671 return -1; 02672 } 02673 02674 AST_STANDARD_APP_ARGS(args, localdata); 02675 02676 conf = find_conf(chan, args.confno, 0, 0, NULL, 0, 1, NULL); 02677 02678 if (conf) { 02679 count = conf->users; 02680 dispose_conf(conf); 02681 conf = NULL; 02682 } else 02683 count = 0; 02684 02685 if (!ast_strlen_zero(args.varname)){ 02686 /* have var so load it and exit */ 02687 snprintf(val, sizeof(val), "%d",count); 02688 pbx_builtin_setvar_helper(chan, args.varname, val); 02689 } else { 02690 if (chan->_state != AST_STATE_UP) 02691 ast_answer(chan); 02692 res = ast_say_number(chan, count, "", chan->language, (char *) NULL); /* Needs gender */ 02693 } 02694 ast_module_user_remove(u); 02695 02696 return res; 02697 }
static struct sla_trunk_ref* create_trunk_ref | ( | struct sla_trunk * | trunk | ) | [static] |
Definition at line 4473 of file app_meetme.c.
References ast_calloc, and sla_trunk_ref::trunk.
Referenced by sla_add_trunk_to_station().
04474 { 04475 struct sla_trunk_ref *trunk_ref; 04476 04477 if (!(trunk_ref = ast_calloc(1, sizeof(*trunk_ref)))) 04478 return NULL; 04479 04480 trunk_ref->trunk = trunk; 04481 04482 return trunk_ref; 04483 }
static void destroy_station | ( | struct sla_station * | station | ) | [static] |
Definition at line 4641 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().
04642 { 04643 struct sla_trunk_ref *trunk_ref; 04644 04645 if (!ast_strlen_zero(station->autocontext)) { 04646 AST_RWLIST_RDLOCK(&sla_trunks); 04647 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) { 04648 char exten[AST_MAX_EXTENSION]; 04649 char hint[AST_MAX_APP]; 04650 snprintf(exten, sizeof(exten), "%s_%s", station->name, trunk_ref->trunk->name); 04651 snprintf(hint, sizeof(hint), "SLA:%s", exten); 04652 ast_context_remove_extension(station->autocontext, exten, 04653 1, sla_registrar); 04654 ast_context_remove_extension(station->autocontext, hint, 04655 PRIORITY_HINT, sla_registrar); 04656 } 04657 AST_RWLIST_UNLOCK(&sla_trunks); 04658 } 04659 04660 while ((trunk_ref = AST_LIST_REMOVE_HEAD(&station->trunks, entry))) 04661 free(trunk_ref); 04662 04663 ast_string_field_free_memory(station); 04664 free(station); 04665 }
static void destroy_trunk | ( | struct sla_trunk * | trunk | ) | [static] |
Definition at line 4627 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().
04628 { 04629 struct sla_station_ref *station_ref; 04630 04631 if (!ast_strlen_zero(trunk->autocontext)) 04632 ast_context_remove_extension(trunk->autocontext, "s", 1, sla_registrar); 04633 04634 while ((station_ref = AST_LIST_REMOVE_HEAD(&trunk->stations, entry))) 04635 free(station_ref); 04636 04637 ast_string_field_free_memory(trunk); 04638 free(trunk); 04639 }
static void* dial_trunk | ( | void * | data | ) | [static] |
Definition at line 4192 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().
04193 { 04194 struct dial_trunk_args *args = data; 04195 struct ast_dial *dial; 04196 char *tech, *tech_data; 04197 enum ast_dial_result dial_res; 04198 char conf_name[MAX_CONFNUM]; 04199 struct ast_conference *conf; 04200 struct ast_flags conf_flags = { 0 }; 04201 struct sla_trunk_ref *trunk_ref = args->trunk_ref; 04202 const char *cid_name = NULL, *cid_num = NULL; 04203 04204 if (!(dial = ast_dial_create())) { 04205 ast_mutex_lock(args->cond_lock); 04206 ast_cond_signal(args->cond); 04207 ast_mutex_unlock(args->cond_lock); 04208 return NULL; 04209 } 04210 04211 tech_data = ast_strdupa(trunk_ref->trunk->device); 04212 tech = strsep(&tech_data, "/"); 04213 if (ast_dial_append(dial, tech, tech_data) == -1) { 04214 ast_mutex_lock(args->cond_lock); 04215 ast_cond_signal(args->cond); 04216 ast_mutex_unlock(args->cond_lock); 04217 ast_dial_destroy(dial); 04218 return NULL; 04219 } 04220 04221 if (!sla.attempt_callerid && !ast_strlen_zero(trunk_ref->chan->cid.cid_name)) { 04222 cid_name = ast_strdupa(trunk_ref->chan->cid.cid_name); 04223 free(trunk_ref->chan->cid.cid_name); 04224 trunk_ref->chan->cid.cid_name = NULL; 04225 } 04226 if (!sla.attempt_callerid && !ast_strlen_zero(trunk_ref->chan->cid.cid_num)) { 04227 cid_num = ast_strdupa(trunk_ref->chan->cid.cid_num); 04228 free(trunk_ref->chan->cid.cid_num); 04229 trunk_ref->chan->cid.cid_num = NULL; 04230 } 04231 04232 dial_res = ast_dial_run(dial, trunk_ref->chan, 1); 04233 04234 if (cid_name) 04235 trunk_ref->chan->cid.cid_name = ast_strdup(cid_name); 04236 if (cid_num) 04237 trunk_ref->chan->cid.cid_num = ast_strdup(cid_num); 04238 04239 if (dial_res != AST_DIAL_RESULT_TRYING) { 04240 ast_mutex_lock(args->cond_lock); 04241 ast_cond_signal(args->cond); 04242 ast_mutex_unlock(args->cond_lock); 04243 ast_dial_destroy(dial); 04244 return NULL; 04245 } 04246 04247 for (;;) { 04248 unsigned int done = 0; 04249 switch ((dial_res = ast_dial_state(dial))) { 04250 case AST_DIAL_RESULT_ANSWERED: 04251 trunk_ref->trunk->chan = ast_dial_answered(dial); 04252 case AST_DIAL_RESULT_HANGUP: 04253 case AST_DIAL_RESULT_INVALID: 04254 case AST_DIAL_RESULT_FAILED: 04255 case AST_DIAL_RESULT_TIMEOUT: 04256 case AST_DIAL_RESULT_UNANSWERED: 04257 done = 1; 04258 case AST_DIAL_RESULT_TRYING: 04259 case AST_DIAL_RESULT_RINGING: 04260 case AST_DIAL_RESULT_PROGRESS: 04261 case AST_DIAL_RESULT_PROCEEDING: 04262 break; 04263 } 04264 if (done) 04265 break; 04266 } 04267 04268 if (!trunk_ref->trunk->chan) { 04269 ast_mutex_lock(args->cond_lock); 04270 ast_cond_signal(args->cond); 04271 ast_mutex_unlock(args->cond_lock); 04272 ast_dial_join(dial); 04273 ast_dial_destroy(dial); 04274 return NULL; 04275 } 04276 04277 snprintf(conf_name, sizeof(conf_name), "SLA_%s", trunk_ref->trunk->name); 04278 ast_set_flag(&conf_flags, 04279 CONFFLAG_QUIET | CONFFLAG_MARKEDEXIT | CONFFLAG_MARKEDUSER | 04280 CONFFLAG_PASS_DTMF | CONFFLAG_SLA_TRUNK); 04281 conf = build_conf(conf_name, "", "", 1, 1, 1); 04282 04283 ast_mutex_lock(args->cond_lock); 04284 ast_cond_signal(args->cond); 04285 ast_mutex_unlock(args->cond_lock); 04286 04287 if (conf) { 04288 conf_run(trunk_ref->trunk->chan, conf, conf_flags.flags, NULL); 04289 dispose_conf(conf); 04290 conf = NULL; 04291 } 04292 04293 /* If the trunk is going away, it is definitely now IDLE. */ 04294 sla_change_trunk_state(trunk_ref->trunk, SLA_TRUNK_STATE_IDLE, ALL_TRUNK_REFS, NULL); 04295 04296 trunk_ref->trunk->chan = NULL; 04297 trunk_ref->trunk->on_hold = 0; 04298 04299 ast_dial_join(dial); 04300 ast_dial_destroy(dial); 04301 04302 return NULL; 04303 }
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 2555 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().
02557 { 02558 struct ast_config *cfg; 02559 struct ast_variable *var; 02560 struct ast_conference *cnf; 02561 char *parse; 02562 AST_DECLARE_APP_ARGS(args, 02563 AST_APP_ARG(confno); 02564 AST_APP_ARG(pin); 02565 AST_APP_ARG(pinadmin); 02566 ); 02567 02568 /* Check first in the conference list */ 02569 AST_LIST_LOCK(&confs); 02570 AST_LIST_TRAVERSE(&confs, cnf, list) { 02571 if (!strcmp(confno, cnf->confno)) 02572 break; 02573 } 02574 if (cnf){ 02575 cnf->refcount += refcount; 02576 } 02577 AST_LIST_UNLOCK(&confs); 02578 02579 if (!cnf) { 02580 if (dynamic) { 02581 /* No need to parse meetme.conf */ 02582 ast_log(LOG_DEBUG, "Building dynamic conference '%s'\n", confno); 02583 if (dynamic_pin) { 02584 if (dynamic_pin[0] == 'q') { 02585 /* Query the user to enter a PIN */ 02586 if (ast_app_getdata(chan, "conf-getpin", dynamic_pin, pin_buf_len - 1, 0) < 0) 02587 return NULL; 02588 } 02589 cnf = build_conf(confno, dynamic_pin, "", make, dynamic, refcount); 02590 } else { 02591 cnf = build_conf(confno, "", "", make, dynamic, refcount); 02592 } 02593 } else { 02594 /* Check the config */ 02595 cfg = ast_config_load(CONFIG_FILE_NAME); 02596 if (!cfg) { 02597 ast_log(LOG_WARNING, "No %s file :(\n", CONFIG_FILE_NAME); 02598 return NULL; 02599 } 02600 for (var = ast_variable_browse(cfg, "rooms"); var; var = var->next) { 02601 if (strcasecmp(var->name, "conf")) 02602 continue; 02603 02604 if (!(parse = ast_strdupa(var->value))) 02605 return NULL; 02606 02607 AST_NONSTANDARD_APP_ARGS(args, parse, ','); 02608 if (!strcasecmp(args.confno, confno)) { 02609 /* Bingo it's a valid conference */ 02610 cnf = build_conf(args.confno, 02611 S_OR(args.pin, ""), 02612 S_OR(args.pinadmin, ""), 02613 make, dynamic, refcount); 02614 break; 02615 } 02616 } 02617 if (!var) { 02618 ast_log(LOG_DEBUG, "%s isn't a valid conference\n", confno); 02619 } 02620 ast_config_destroy(cfg); 02621 } 02622 } else if (dynamic_pin) { 02623 /* Correct for the user selecting 'D' instead of 'd' to have 02624 someone join into a conference that has already been created 02625 with a pin. */ 02626 if (dynamic_pin[0] == 'q') 02627 dynamic_pin[0] = '\0'; 02628 } 02629 02630 if (cnf) { 02631 if (confflags && !cnf->chan && 02632 !ast_test_flag(confflags, CONFFLAG_QUIET) && 02633 ast_test_flag(confflags, CONFFLAG_INTROUSER | CONFFLAG_INTROUSERNOREVIEW)) { 02634 ast_log(LOG_WARNING, "No %s channel available for conference, user introduction disabled\n", dahdi_chan_name); 02635 ast_clear_flag(confflags, CONFFLAG_INTROUSER | CONFFLAG_INTROUSERNOREVIEW); 02636 } 02637 02638 if (confflags && !cnf->chan && 02639 ast_test_flag(confflags, CONFFLAG_RECORDCONF)) { 02640 ast_log(LOG_WARNING, "No %s channel available for conference, conference recording disabled\n", dahdi_chan_name); 02641 ast_clear_flag(confflags, CONFFLAG_RECORDCONF); 02642 } 02643 } 02644 02645 return cnf; 02646 }
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 2497 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().
02499 { 02500 struct ast_variable *var, *save; 02501 struct ast_conference *cnf; 02502 02503 /* Check first in the conference list */ 02504 AST_LIST_LOCK(&confs); 02505 AST_LIST_TRAVERSE(&confs, cnf, list) { 02506 if (!strcmp(confno, cnf->confno)) 02507 break; 02508 } 02509 if (cnf) { 02510 cnf->refcount += refcount; 02511 } 02512 AST_LIST_UNLOCK(&confs); 02513 02514 if (!cnf) { 02515 char *pin = NULL, *pinadmin = NULL; /* For temp use */ 02516 02517 var = ast_load_realtime("meetme", "confno", confno, NULL); 02518 02519 if (!var) 02520 return NULL; 02521 02522 save = var; 02523 while (var) { 02524 if (!strcasecmp(var->name, "pin")) { 02525 pin = ast_strdupa(var->value); 02526 } else if (!strcasecmp(var->name, "adminpin")) { 02527 pinadmin = ast_strdupa(var->value); 02528 } 02529 var = var->next; 02530 } 02531 ast_variables_destroy(save); 02532 02533 cnf = build_conf(confno, pin ? pin : "", pinadmin ? pinadmin : "", make, dynamic, refcount); 02534 } 02535 02536 if (cnf) { 02537 if (confflags && !cnf->chan && 02538 !ast_test_flag(confflags, CONFFLAG_QUIET) && 02539 ast_test_flag(confflags, CONFFLAG_INTROUSER | CONFFLAG_INTROUSERNOREVIEW)) { 02540 ast_log(LOG_WARNING, "No %s channel available for conference, user introduction disabled\n", dahdi_chan_name); 02541 ast_clear_flag(confflags, CONFFLAG_INTROUSER | CONFFLAG_INTROUSERNOREVIEW); 02542 } 02543 02544 if (confflags && !cnf->chan && 02545 ast_test_flag(confflags, CONFFLAG_RECORDCONF)) { 02546 ast_log(LOG_WARNING, "No %s channel available for conference, conference recording disabled\n", dahdi_chan_name); 02547 ast_clear_flag(confflags, CONFFLAG_RECORDCONF); 02548 } 02549 } 02550 02551 return cnf; 02552 }
static struct ast_conf_user* find_user | ( | struct ast_conference * | conf, | |
char * | callerident | |||
) | [static] |
Definition at line 2946 of file app_meetme.c.
References AST_LIST_TRAVERSE, ast_conf_user::list, ast_conf_user::user_no, and ast_conference::userlist.
02947 { 02948 struct ast_conf_user *user = NULL; 02949 int cid; 02950 02951 sscanf(callerident, "%30i", &cid); 02952 if (conf && callerident) { 02953 AST_LIST_TRAVERSE(&conf->userlist, user, list) { 02954 if (cid == user->user_no) 02955 return user; 02956 } 02957 } 02958 return NULL; 02959 }
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 4996 of file app_meetme.c.
References load_config_meetme(), and sla_load_config().
04997 { 04998 int res = 0; 04999 05000 load_config_meetme(); 05001 if (!reload) 05002 res = sla_load_config(); 05003 05004 return res; 05005 }
static void load_config_meetme | ( | void | ) | [static] |
Definition at line 3274 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().
03275 { 03276 struct ast_config *cfg; 03277 const char *val; 03278 03279 audio_buffers = DEFAULT_AUDIO_BUFFERS; 03280 03281 if (!(cfg = ast_config_load(CONFIG_FILE_NAME))) 03282 return; 03283 03284 if ((val = ast_variable_retrieve(cfg, "general", "audiobuffers"))) { 03285 if ((sscanf(val, "%30d", &audio_buffers) != 1)) { 03286 ast_log(LOG_WARNING, "audiobuffers setting must be a number, not '%s'\n", val); 03287 audio_buffers = DEFAULT_AUDIO_BUFFERS; 03288 } else if ((audio_buffers < DAHDI_DEFAULT_NUM_BUFS) || (audio_buffers > DAHDI_MAX_NUM_BUFS)) { 03289 ast_log(LOG_WARNING, "audiobuffers setting must be between %d and %d\n", 03290 DAHDI_DEFAULT_NUM_BUFS, DAHDI_MAX_NUM_BUFS); 03291 audio_buffers = DEFAULT_AUDIO_BUFFERS; 03292 } 03293 if (audio_buffers != DEFAULT_AUDIO_BUFFERS) 03294 ast_log(LOG_NOTICE, "Audio buffers per channel set to %d\n", audio_buffers); 03295 } 03296 03297 ast_config_destroy(cfg); 03298 }
static int load_module | ( | void | ) | [static] |
Definition at line 5030 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().
05031 { 05032 int res = 0; 05033 05034 res |= load_config(0); 05035 05036 ast_cli_register_multiple(cli_meetme, ARRAY_LEN(cli_meetme)); 05037 res |= ast_manager_register("MeetmeMute", EVENT_FLAG_CALL, 05038 action_meetmemute, "Mute a Meetme user"); 05039 res |= ast_manager_register("MeetmeUnmute", EVENT_FLAG_CALL, 05040 action_meetmeunmute, "Unmute a Meetme user"); 05041 res |= ast_register_application(app3, admin_exec, synopsis3, descrip3); 05042 res |= ast_register_application(app2, count_exec, synopsis2, descrip2); 05043 res |= ast_register_application(app, conf_exec, synopsis, descrip); 05044 res |= ast_register_application(slastation_app, sla_station_exec, 05045 slastation_synopsis, slastation_desc); 05046 res |= ast_register_application(slatrunk_app, sla_trunk_exec, 05047 slatrunk_synopsis, slatrunk_desc); 05048 05049 res |= ast_devstate_prov_add("Meetme", meetmestate); 05050 res |= ast_devstate_prov_add("SLA", sla_state); 05051 05052 return res; 05053 }
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 3116 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().
03117 { 03118 struct ast_conference *conf; 03119 struct ast_conf_user *user; 03120 const char *confid = astman_get_header(m, "Meetme"); 03121 char *userid = ast_strdupa(astman_get_header(m, "Usernum")); 03122 int userno; 03123 03124 if (ast_strlen_zero(confid)) { 03125 astman_send_error(s, m, "Meetme conference not specified"); 03126 return 0; 03127 } 03128 03129 if (ast_strlen_zero(userid)) { 03130 astman_send_error(s, m, "Meetme user number not specified"); 03131 return 0; 03132 } 03133 03134 userno = strtoul(userid, &userid, 10); 03135 03136 if (*userid) { 03137 astman_send_error(s, m, "Invalid user number"); 03138 return 0; 03139 } 03140 03141 /* Look in the conference list */ 03142 AST_LIST_LOCK(&confs); 03143 AST_LIST_TRAVERSE(&confs, conf, list) { 03144 if (!strcmp(confid, conf->confno)) 03145 break; 03146 } 03147 03148 if (!conf) { 03149 AST_LIST_UNLOCK(&confs); 03150 astman_send_error(s, m, "Meetme conference does not exist"); 03151 return 0; 03152 } 03153 03154 AST_LIST_TRAVERSE(&conf->userlist, user, list) 03155 if (user->user_no == userno) 03156 break; 03157 03158 if (!user) { 03159 AST_LIST_UNLOCK(&confs); 03160 astman_send_error(s, m, "User number not found"); 03161 return 0; 03162 } 03163 03164 if (mute) 03165 user->adminflags |= ADMINFLAG_MUTED; /* request user muting */ 03166 else 03167 user->adminflags &= ~(ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED); /* request user unmuting */ 03168 03169 AST_LIST_UNLOCK(&confs); 03170 03171 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); 03172 03173 astman_send_ack(s, m, mute ? "User muted" : "User unmuted"); 03174 return 0; 03175 }
static int meetmestate | ( | const char * | data | ) | [static] |
Callback for devicestate providers.
Definition at line 3252 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().
03253 { 03254 struct ast_conference *conf; 03255 03256 /* Find conference */ 03257 AST_LIST_LOCK(&confs); 03258 AST_LIST_TRAVERSE(&confs, conf, list) { 03259 if (!strcmp(data, conf->confno)) 03260 break; 03261 } 03262 AST_LIST_UNLOCK(&confs); 03263 if (!conf) 03264 return AST_DEVICE_INVALID; 03265 03266 03267 /* SKREP to fill */ 03268 if (!conf->users) 03269 return AST_DEVICE_NOT_INUSE; 03270 03271 return AST_DEVICE_INUSE; 03272 }
static struct sla_ringing_trunk* queue_ringing_trunk | ( | struct sla_trunk * | trunk | ) | [static] |
Definition at line 4485 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().
04486 { 04487 struct sla_ringing_trunk *ringing_trunk; 04488 04489 if (!(ringing_trunk = ast_calloc(1, sizeof(*ringing_trunk)))) 04490 return NULL; 04491 04492 ringing_trunk->trunk = trunk; 04493 ringing_trunk->ring_begin = ast_tvnow(); 04494 04495 sla_change_trunk_state(trunk, SLA_TRUNK_STATE_RINGING, ALL_TRUNK_REFS, NULL); 04496 04497 ast_mutex_lock(&sla.lock); 04498 AST_LIST_INSERT_HEAD(&sla.ringing_trunks, ringing_trunk, entry); 04499 ast_mutex_unlock(&sla.lock); 04500 04501 sla_queue_event(SLA_EVENT_RINGING_TRUNK); 04502 04503 return ringing_trunk; 04504 }
static void * recordthread | ( | void * | args | ) | [static] |
Definition at line 3187 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.
03188 { 03189 struct ast_conference *cnf = args; 03190 struct ast_frame *f=NULL; 03191 int flags; 03192 struct ast_filestream *s=NULL; 03193 int res=0; 03194 int x; 03195 const char *oldrecordingfilename = NULL; 03196 03197 if (!cnf || !cnf->lchan) { 03198 pthread_exit(0); 03199 } 03200 03201 ast_stopstream(cnf->lchan); 03202 flags = O_CREAT|O_TRUNC|O_WRONLY; 03203 03204 03205 cnf->recording = MEETME_RECORD_ACTIVE; 03206 while (ast_waitfor(cnf->lchan, -1) > -1) { 03207 if (cnf->recording == MEETME_RECORD_TERMINATE) { 03208 AST_LIST_LOCK(&confs); 03209 AST_LIST_UNLOCK(&confs); 03210 break; 03211 } 03212 if (!s && cnf->recordingfilename && (cnf->recordingfilename != oldrecordingfilename)) { 03213 s = ast_writefile(cnf->recordingfilename, cnf->recordingformat, NULL, flags, 0, 0644); 03214 oldrecordingfilename = cnf->recordingfilename; 03215 } 03216 03217 f = ast_read(cnf->lchan); 03218 if (!f) { 03219 res = -1; 03220 break; 03221 } 03222 if (f->frametype == AST_FRAME_VOICE) { 03223 ast_mutex_lock(&cnf->listenlock); 03224 for (x=0;x<AST_FRAME_BITS;x++) { 03225 /* Free any translations that have occured */ 03226 if (cnf->transframe[x]) { 03227 ast_frfree(cnf->transframe[x]); 03228 cnf->transframe[x] = NULL; 03229 } 03230 } 03231 if (cnf->origframe) 03232 ast_frfree(cnf->origframe); 03233 cnf->origframe = ast_frdup(f); 03234 ast_mutex_unlock(&cnf->listenlock); 03235 if (s) 03236 res = ast_writestream(s, f); 03237 if (res) { 03238 ast_frfree(f); 03239 break; 03240 } 03241 } 03242 ast_frfree(f); 03243 } 03244 cnf->recording = MEETME_RECORD_OFF; 03245 if (s) 03246 ast_closestream(s); 03247 03248 pthread_exit(0); 03249 }
static int reload | ( | void | ) | [static] |
Definition at line 5055 of file app_meetme.c.
References load_config().
05056 { 05057 return load_config(1); 05058 }
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 3439 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().
03440 { 03441 struct sla_station *station; 03442 struct sla_trunk_ref *trunk_ref; 03443 char conf_name[MAX_CONFNUM]; 03444 struct ast_flags conf_flags = { 0 }; 03445 struct ast_conference *conf; 03446 03447 { 03448 struct run_station_args *args = data; 03449 station = args->station; 03450 trunk_ref = args->trunk_ref; 03451 ast_mutex_lock(args->cond_lock); 03452 ast_cond_signal(args->cond); 03453 ast_mutex_unlock(args->cond_lock); 03454 /* args is no longer valid here. */ 03455 } 03456 03457 ast_atomic_fetchadd_int((int *) &trunk_ref->trunk->active_stations, 1); 03458 snprintf(conf_name, sizeof(conf_name), "SLA_%s", trunk_ref->trunk->name); 03459 ast_set_flag(&conf_flags, 03460 CONFFLAG_QUIET | CONFFLAG_MARKEDEXIT | CONFFLAG_PASS_DTMF | CONFFLAG_SLA_STATION); 03461 answer_trunk_chan(trunk_ref->chan); 03462 conf = build_conf(conf_name, "", "", 0, 0, 1); 03463 if (conf) { 03464 conf_run(trunk_ref->chan, conf, conf_flags.flags, NULL); 03465 dispose_conf(conf); 03466 conf = NULL; 03467 } 03468 trunk_ref->chan = NULL; 03469 if (ast_atomic_dec_and_test((int *) &trunk_ref->trunk->active_stations) && 03470 trunk_ref->state != SLA_TRUNK_STATE_ONHOLD_BYME) { 03471 strncat(conf_name, "|K", sizeof(conf_name) - strlen(conf_name) - 1); 03472 admin_exec(NULL, conf_name); 03473 trunk_ref->trunk->hold_stations = 0; 03474 sla_change_trunk_state(trunk_ref->trunk, SLA_TRUNK_STATE_IDLE, ALL_TRUNK_REFS, NULL); 03475 } 03476 03477 ast_dial_join(station->dial); 03478 ast_dial_destroy(station->dial); 03479 station->dial = NULL; 03480 03481 return NULL; 03482 }
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 4788 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().
04789 { 04790 struct sla_trunk *trunk; 04791 struct sla_trunk_ref *trunk_ref; 04792 struct sla_station_ref *station_ref; 04793 char *trunk_name, *options, *cur; 04794 04795 options = ast_strdupa(var->value); 04796 trunk_name = strsep(&options, ","); 04797 04798 AST_RWLIST_RDLOCK(&sla_trunks); 04799 AST_RWLIST_TRAVERSE(&sla_trunks, trunk, entry) { 04800 if (!strcasecmp(trunk->name, trunk_name)) 04801 break; 04802 } 04803 04804 AST_RWLIST_UNLOCK(&sla_trunks); 04805 if (!trunk) { 04806 ast_log(LOG_ERROR, "Trunk '%s' not found!\n", var->value); 04807 return; 04808 } 04809 if (!(trunk_ref = create_trunk_ref(trunk))) 04810 return; 04811 trunk_ref->state = SLA_TRUNK_STATE_IDLE; 04812 04813 while ((cur = strsep(&options, ","))) { 04814 char *name, *value = cur; 04815 name = strsep(&value, "="); 04816 if (!strcasecmp(name, "ringtimeout")) { 04817 if (sscanf(value, "%30u", &trunk_ref->ring_timeout) != 1) { 04818 ast_log(LOG_WARNING, "Invalid ringtimeout value '%s' for " 04819 "trunk '%s' on station '%s'\n", value, trunk->name, station->name); 04820 trunk_ref->ring_timeout = 0; 04821 } 04822 } else if (!strcasecmp(name, "ringdelay")) { 04823 if (sscanf(value, "%30u", &trunk_ref->ring_delay) != 1) { 04824 ast_log(LOG_WARNING, "Invalid ringdelay value '%s' for " 04825 "trunk '%s' on station '%s'\n", value, trunk->name, station->name); 04826 trunk_ref->ring_delay = 0; 04827 } 04828 } else { 04829 ast_log(LOG_WARNING, "Invalid option '%s' for " 04830 "trunk '%s' on station '%s'\n", name, trunk->name, station->name); 04831 } 04832 } 04833 04834 if (!(station_ref = sla_create_station_ref(station))) { 04835 free(trunk_ref); 04836 return; 04837 } 04838 ast_atomic_fetchadd_int((int *) &trunk->num_stations, 1); 04839 AST_RWLIST_WRLOCK(&sla_trunks); 04840 AST_LIST_INSERT_TAIL(&trunk->stations, station_ref, entry); 04841 AST_RWLIST_UNLOCK(&sla_trunks); 04842 AST_LIST_INSERT_TAIL(&station->trunks, trunk_ref, entry); 04843 }
static int sla_build_station | ( | struct ast_config * | cfg, | |
const char * | cat | |||
) | [static] |
Definition at line 4845 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().
04846 { 04847 struct sla_station *station; 04848 struct ast_variable *var; 04849 const char *dev; 04850 04851 if (!(dev = ast_variable_retrieve(cfg, cat, "device"))) { 04852 ast_log(LOG_ERROR, "SLA Station '%s' defined with no device!\n", cat); 04853 return -1; 04854 } 04855 04856 if (!(station = ast_calloc(1, sizeof(*station)))) 04857 return -1; 04858 if (ast_string_field_init(station, 32)) { 04859 free(station); 04860 return -1; 04861 } 04862 04863 ast_string_field_set(station, name, cat); 04864 ast_string_field_set(station, device, dev); 04865 04866 for (var = ast_variable_browse(cfg, cat); var; var = var->next) { 04867 if (!strcasecmp(var->name, "trunk")) 04868 sla_add_trunk_to_station(station, var); 04869 else if (!strcasecmp(var->name, "autocontext")) 04870 ast_string_field_set(station, autocontext, var->value); 04871 else if (!strcasecmp(var->name, "ringtimeout")) { 04872 if (sscanf(var->value, "%30u", &station->ring_timeout) != 1) { 04873 ast_log(LOG_WARNING, "Invalid ringtimeout '%s' specified for station '%s'\n", 04874 var->value, station->name); 04875 station->ring_timeout = 0; 04876 } 04877 } else if (!strcasecmp(var->name, "ringdelay")) { 04878 if (sscanf(var->value, "%30u", &station->ring_delay) != 1) { 04879 ast_log(LOG_WARNING, "Invalid ringdelay '%s' specified for station '%s'\n", 04880 var->value, station->name); 04881 station->ring_delay = 0; 04882 } 04883 } else if (!strcasecmp(var->name, "hold")) { 04884 if (!strcasecmp(var->value, "private")) 04885 station->hold_access = SLA_HOLD_PRIVATE; 04886 else if (!strcasecmp(var->value, "open")) 04887 station->hold_access = SLA_HOLD_OPEN; 04888 else { 04889 ast_log(LOG_WARNING, "Invalid value '%s' for hold on station %s\n", 04890 var->value, station->name); 04891 } 04892 04893 } else if (strcasecmp(var->name, "type") && strcasecmp(var->name, "device")) { 04894 ast_log(LOG_ERROR, "Invalid option '%s' specified at line %d of %s!\n", 04895 var->name, var->lineno, SLA_CONFIG_FILE); 04896 } 04897 } 04898 04899 if (!ast_strlen_zero(station->autocontext)) { 04900 struct ast_context *context; 04901 struct sla_trunk_ref *trunk_ref; 04902 context = ast_context_find_or_create(NULL, station->autocontext, sla_registrar); 04903 if (!context) { 04904 ast_log(LOG_ERROR, "Failed to automatically find or create " 04905 "context '%s' for SLA!\n", station->autocontext); 04906 destroy_station(station); 04907 return -1; 04908 } 04909 /* The extension for when the handset goes off-hook. 04910 * exten => station1,1,SLAStation(station1) */ 04911 if (ast_add_extension2(context, 0 /* don't replace */, station->name, 1, 04912 NULL, NULL, slastation_app, ast_strdup(station->name), ast_free_ptr, sla_registrar)) { 04913 ast_log(LOG_ERROR, "Failed to automatically create extension " 04914 "for trunk '%s'!\n", station->name); 04915 destroy_station(station); 04916 return -1; 04917 } 04918 AST_RWLIST_RDLOCK(&sla_trunks); 04919 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) { 04920 char exten[AST_MAX_EXTENSION]; 04921 char hint[AST_MAX_APP]; 04922 snprintf(exten, sizeof(exten), "%s_%s", station->name, trunk_ref->trunk->name); 04923 snprintf(hint, sizeof(hint), "SLA:%s", exten); 04924 /* Extension for this line button 04925 * exten => station1_line1,1,SLAStation(station1_line1) */ 04926 if (ast_add_extension2(context, 0 /* don't replace */, exten, 1, 04927 NULL, NULL, slastation_app, ast_strdup(exten), ast_free_ptr, sla_registrar)) { 04928 ast_log(LOG_ERROR, "Failed to automatically create extension " 04929 "for trunk '%s'!\n", station->name); 04930 destroy_station(station); 04931 return -1; 04932 } 04933 /* Hint for this line button 04934 * exten => station1_line1,hint,SLA:station1_line1 */ 04935 if (ast_add_extension2(context, 0 /* don't replace */, exten, PRIORITY_HINT, 04936 NULL, NULL, hint, NULL, NULL, sla_registrar)) { 04937 ast_log(LOG_ERROR, "Failed to automatically create hint " 04938 "for trunk '%s'!\n", station->name); 04939 destroy_station(station); 04940 return -1; 04941 } 04942 } 04943 AST_RWLIST_UNLOCK(&sla_trunks); 04944 } 04945 04946 AST_RWLIST_WRLOCK(&sla_stations); 04947 AST_RWLIST_INSERT_TAIL(&sla_stations, station, entry); 04948 AST_RWLIST_UNLOCK(&sla_stations); 04949 04950 return 0; 04951 }
static int sla_build_trunk | ( | struct ast_config * | cfg, | |
const char * | cat | |||
) | [static] |
Definition at line 4710 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().
04711 { 04712 struct sla_trunk *trunk; 04713 struct ast_variable *var; 04714 const char *dev; 04715 04716 if (!(dev = ast_variable_retrieve(cfg, cat, "device"))) { 04717 ast_log(LOG_ERROR, "SLA Trunk '%s' defined with no device!\n", cat); 04718 return -1; 04719 } 04720 04721 if (sla_check_device(dev)) { 04722 ast_log(LOG_ERROR, "SLA Trunk '%s' define with invalid device '%s'!\n", 04723 cat, dev); 04724 return -1; 04725 } 04726 04727 if (!(trunk = ast_calloc(1, sizeof(*trunk)))) 04728 return -1; 04729 if (ast_string_field_init(trunk, 32)) { 04730 free(trunk); 04731 return -1; 04732 } 04733 04734 ast_string_field_set(trunk, name, cat); 04735 ast_string_field_set(trunk, device, dev); 04736 04737 for (var = ast_variable_browse(cfg, cat); var; var = var->next) { 04738 if (!strcasecmp(var->name, "autocontext")) 04739 ast_string_field_set(trunk, autocontext, var->value); 04740 else if (!strcasecmp(var->name, "ringtimeout")) { 04741 if (sscanf(var->value, "%30u", &trunk->ring_timeout) != 1) { 04742 ast_log(LOG_WARNING, "Invalid ringtimeout '%s' specified for trunk '%s'\n", 04743 var->value, trunk->name); 04744 trunk->ring_timeout = 0; 04745 } 04746 } else if (!strcasecmp(var->name, "barge")) 04747 trunk->barge_disabled = ast_false(var->value); 04748 else if (!strcasecmp(var->name, "hold")) { 04749 if (!strcasecmp(var->value, "private")) 04750 trunk->hold_access = SLA_HOLD_PRIVATE; 04751 else if (!strcasecmp(var->value, "open")) 04752 trunk->hold_access = SLA_HOLD_OPEN; 04753 else { 04754 ast_log(LOG_WARNING, "Invalid value '%s' for hold on trunk %s\n", 04755 var->value, trunk->name); 04756 } 04757 } else if (strcasecmp(var->name, "type") && strcasecmp(var->name, "device")) { 04758 ast_log(LOG_ERROR, "Invalid option '%s' specified at line %d of %s!\n", 04759 var->name, var->lineno, SLA_CONFIG_FILE); 04760 } 04761 } 04762 04763 if (!ast_strlen_zero(trunk->autocontext)) { 04764 struct ast_context *context; 04765 context = ast_context_find_or_create(NULL, trunk->autocontext, sla_registrar); 04766 if (!context) { 04767 ast_log(LOG_ERROR, "Failed to automatically find or create " 04768 "context '%s' for SLA!\n", trunk->autocontext); 04769 destroy_trunk(trunk); 04770 return -1; 04771 } 04772 if (ast_add_extension2(context, 0 /* don't replace */, "s", 1, 04773 NULL, NULL, slatrunk_app, ast_strdup(trunk->name), ast_free_ptr, sla_registrar)) { 04774 ast_log(LOG_ERROR, "Failed to automatically create extension " 04775 "for trunk '%s'!\n", trunk->name); 04776 destroy_trunk(trunk); 04777 return -1; 04778 } 04779 } 04780 04781 AST_RWLIST_WRLOCK(&sla_trunks); 04782 AST_RWLIST_INSERT_TAIL(&sla_trunks, trunk, entry); 04783 AST_RWLIST_UNLOCK(&sla_trunks); 04784 04785 return 0; 04786 }
static int sla_calc_station_delays | ( | unsigned int * | timeout | ) | [static] |
Calculate the ring delay for a station.
Definition at line 4056 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().
04057 { 04058 struct sla_station *station; 04059 int res = 0; 04060 04061 AST_LIST_TRAVERSE(&sla_stations, station, entry) { 04062 struct sla_ringing_trunk *ringing_trunk; 04063 int time_left; 04064 04065 /* Ignore stations already ringing */ 04066 if (sla_check_ringing_station(station)) 04067 continue; 04068 04069 /* Ignore stations already on a call */ 04070 if (sla_check_inuse_station(station)) 04071 continue; 04072 04073 /* Ignore stations that don't have one of their trunks ringing */ 04074 if (!(ringing_trunk = sla_choose_ringing_trunk(station, NULL, 0))) 04075 continue; 04076 04077 if ((time_left = sla_check_station_delay(station, ringing_trunk)) == INT_MAX) 04078 continue; 04079 04080 /* If there is no time left, then the station needs to start ringing. 04081 * Return non-zero so that an event will be queued up an event to 04082 * make that happen. */ 04083 if (time_left <= 0) { 04084 res = 1; 04085 continue; 04086 } 04087 04088 if (time_left < *timeout) 04089 *timeout = time_left; 04090 } 04091 04092 return res; 04093 }
static int sla_calc_station_timeouts | ( | unsigned int * | timeout | ) | [static] |
Process station ring timeouts.
Definition at line 3973 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().
03974 { 03975 struct sla_ringing_trunk *ringing_trunk; 03976 struct sla_ringing_station *ringing_station; 03977 int res = 0; 03978 03979 AST_LIST_TRAVERSE_SAFE_BEGIN(&sla.ringing_stations, ringing_station, entry) { 03980 unsigned int ring_timeout = 0; 03981 int time_elapsed, time_left = INT_MAX, final_trunk_time_left = INT_MIN; 03982 struct sla_trunk_ref *trunk_ref; 03983 03984 /* If there are any ring timeouts specified for a specific trunk 03985 * on the station, then use the highest per-trunk ring timeout. 03986 * Otherwise, use the ring timeout set for the entire station. */ 03987 AST_LIST_TRAVERSE(&ringing_station->station->trunks, trunk_ref, entry) { 03988 struct sla_station_ref *station_ref; 03989 int trunk_time_elapsed, trunk_time_left; 03990 03991 AST_LIST_TRAVERSE(&sla.ringing_trunks, ringing_trunk, entry) { 03992 if (ringing_trunk->trunk == trunk_ref->trunk) 03993 break; 03994 } 03995 if (!ringing_trunk) 03996 continue; 03997 03998 /* If there is a trunk that is ringing without a timeout, then the 03999 * only timeout that could matter is a global station ring timeout. */ 04000 if (!trunk_ref->ring_timeout) 04001 break; 04002 04003 /* This trunk on this station is ringing and has a timeout. 04004 * However, make sure this trunk isn't still ringing from a 04005 * previous timeout. If so, don't consider it. */ 04006 AST_LIST_TRAVERSE(&ringing_trunk->timed_out_stations, station_ref, entry) { 04007 if (station_ref->station == ringing_station->station) 04008 break; 04009 } 04010 if (station_ref) 04011 continue; 04012 04013 trunk_time_elapsed = ast_tvdiff_ms(ast_tvnow(), ringing_trunk->ring_begin); 04014 trunk_time_left = (trunk_ref->ring_timeout * 1000) - trunk_time_elapsed; 04015 if (trunk_time_left > final_trunk_time_left) 04016 final_trunk_time_left = trunk_time_left; 04017 } 04018 04019 /* No timeout was found for ringing trunks, and no timeout for the entire station */ 04020 if (final_trunk_time_left == INT_MIN && !ringing_station->station->ring_timeout) 04021 continue; 04022 04023 /* Compute how much time is left for a global station timeout */ 04024 if (ringing_station->station->ring_timeout) { 04025 ring_timeout = ringing_station->station->ring_timeout; 04026 time_elapsed = ast_tvdiff_ms(ast_tvnow(), ringing_station->ring_begin); 04027 time_left = (ring_timeout * 1000) - time_elapsed; 04028 } 04029 04030 /* If the time left based on the per-trunk timeouts is smaller than the 04031 * global station ring timeout, use that. */ 04032 if (final_trunk_time_left > INT_MIN && final_trunk_time_left < time_left) 04033 time_left = final_trunk_time_left; 04034 04035 /* If there is no time left, the station needs to stop ringing */ 04036 if (time_left <= 0) { 04037 AST_LIST_REMOVE_CURRENT(&sla.ringing_stations, entry); 04038 sla_stop_ringing_station(ringing_station, SLA_STATION_HANGUP_TIMEOUT); 04039 res = 1; 04040 continue; 04041 } 04042 04043 /* There is still some time left for this station to ring, so save that 04044 * timeout if it is the first event scheduled to occur */ 04045 if (time_left < *timeout) 04046 *timeout = time_left; 04047 } 04048 AST_LIST_TRAVERSE_SAFE_END 04049 04050 return res; 04051 }
static int sla_calc_trunk_timeouts | ( | unsigned int * | timeout | ) | [static] |
Process trunk ring timeouts.
Definition at line 3943 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().
03944 { 03945 struct sla_ringing_trunk *ringing_trunk; 03946 int res = 0; 03947 03948 AST_LIST_TRAVERSE_SAFE_BEGIN(&sla.ringing_trunks, ringing_trunk, entry) { 03949 int time_left, time_elapsed; 03950 if (!ringing_trunk->trunk->ring_timeout) 03951 continue; 03952 time_elapsed = ast_tvdiff_ms(ast_tvnow(), ringing_trunk->ring_begin); 03953 time_left = (ringing_trunk->trunk->ring_timeout * 1000) - time_elapsed; 03954 if (time_left <= 0) { 03955 pbx_builtin_setvar_helper(ringing_trunk->trunk->chan, "SLATRUNK_STATUS", "RINGTIMEOUT"); 03956 AST_LIST_REMOVE_CURRENT(&sla.ringing_trunks, entry); 03957 sla_stop_ringing_trunk(ringing_trunk); 03958 res = 1; 03959 continue; 03960 } 03961 if (time_left < *timeout) 03962 *timeout = time_left; 03963 } 03964 AST_LIST_TRAVERSE_SAFE_END 03965 03966 return res; 03967 }
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 3408 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().
03410 { 03411 struct sla_station *station; 03412 struct sla_trunk_ref *trunk_ref; 03413 03414 AST_LIST_TRAVERSE(&sla_stations, station, entry) { 03415 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) { 03416 if (trunk_ref->trunk != trunk || (inactive_only ? trunk_ref->chan : 0) 03417 || trunk_ref == exclude) 03418 continue; 03419 trunk_ref->state = state; 03420 ast_device_state_changed("SLA:%s_%s", station->name, trunk->name); 03421 break; 03422 } 03423 } 03424 }
static int sla_check_device | ( | const char * | device | ) | [static] |
Definition at line 4697 of file app_meetme.c.
References ast_strdupa, and ast_strlen_zero().
Referenced by sla_build_trunk().
04698 { 04699 char *tech, *tech_data; 04700 04701 tech_data = ast_strdupa(device); 04702 tech = strsep(&tech_data, "/"); 04703 04704 if (ast_strlen_zero(tech) || ast_strlen_zero(tech_data)) 04705 return -1; 04706 04707 return 0; 04708 }
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 3691 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().
03692 { 03693 struct sla_failed_station *failed_station; 03694 int res = 0; 03695 03696 AST_LIST_TRAVERSE_SAFE_BEGIN(&sla.failed_stations, failed_station, entry) { 03697 if (station != failed_station->station) 03698 continue; 03699 if (ast_tvdiff_ms(ast_tvnow(), failed_station->last_try) > 1000) { 03700 AST_LIST_REMOVE_CURRENT(&sla.failed_stations, entry); 03701 free(failed_station); 03702 break; 03703 } 03704 res = 1; 03705 } 03706 AST_LIST_TRAVERSE_SAFE_END 03707 03708 return res; 03709 }
static int sla_check_inuse_station | ( | const struct sla_station * | station | ) | [static] |
Check to see if a station is in use.
Definition at line 3777 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().
03778 { 03779 struct sla_trunk_ref *trunk_ref; 03780 03781 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) { 03782 if (trunk_ref->chan) 03783 return 1; 03784 } 03785 03786 return 0; 03787 }
static int sla_check_ringing_station | ( | const struct sla_station * | station | ) | [static] |
Check to see if this station is already ringing.
Definition at line 3676 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().
03677 { 03678 struct sla_ringing_station *ringing_station; 03679 03680 AST_LIST_TRAVERSE(&sla.ringing_stations, ringing_station, entry) { 03681 if (station == ringing_station->station) 03682 return 1; 03683 } 03684 03685 return 0; 03686 }
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 3807 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().
03809 { 03810 struct sla_trunk_ref *trunk_ref; 03811 unsigned int delay = UINT_MAX; 03812 int time_left, time_elapsed; 03813 03814 if (!ringing_trunk) 03815 ringing_trunk = sla_choose_ringing_trunk(station, &trunk_ref, 0); 03816 else 03817 trunk_ref = sla_find_trunk_ref(station, ringing_trunk->trunk); 03818 03819 if (!ringing_trunk || !trunk_ref) 03820 return delay; 03821 03822 /* If this station has a ring delay specific to the highest priority 03823 * ringing trunk, use that. Otherwise, use the ring delay specified 03824 * globally for the station. */ 03825 delay = trunk_ref->ring_delay; 03826 if (!delay) 03827 delay = station->ring_delay; 03828 if (!delay) 03829 return INT_MAX; 03830 03831 time_elapsed = ast_tvdiff_ms(ast_tvnow(), ringing_trunk->ring_begin); 03832 time_left = (delay * 1000) - time_elapsed; 03833 03834 return time_left; 03835 }
static int sla_check_station_hold_access | ( | const struct sla_trunk * | trunk, | |
const struct sla_station * | station | |||
) | [static] |
Definition at line 3330 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().
03332 { 03333 struct sla_station_ref *station_ref; 03334 struct sla_trunk_ref *trunk_ref; 03335 03336 /* For each station that has this call on hold, check for private hold. */ 03337 AST_LIST_TRAVERSE(&trunk->stations, station_ref, entry) { 03338 AST_LIST_TRAVERSE(&station_ref->station->trunks, trunk_ref, entry) { 03339 if (trunk_ref->trunk != trunk || station_ref->station == station) 03340 continue; 03341 if (trunk_ref->state == SLA_TRUNK_STATE_ONHOLD_BYME && 03342 station_ref->station->hold_access == SLA_HOLD_PRIVATE) 03343 return 1; 03344 return 0; 03345 } 03346 } 03347 03348 return 0; 03349 }
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 3542 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().
03544 { 03545 struct sla_station_ref *timed_out_station; 03546 03547 AST_LIST_TRAVERSE(&ringing_trunk->timed_out_stations, timed_out_station, entry) { 03548 if (station == timed_out_station->station) 03549 return 1; 03550 } 03551 03552 return 0; 03553 }
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 4307 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().
04308 { 04309 struct sla_trunk_ref *trunk_ref = NULL; 04310 04311 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) { 04312 if (trunk_ref->state == SLA_TRUNK_STATE_IDLE) 04313 break; 04314 } 04315 04316 return trunk_ref; 04317 }
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 3563 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().
03565 { 03566 struct sla_trunk_ref *s_trunk_ref; 03567 struct sla_ringing_trunk *ringing_trunk = NULL; 03568 03569 AST_LIST_TRAVERSE(&station->trunks, s_trunk_ref, entry) { 03570 AST_LIST_TRAVERSE_SAFE_BEGIN(&sla.ringing_trunks, ringing_trunk, entry) { 03571 /* Make sure this is the trunk we're looking for */ 03572 if (s_trunk_ref->trunk != ringing_trunk->trunk) 03573 continue; 03574 03575 /* This trunk on the station is ringing. But, make sure this station 03576 * didn't already time out while this trunk was ringing. */ 03577 if (sla_check_timed_out_station(ringing_trunk, station)) 03578 continue; 03579 03580 if (remove) 03581 AST_LIST_REMOVE_CURRENT(&sla.ringing_trunks, entry); 03582 03583 if (trunk_ref) 03584 *trunk_ref = s_trunk_ref; 03585 03586 break; 03587 } 03588 AST_LIST_TRAVERSE_SAFE_END 03589 03590 if (ringing_trunk) 03591 break; 03592 } 03593 03594 return ringing_trunk; 03595 }
static struct sla_ringing_station* sla_create_ringing_station | ( | struct sla_station * | station | ) | [static] |
Definition at line 3395 of file app_meetme.c.
References ast_calloc, ast_tvnow(), and sla_ringing_station::station.
Referenced by sla_ring_station().
03396 { 03397 struct sla_ringing_station *ringing_station; 03398 03399 if (!(ringing_station = ast_calloc(1, sizeof(*ringing_station)))) 03400 return NULL; 03401 03402 ringing_station->station = station; 03403 ringing_station->ring_begin = ast_tvnow(); 03404 03405 return ringing_station; 03406 }
static struct sla_station_ref* sla_create_station_ref | ( | struct sla_station * | station | ) | [static] |
Definition at line 3383 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().
03384 { 03385 struct sla_station_ref *station_ref; 03386 03387 if (!(station_ref = ast_calloc(1, sizeof(*station_ref)))) 03388 return NULL; 03389 03390 station_ref->station = station; 03391 03392 return station_ref; 03393 }
static void sla_destroy | ( | void | ) | [static] |
Definition at line 4667 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().
04668 { 04669 struct sla_trunk *trunk; 04670 struct sla_station *station; 04671 04672 AST_RWLIST_WRLOCK(&sla_trunks); 04673 while ((trunk = AST_RWLIST_REMOVE_HEAD(&sla_trunks, entry))) 04674 destroy_trunk(trunk); 04675 AST_RWLIST_UNLOCK(&sla_trunks); 04676 04677 AST_RWLIST_WRLOCK(&sla_stations); 04678 while ((station = AST_RWLIST_REMOVE_HEAD(&sla_stations, entry))) 04679 destroy_station(station); 04680 AST_RWLIST_UNLOCK(&sla_stations); 04681 04682 if (sla.thread != AST_PTHREADT_NULL) { 04683 ast_mutex_lock(&sla.lock); 04684 sla.stop = 1; 04685 ast_cond_signal(&sla.cond); 04686 ast_mutex_unlock(&sla.lock); 04687 pthread_join(sla.thread, NULL); 04688 } 04689 04690 /* Drop any created contexts from the dialplan */ 04691 ast_context_destroy(NULL, sla_registrar); 04692 04693 ast_mutex_destroy(&sla.lock); 04694 ast_cond_destroy(&sla.cond); 04695 }
static void sla_dial_state_callback | ( | struct ast_dial * | dial | ) | [static] |
Definition at line 3534 of file app_meetme.c.
References SLA_EVENT_DIAL_STATE, and sla_queue_event().
Referenced by sla_ring_station().
03535 { 03536 sla_queue_event(SLA_EVENT_DIAL_STATE); 03537 }
static struct sla_station* sla_find_station | ( | const char * | name | ) | [static] |
Find an SLA station by name.
Definition at line 3318 of file app_meetme.c.
References AST_RWLIST_TRAVERSE, announce_listitem::entry, and sla_station::name.
Referenced by sla_station_exec().
03319 { 03320 struct sla_station *station = NULL; 03321 03322 AST_RWLIST_TRAVERSE(&sla_stations, station, entry) { 03323 if (!strcasecmp(station->name, name)) 03324 break; 03325 } 03326 03327 return station; 03328 }
static struct sla_trunk* sla_find_trunk | ( | const char * | name | ) | [static] |
Find an SLA trunk by name.
Definition at line 3303 of file app_meetme.c.
References AST_RWLIST_TRAVERSE, announce_listitem::entry, and sla_trunk::name.
Referenced by sla_trunk_exec().
03304 { 03305 struct sla_trunk *trunk = NULL; 03306 03307 AST_RWLIST_TRAVERSE(&sla_trunks, trunk, entry) { 03308 if (!strcasecmp(trunk->name, name)) 03309 break; 03310 } 03311 03312 return trunk; 03313 }
static struct sla_trunk_ref* sla_find_trunk_ref | ( | const struct sla_station * | station, | |
const struct sla_trunk * | trunk | |||
) | [static] |
Definition at line 3789 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().
03791 { 03792 struct sla_trunk_ref *trunk_ref = NULL; 03793 03794 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) { 03795 if (trunk_ref->trunk == trunk) 03796 break; 03797 } 03798 03799 return trunk_ref; 03800 }
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 3358 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().
03360 { 03361 struct sla_trunk_ref *trunk_ref = NULL; 03362 03363 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) { 03364 if (strcasecmp(trunk_ref->trunk->name, name)) 03365 continue; 03366 03367 if ( (trunk_ref->trunk->barge_disabled 03368 && trunk_ref->state == SLA_TRUNK_STATE_UP) || 03369 (trunk_ref->trunk->hold_stations 03370 && trunk_ref->trunk->hold_access == SLA_HOLD_PRIVATE 03371 && trunk_ref->state != SLA_TRUNK_STATE_ONHOLD_BYME) || 03372 sla_check_station_hold_access(trunk_ref->trunk, station) ) 03373 { 03374 trunk_ref = NULL; 03375 } 03376 03377 break; 03378 } 03379 03380 return trunk_ref; 03381 }
static void sla_handle_dial_state_event | ( | void | ) | [static] |
Definition at line 3597 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().
03598 { 03599 struct sla_ringing_station *ringing_station; 03600 03601 AST_LIST_TRAVERSE_SAFE_BEGIN(&sla.ringing_stations, ringing_station, entry) { 03602 struct sla_trunk_ref *s_trunk_ref = NULL; 03603 struct sla_ringing_trunk *ringing_trunk = NULL; 03604 struct run_station_args args; 03605 enum ast_dial_result dial_res; 03606 pthread_attr_t attr; 03607 pthread_t dont_care; 03608 ast_mutex_t cond_lock; 03609 ast_cond_t cond; 03610 03611 switch ((dial_res = ast_dial_state(ringing_station->station->dial))) { 03612 case AST_DIAL_RESULT_HANGUP: 03613 case AST_DIAL_RESULT_INVALID: 03614 case AST_DIAL_RESULT_FAILED: 03615 case AST_DIAL_RESULT_TIMEOUT: 03616 case AST_DIAL_RESULT_UNANSWERED: 03617 AST_LIST_REMOVE_CURRENT(&sla.ringing_stations, entry); 03618 sla_stop_ringing_station(ringing_station, SLA_STATION_HANGUP_NORMAL); 03619 break; 03620 case AST_DIAL_RESULT_ANSWERED: 03621 AST_LIST_REMOVE_CURRENT(&sla.ringing_stations, entry); 03622 /* Find the appropriate trunk to answer. */ 03623 ast_mutex_lock(&sla.lock); 03624 ringing_trunk = sla_choose_ringing_trunk(ringing_station->station, &s_trunk_ref, 1); 03625 ast_mutex_unlock(&sla.lock); 03626 if (!ringing_trunk) { 03627 ast_log(LOG_DEBUG, "Found no ringing trunk for station '%s' to answer!\n", 03628 ringing_station->station->name); 03629 break; 03630 } 03631 /* Track the channel that answered this trunk */ 03632 s_trunk_ref->chan = ast_dial_answered(ringing_station->station->dial); 03633 /* Actually answer the trunk */ 03634 answer_trunk_chan(ringing_trunk->trunk->chan); 03635 sla_change_trunk_state(ringing_trunk->trunk, SLA_TRUNK_STATE_UP, ALL_TRUNK_REFS, NULL); 03636 /* Now, start a thread that will connect this station to the trunk. The rest of 03637 * the code here sets up the thread and ensures that it is able to save the arguments 03638 * before they are no longer valid since they are allocated on the stack. */ 03639 args.trunk_ref = s_trunk_ref; 03640 args.station = ringing_station->station; 03641 args.cond = &cond; 03642 args.cond_lock = &cond_lock; 03643 free(ringing_trunk); 03644 free(ringing_station); 03645 ast_mutex_init(&cond_lock); 03646 ast_cond_init(&cond, NULL); 03647 pthread_attr_init(&attr); 03648 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 03649 ast_mutex_lock(&cond_lock); 03650 ast_pthread_create_background(&dont_care, &attr, run_station, &args); 03651 ast_cond_wait(&cond, &cond_lock); 03652 ast_mutex_unlock(&cond_lock); 03653 ast_mutex_destroy(&cond_lock); 03654 ast_cond_destroy(&cond); 03655 pthread_attr_destroy(&attr); 03656 break; 03657 case AST_DIAL_RESULT_TRYING: 03658 case AST_DIAL_RESULT_RINGING: 03659 case AST_DIAL_RESULT_PROGRESS: 03660 case AST_DIAL_RESULT_PROCEEDING: 03661 break; 03662 } 03663 if (dial_res == AST_DIAL_RESULT_ANSWERED) { 03664 /* Queue up reprocessing ringing trunks, and then ringing stations again */ 03665 sla_queue_event(SLA_EVENT_RINGING_TRUNK); 03666 sla_queue_event(SLA_EVENT_DIAL_STATE); 03667 break; 03668 } 03669 } 03670 AST_LIST_TRAVERSE_SAFE_END 03671 }
static void sla_handle_hold_event | ( | struct sla_event * | event | ) | [static] |
Definition at line 3919 of file app_meetme.c.
References sla_trunk::active_stations, ast_atomic_fetchadd_int(), AST_CONTROL_HOLD, ast_device_state_changed(), ast_indicate(), ast_softhangup(), AST_SOFTHANGUP_DEV, sla_trunk_ref::chan, sla_trunk::chan, sla_trunk::hold_stations, INACTIVE_TRUNK_REFS, sla_trunk::name, sla_station::name, sla_trunk::on_hold, sla_change_trunk_state(), SLA_TRUNK_STATE_ONHOLD, SLA_TRUNK_STATE_ONHOLD_BYME, sla_trunk_ref::state, sla_event::station, sla_trunk_ref::trunk, and sla_event::trunk_ref.
Referenced by sla_thread().
03920 { 03921 ast_atomic_fetchadd_int((int *) &event->trunk_ref->trunk->hold_stations, 1); 03922 event->trunk_ref->state = SLA_TRUNK_STATE_ONHOLD_BYME; 03923 ast_device_state_changed("SLA:%s_%s", 03924 event->station->name, event->trunk_ref->trunk->name); 03925 sla_change_trunk_state(event->trunk_ref->trunk, SLA_TRUNK_STATE_ONHOLD, 03926 INACTIVE_TRUNK_REFS, event->trunk_ref); 03927 03928 if (event->trunk_ref->trunk->active_stations == 1) { 03929 /* The station putting it on hold is the only one on the call, so start 03930 * Music on hold to the trunk. */ 03931 event->trunk_ref->trunk->on_hold = 1; 03932 ast_indicate(event->trunk_ref->trunk->chan, AST_CONTROL_HOLD); 03933 } 03934 03935 ast_softhangup(event->trunk_ref->chan, AST_SOFTHANGUP_DEV); 03936 event->trunk_ref->chan = NULL; 03937 }
static void sla_handle_ringing_trunk_event | ( | void | ) | [static] |
Definition at line 3909 of file app_meetme.c.
References ast_mutex_lock, ast_mutex_unlock, sla, sla_hangup_stations(), and sla_ring_stations().
Referenced by sla_thread().
03910 { 03911 ast_mutex_lock(&sla.lock); 03912 sla_ring_stations(); 03913 ast_mutex_unlock(&sla.lock); 03914 03915 /* Find stations that shouldn't be ringing anymore. */ 03916 sla_hangup_stations(); 03917 }
static void sla_hangup_stations | ( | void | ) | [static] |
Definition at line 3881 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().
03882 { 03883 struct sla_trunk_ref *trunk_ref; 03884 struct sla_ringing_station *ringing_station; 03885 03886 AST_LIST_TRAVERSE_SAFE_BEGIN(&sla.ringing_stations, ringing_station, entry) { 03887 AST_LIST_TRAVERSE(&ringing_station->station->trunks, trunk_ref, entry) { 03888 struct sla_ringing_trunk *ringing_trunk; 03889 ast_mutex_lock(&sla.lock); 03890 AST_LIST_TRAVERSE(&sla.ringing_trunks, ringing_trunk, entry) { 03891 if (trunk_ref->trunk == ringing_trunk->trunk) 03892 break; 03893 } 03894 ast_mutex_unlock(&sla.lock); 03895 if (ringing_trunk) 03896 break; 03897 } 03898 if (!trunk_ref) { 03899 AST_LIST_REMOVE_CURRENT(&sla.ringing_stations, entry); 03900 ast_dial_join(ringing_station->station->dial); 03901 ast_dial_destroy(ringing_station->station->dial); 03902 ringing_station->station->dial = NULL; 03903 free(ringing_station); 03904 } 03905 } 03906 AST_LIST_TRAVERSE_SAFE_END 03907 }
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 4953 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().
04954 { 04955 struct ast_config *cfg; 04956 const char *cat = NULL; 04957 int res = 0; 04958 const char *val; 04959 04960 ast_mutex_init(&sla.lock); 04961 ast_cond_init(&sla.cond, NULL); 04962 04963 if (!(cfg = ast_config_load(SLA_CONFIG_FILE))) 04964 return 0; /* Treat no config as normal */ 04965 04966 if ((val = ast_variable_retrieve(cfg, "general", "attemptcallerid"))) 04967 sla.attempt_callerid = ast_true(val); 04968 04969 while ((cat = ast_category_browse(cfg, cat)) && !res) { 04970 const char *type; 04971 if (!strcasecmp(cat, "general")) 04972 continue; 04973 if (!(type = ast_variable_retrieve(cfg, cat, "type"))) { 04974 ast_log(LOG_WARNING, "Invalid entry in %s defined with no type!\n", 04975 SLA_CONFIG_FILE); 04976 continue; 04977 } 04978 if (!strcasecmp(type, "trunk")) 04979 res = sla_build_trunk(cfg, cat); 04980 else if (!strcasecmp(type, "station")) 04981 res = sla_build_station(cfg, cat); 04982 else { 04983 ast_log(LOG_WARNING, "Entry in %s defined with invalid type '%s'!\n", 04984 SLA_CONFIG_FILE, type); 04985 } 04986 } 04987 04988 ast_config_destroy(cfg); 04989 04990 if (!AST_LIST_EMPTY(&sla_stations) || !AST_LIST_EMPTY(&sla_stations)) 04991 ast_pthread_create(&sla.thread, NULL, sla_thread, NULL); 04992 04993 return res; 04994 }
static int sla_process_timers | ( | struct timespec * | ts | ) | [static] |
Calculate the time until the next known event.
Definition at line 4097 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().
04098 { 04099 unsigned int timeout = UINT_MAX; 04100 struct timeval tv; 04101 unsigned int change_made = 0; 04102 04103 /* Check for ring timeouts on ringing trunks */ 04104 if (sla_calc_trunk_timeouts(&timeout)) 04105 change_made = 1; 04106 04107 /* Check for ring timeouts on ringing stations */ 04108 if (sla_calc_station_timeouts(&timeout)) 04109 change_made = 1; 04110 04111 /* Check for station ring delays */ 04112 if (sla_calc_station_delays(&timeout)) 04113 change_made = 1; 04114 04115 /* queue reprocessing of ringing trunks */ 04116 if (change_made) 04117 sla_queue_event_nolock(SLA_EVENT_RINGING_TRUNK); 04118 04119 /* No timeout */ 04120 if (timeout == UINT_MAX) 04121 return 0; 04122 04123 if (ts) { 04124 tv = ast_tvadd(ast_tvnow(), ast_samp2tv(timeout, 1000)); 04125 ts->tv_sec = tv.tv_sec; 04126 ts->tv_nsec = tv.tv_usec * 1000; 04127 } 04128 04129 return 1; 04130 }
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 3714 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().
03715 { 03716 char *tech, *tech_data; 03717 struct ast_dial *dial; 03718 struct sla_ringing_station *ringing_station; 03719 const char *cid_name = NULL, *cid_num = NULL; 03720 enum ast_dial_result res; 03721 03722 if (!(dial = ast_dial_create())) 03723 return -1; 03724 03725 ast_dial_set_state_callback(dial, sla_dial_state_callback); 03726 tech_data = ast_strdupa(station->device); 03727 tech = strsep(&tech_data, "/"); 03728 03729 if (ast_dial_append(dial, tech, tech_data) == -1) { 03730 ast_dial_destroy(dial); 03731 return -1; 03732 } 03733 03734 if (!sla.attempt_callerid && !ast_strlen_zero(ringing_trunk->trunk->chan->cid.cid_name)) { 03735 cid_name = ast_strdupa(ringing_trunk->trunk->chan->cid.cid_name); 03736 free(ringing_trunk->trunk->chan->cid.cid_name); 03737 ringing_trunk->trunk->chan->cid.cid_name = NULL; 03738 } 03739 if (!sla.attempt_callerid && !ast_strlen_zero(ringing_trunk->trunk->chan->cid.cid_num)) { 03740 cid_num = ast_strdupa(ringing_trunk->trunk->chan->cid.cid_num); 03741 free(ringing_trunk->trunk->chan->cid.cid_num); 03742 ringing_trunk->trunk->chan->cid.cid_num = NULL; 03743 } 03744 03745 res = ast_dial_run(dial, ringing_trunk->trunk->chan, 1); 03746 03747 if (cid_name) 03748 ringing_trunk->trunk->chan->cid.cid_name = ast_strdup(cid_name); 03749 if (cid_num) 03750 ringing_trunk->trunk->chan->cid.cid_num = ast_strdup(cid_num); 03751 03752 if (res != AST_DIAL_RESULT_TRYING) { 03753 struct sla_failed_station *failed_station; 03754 ast_dial_destroy(dial); 03755 if (!(failed_station = ast_calloc(1, sizeof(*failed_station)))) 03756 return -1; 03757 failed_station->station = station; 03758 failed_station->last_try = ast_tvnow(); 03759 AST_LIST_INSERT_HEAD(&sla.failed_stations, failed_station, entry); 03760 return -1; 03761 } 03762 if (!(ringing_station = sla_create_ringing_station(station))) { 03763 ast_dial_join(dial); 03764 ast_dial_destroy(dial); 03765 return -1; 03766 } 03767 03768 station->dial = dial; 03769 03770 AST_LIST_INSERT_HEAD(&sla.ringing_stations, ringing_station, entry); 03771 03772 return 0; 03773 }
static void sla_ring_stations | ( | void | ) | [static] |
Ring stations based on current set of ringing trunks.
Definition at line 3840 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().
03841 { 03842 struct sla_station_ref *station_ref; 03843 struct sla_ringing_trunk *ringing_trunk; 03844 03845 /* Make sure that every station that uses at least one of the ringing 03846 * trunks, is ringing. */ 03847 AST_LIST_TRAVERSE(&sla.ringing_trunks, ringing_trunk, entry) { 03848 AST_LIST_TRAVERSE(&ringing_trunk->trunk->stations, station_ref, entry) { 03849 int time_left; 03850 03851 /* Is this station already ringing? */ 03852 if (sla_check_ringing_station(station_ref->station)) 03853 continue; 03854 03855 /* Is this station already in a call? */ 03856 if (sla_check_inuse_station(station_ref->station)) 03857 continue; 03858 03859 /* Did we fail to dial this station earlier? If so, has it been 03860 * a minute since we tried? */ 03861 if (sla_check_failed_station(station_ref->station)) 03862 continue; 03863 03864 /* If this station already timed out while this trunk was ringing, 03865 * do not dial it again for this ringing trunk. */ 03866 if (sla_check_timed_out_station(ringing_trunk, station_ref->station)) 03867 continue; 03868 03869 /* Check for a ring delay in progress */ 03870 time_left = sla_check_station_delay(station_ref->station, ringing_trunk); 03871 if (time_left != INT_MAX && time_left > 0) 03872 continue; 03873 03874 /* It is time to make this station begin to ring. Do it! */ 03875 sla_ring_station(ringing_trunk, station_ref->station); 03876 } 03877 } 03878 /* Now, all of the stations that should be ringing, are ringing. */ 03879 }
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 4577 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().
04578 { 04579 char *buf, *station_name, *trunk_name; 04580 struct sla_station *station; 04581 struct sla_trunk_ref *trunk_ref; 04582 int res = AST_DEVICE_INVALID; 04583 04584 trunk_name = buf = ast_strdupa(data); 04585 station_name = strsep(&trunk_name, "_"); 04586 04587 AST_RWLIST_RDLOCK(&sla_stations); 04588 AST_LIST_TRAVERSE(&sla_stations, station, entry) { 04589 if (strcasecmp(station_name, station->name)) 04590 continue; 04591 AST_RWLIST_RDLOCK(&sla_trunks); 04592 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) { 04593 if (!strcasecmp(trunk_name, trunk_ref->trunk->name)) 04594 break; 04595 } 04596 if (!trunk_ref) { 04597 AST_RWLIST_UNLOCK(&sla_trunks); 04598 break; 04599 } 04600 switch (trunk_ref->state) { 04601 case SLA_TRUNK_STATE_IDLE: 04602 res = AST_DEVICE_NOT_INUSE; 04603 break; 04604 case SLA_TRUNK_STATE_RINGING: 04605 res = AST_DEVICE_RINGING; 04606 break; 04607 case SLA_TRUNK_STATE_UP: 04608 res = AST_DEVICE_INUSE; 04609 break; 04610 case SLA_TRUNK_STATE_ONHOLD: 04611 case SLA_TRUNK_STATE_ONHOLD_BYME: 04612 res = AST_DEVICE_ONHOLD; 04613 break; 04614 } 04615 AST_RWLIST_UNLOCK(&sla_trunks); 04616 } 04617 AST_RWLIST_UNLOCK(&sla_stations); 04618 04619 if (res == AST_DEVICE_INVALID) { 04620 ast_log(LOG_ERROR, "Could not determine state for trunk %s on station %s!\n", 04621 trunk_name, station_name); 04622 } 04623 04624 return res; 04625 }
static int sla_station_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Definition at line 4319 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().
04320 { 04321 char *station_name, *trunk_name; 04322 struct sla_station *station; 04323 struct sla_trunk_ref *trunk_ref = NULL; 04324 char conf_name[MAX_CONFNUM]; 04325 struct ast_flags conf_flags = { 0 }; 04326 struct ast_conference *conf; 04327 04328 if (ast_strlen_zero(data)) { 04329 ast_log(LOG_WARNING, "Invalid Arguments to SLAStation!\n"); 04330 pbx_builtin_setvar_helper(chan, "SLASTATION_STATUS", "FAILURE"); 04331 return 0; 04332 } 04333 04334 trunk_name = ast_strdupa(data); 04335 station_name = strsep(&trunk_name, "_"); 04336 04337 if (ast_strlen_zero(station_name)) { 04338 ast_log(LOG_WARNING, "Invalid Arguments to SLAStation!\n"); 04339 pbx_builtin_setvar_helper(chan, "SLASTATION_STATUS", "FAILURE"); 04340 return 0; 04341 } 04342 04343 AST_RWLIST_RDLOCK(&sla_stations); 04344 station = sla_find_station(station_name); 04345 AST_RWLIST_UNLOCK(&sla_stations); 04346 04347 if (!station) { 04348 ast_log(LOG_WARNING, "Station '%s' not found!\n", station_name); 04349 pbx_builtin_setvar_helper(chan, "SLASTATION_STATUS", "FAILURE"); 04350 return 0; 04351 } 04352 04353 AST_RWLIST_RDLOCK(&sla_trunks); 04354 if (!ast_strlen_zero(trunk_name)) { 04355 trunk_ref = sla_find_trunk_ref_byname(station, trunk_name); 04356 } else 04357 trunk_ref = sla_choose_idle_trunk(station); 04358 AST_RWLIST_UNLOCK(&sla_trunks); 04359 04360 if (!trunk_ref) { 04361 if (ast_strlen_zero(trunk_name)) 04362 ast_log(LOG_NOTICE, "No trunks available for call.\n"); 04363 else { 04364 ast_log(LOG_NOTICE, "Can't join existing call on trunk " 04365 "'%s' due to access controls.\n", trunk_name); 04366 } 04367 pbx_builtin_setvar_helper(chan, "SLASTATION_STATUS", "CONGESTION"); 04368 return 0; 04369 } 04370 04371 if (trunk_ref->state == SLA_TRUNK_STATE_ONHOLD_BYME) { 04372 if (ast_atomic_dec_and_test((int *) &trunk_ref->trunk->hold_stations) == 1) 04373 sla_change_trunk_state(trunk_ref->trunk, SLA_TRUNK_STATE_UP, ALL_TRUNK_REFS, NULL); 04374 else { 04375 trunk_ref->state = SLA_TRUNK_STATE_UP; 04376 ast_device_state_changed("SLA:%s_%s", station->name, trunk_ref->trunk->name); 04377 } 04378 } else if (trunk_ref->state == SLA_TRUNK_STATE_RINGING) { 04379 struct sla_ringing_trunk *ringing_trunk; 04380 04381 ast_mutex_lock(&sla.lock); 04382 AST_LIST_TRAVERSE_SAFE_BEGIN(&sla.ringing_trunks, ringing_trunk, entry) { 04383 if (ringing_trunk->trunk == trunk_ref->trunk) { 04384 AST_LIST_REMOVE_CURRENT(&sla.ringing_trunks, entry); 04385 break; 04386 } 04387 } 04388 AST_LIST_TRAVERSE_SAFE_END 04389 ast_mutex_unlock(&sla.lock); 04390 04391 if (ringing_trunk) { 04392 answer_trunk_chan(ringing_trunk->trunk->chan); 04393 sla_change_trunk_state(ringing_trunk->trunk, SLA_TRUNK_STATE_UP, ALL_TRUNK_REFS, NULL); 04394 04395 free(ringing_trunk); 04396 04397 /* Queue up reprocessing ringing trunks, and then ringing stations again */ 04398 sla_queue_event(SLA_EVENT_RINGING_TRUNK); 04399 sla_queue_event(SLA_EVENT_DIAL_STATE); 04400 } 04401 } 04402 04403 trunk_ref->chan = chan; 04404 04405 if (!trunk_ref->trunk->chan) { 04406 ast_mutex_t cond_lock; 04407 ast_cond_t cond; 04408 pthread_t dont_care; 04409 pthread_attr_t attr; 04410 struct dial_trunk_args args = { 04411 .trunk_ref = trunk_ref, 04412 .station = station, 04413 .cond_lock = &cond_lock, 04414 .cond = &cond, 04415 }; 04416 sla_change_trunk_state(trunk_ref->trunk, SLA_TRUNK_STATE_UP, ALL_TRUNK_REFS, NULL); 04417 /* Create a thread to dial the trunk and dump it into the conference. 04418 * However, we want to wait until the trunk has been dialed and the 04419 * conference is created before continuing on here. */ 04420 ast_autoservice_start(chan); 04421 ast_mutex_init(&cond_lock); 04422 ast_cond_init(&cond, NULL); 04423 pthread_attr_init(&attr); 04424 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 04425 ast_mutex_lock(&cond_lock); 04426 ast_pthread_create_background(&dont_care, &attr, dial_trunk, &args); 04427 ast_cond_wait(&cond, &cond_lock); 04428 ast_mutex_unlock(&cond_lock); 04429 ast_mutex_destroy(&cond_lock); 04430 ast_cond_destroy(&cond); 04431 pthread_attr_destroy(&attr); 04432 ast_autoservice_stop(chan); 04433 if (!trunk_ref->trunk->chan) { 04434 ast_log(LOG_DEBUG, "Trunk didn't get created. chan: %lx\n", (long) trunk_ref->trunk->chan); 04435 pbx_builtin_setvar_helper(chan, "SLASTATION_STATUS", "CONGESTION"); 04436 sla_change_trunk_state(trunk_ref->trunk, SLA_TRUNK_STATE_IDLE, ALL_TRUNK_REFS, NULL); 04437 trunk_ref->chan = NULL; 04438 return 0; 04439 } 04440 } 04441 04442 if (ast_atomic_fetchadd_int((int *) &trunk_ref->trunk->active_stations, 1) == 0 && 04443 trunk_ref->trunk->on_hold) { 04444 trunk_ref->trunk->on_hold = 0; 04445 ast_indicate(trunk_ref->trunk->chan, AST_CONTROL_UNHOLD); 04446 sla_change_trunk_state(trunk_ref->trunk, SLA_TRUNK_STATE_UP, ALL_TRUNK_REFS, NULL); 04447 } 04448 04449 snprintf(conf_name, sizeof(conf_name), "SLA_%s", trunk_ref->trunk->name); 04450 ast_set_flag(&conf_flags, 04451 CONFFLAG_QUIET | CONFFLAG_MARKEDEXIT | CONFFLAG_PASS_DTMF | CONFFLAG_SLA_STATION); 04452 ast_answer(chan); 04453 conf = build_conf(conf_name, "", "", 0, 0, 1); 04454 if (conf) { 04455 conf_run(chan, conf, conf_flags.flags, NULL); 04456 dispose_conf(conf); 04457 conf = NULL; 04458 } 04459 trunk_ref->chan = NULL; 04460 if (ast_atomic_dec_and_test((int *) &trunk_ref->trunk->active_stations) && 04461 trunk_ref->state != SLA_TRUNK_STATE_ONHOLD_BYME) { 04462 strncat(conf_name, "|K", sizeof(conf_name) - strlen(conf_name) - 1); 04463 admin_exec(NULL, conf_name); 04464 trunk_ref->trunk->hold_stations = 0; 04465 sla_change_trunk_state(trunk_ref->trunk, SLA_TRUNK_STATE_IDLE, ALL_TRUNK_REFS, NULL); 04466 } 04467 04468 pbx_builtin_setvar_helper(chan, "SLASTATION_STATUS", "SUCCESS"); 04469 04470 return 0; 04471 }
static void sla_stop_ringing_station | ( | struct sla_ringing_station * | ringing_station, | |
enum sla_station_hangup | hangup | |||
) | [static] |
Definition at line 3499 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().
03501 { 03502 struct sla_ringing_trunk *ringing_trunk; 03503 struct sla_trunk_ref *trunk_ref; 03504 struct sla_station_ref *station_ref; 03505 03506 ast_dial_join(ringing_station->station->dial); 03507 ast_dial_destroy(ringing_station->station->dial); 03508 ringing_station->station->dial = NULL; 03509 03510 if (hangup == SLA_STATION_HANGUP_NORMAL) 03511 goto done; 03512 03513 /* If the station is being hung up because of a timeout, then add it to the 03514 * list of timed out stations on each of the ringing trunks. This is so 03515 * that when doing further processing to figure out which stations should be 03516 * ringing, which trunk to answer, determining timeouts, etc., we know which 03517 * ringing trunks we should ignore. */ 03518 AST_LIST_TRAVERSE(&sla.ringing_trunks, ringing_trunk, entry) { 03519 AST_LIST_TRAVERSE(&ringing_station->station->trunks, trunk_ref, entry) { 03520 if (ringing_trunk->trunk == trunk_ref->trunk) 03521 break; 03522 } 03523 if (!trunk_ref) 03524 continue; 03525 if (!(station_ref = sla_create_station_ref(ringing_station->station))) 03526 continue; 03527 AST_LIST_INSERT_TAIL(&ringing_trunk->timed_out_stations, station_ref, entry); 03528 } 03529 03530 done: 03531 free(ringing_station); 03532 }
static void sla_stop_ringing_trunk | ( | struct sla_ringing_trunk * | ringing_trunk | ) | [static] |
Definition at line 3484 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().
03485 { 03486 char buf[80]; 03487 struct sla_station_ref *station_ref; 03488 03489 snprintf(buf, sizeof(buf), "SLA_%s|K", ringing_trunk->trunk->name); 03490 admin_exec(NULL, buf); 03491 sla_change_trunk_state(ringing_trunk->trunk, SLA_TRUNK_STATE_IDLE, ALL_TRUNK_REFS, NULL); 03492 03493 while ((station_ref = AST_LIST_REMOVE_HEAD(&ringing_trunk->timed_out_stations, entry))) 03494 free(station_ref); 03495 03496 free(ringing_trunk); 03497 }
static void* sla_thread | ( | void * | data | ) | [static] |
Definition at line 4132 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().
04133 { 04134 struct sla_failed_station *failed_station; 04135 struct sla_ringing_station *ringing_station; 04136 04137 ast_mutex_lock(&sla.lock); 04138 04139 while (!sla.stop) { 04140 struct sla_event *event; 04141 struct timespec ts = { 0, }; 04142 unsigned int have_timeout = 0; 04143 04144 if (AST_LIST_EMPTY(&sla.event_q)) { 04145 if ((have_timeout = sla_process_timers(&ts))) 04146 ast_cond_timedwait(&sla.cond, &sla.lock, &ts); 04147 else 04148 ast_cond_wait(&sla.cond, &sla.lock); 04149 if (sla.stop) 04150 break; 04151 } 04152 04153 if (have_timeout) 04154 sla_process_timers(NULL); 04155 04156 while ((event = AST_LIST_REMOVE_HEAD(&sla.event_q, entry))) { 04157 ast_mutex_unlock(&sla.lock); 04158 switch (event->type) { 04159 case SLA_EVENT_HOLD: 04160 sla_handle_hold_event(event); 04161 break; 04162 case SLA_EVENT_DIAL_STATE: 04163 sla_handle_dial_state_event(); 04164 break; 04165 case SLA_EVENT_RINGING_TRUNK: 04166 sla_handle_ringing_trunk_event(); 04167 break; 04168 } 04169 free(event); 04170 ast_mutex_lock(&sla.lock); 04171 } 04172 } 04173 04174 ast_mutex_unlock(&sla.lock); 04175 04176 while ((ringing_station = AST_LIST_REMOVE_HEAD(&sla.ringing_stations, entry))) 04177 free(ringing_station); 04178 04179 while ((failed_station = AST_LIST_REMOVE_HEAD(&sla.failed_stations, entry))) 04180 free(failed_station); 04181 04182 return NULL; 04183 }
static int sla_trunk_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Definition at line 4506 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().
04507 { 04508 const char *trunk_name = data; 04509 char conf_name[MAX_CONFNUM]; 04510 struct ast_conference *conf; 04511 struct ast_flags conf_flags = { 0 }; 04512 struct sla_trunk *trunk; 04513 struct sla_ringing_trunk *ringing_trunk; 04514 04515 AST_RWLIST_RDLOCK(&sla_trunks); 04516 trunk = sla_find_trunk(trunk_name); 04517 AST_RWLIST_UNLOCK(&sla_trunks); 04518 if (!trunk) { 04519 ast_log(LOG_ERROR, "SLA Trunk '%s' not found!\n", trunk_name); 04520 pbx_builtin_setvar_helper(chan, "SLATRUNK_STATUS", "FAILURE"); 04521 return 0; 04522 } 04523 if (trunk->chan) { 04524 ast_log(LOG_ERROR, "Call came in on %s, but the trunk is already in use!\n", 04525 trunk_name); 04526 pbx_builtin_setvar_helper(chan, "SLATRUNK_STATUS", "FAILURE"); 04527 return 0; 04528 } 04529 trunk->chan = chan; 04530 04531 if (!(ringing_trunk = queue_ringing_trunk(trunk))) { 04532 pbx_builtin_setvar_helper(chan, "SLATRUNK_STATUS", "FAILURE"); 04533 return 0; 04534 } 04535 04536 snprintf(conf_name, sizeof(conf_name), "SLA_%s", trunk_name); 04537 conf = build_conf(conf_name, "", "", 1, 1, 1); 04538 if (!conf) { 04539 pbx_builtin_setvar_helper(chan, "SLATRUNK_STATUS", "FAILURE"); 04540 return 0; 04541 } 04542 ast_set_flag(&conf_flags, 04543 CONFFLAG_QUIET | CONFFLAG_MARKEDEXIT | CONFFLAG_MARKEDUSER | CONFFLAG_PASS_DTMF | CONFFLAG_NO_AUDIO_UNTIL_UP); 04544 ast_indicate(chan, AST_CONTROL_RINGING); 04545 conf_run(chan, conf, conf_flags.flags, NULL); 04546 dispose_conf(conf); 04547 conf = NULL; 04548 trunk->chan = NULL; 04549 trunk->on_hold = 0; 04550 04551 sla_change_trunk_state(trunk, SLA_TRUNK_STATE_IDLE, ALL_TRUNK_REFS, NULL); 04552 04553 if (!pbx_builtin_getvar_helper(chan, "SLATRUNK_STATUS")) 04554 pbx_builtin_setvar_helper(chan, "SLATRUNK_STATUS", "SUCCESS"); 04555 04556 /* Remove the entry from the list of ringing trunks if it is still there. */ 04557 ast_mutex_lock(&sla.lock); 04558 AST_LIST_TRAVERSE_SAFE_BEGIN(&sla.ringing_trunks, ringing_trunk, entry) { 04559 if (ringing_trunk->trunk == trunk) { 04560 AST_LIST_REMOVE_CURRENT(&sla.ringing_trunks, entry); 04561 break; 04562 } 04563 } 04564 AST_LIST_TRAVERSE_SAFE_END 04565 ast_mutex_unlock(&sla.lock); 04566 if (ringing_trunk) { 04567 free(ringing_trunk); 04568 pbx_builtin_setvar_helper(chan, "SLATRUNK_STATUS", "UNANSWERED"); 04569 /* Queue reprocessing of ringing trunks to make stations stop ringing 04570 * that shouldn't be ringing after this trunk stopped. */ 04571 sla_queue_event(SLA_EVENT_RINGING_TRUNK); 04572 } 04573 04574 return 0; 04575 }
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 5007 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().
05008 { 05009 int res = 0; 05010 05011 ast_cli_unregister_multiple(cli_meetme, ARRAY_LEN(cli_meetme)); 05012 res = ast_manager_unregister("MeetmeMute"); 05013 res |= ast_manager_unregister("MeetmeUnmute"); 05014 res |= ast_unregister_application(app3); 05015 res |= ast_unregister_application(app2); 05016 res |= ast_unregister_application(app); 05017 res |= ast_unregister_application(slastation_app); 05018 res |= ast_unregister_application(slatrunk_app); 05019 05020 ast_devstate_prov_del("Meetme"); 05021 ast_devstate_prov_del("SLA"); 05022 05023 ast_module_user_hangup_all(); 05024 05025 sla_destroy(); 05026 05027 return res; 05028 }
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 5064 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 5064 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().