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