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