Meet me conference bridge and Shared Line Appearances. More...
#include "asterisk.h"#include <dahdi/user.h>#include "asterisk/lock.h"#include "asterisk/file.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/cli.h"#include "asterisk/say.h"#include "asterisk/utils.h"#include "asterisk/translate.h"#include "asterisk/ulaw.h"#include "asterisk/astobj2.h"#include "asterisk/devicestate.h"#include "asterisk/dial.h"#include "asterisk/causes.h"#include "asterisk/paths.h"#include "enter.h"#include "leave.h"
Go to the source code of this file.
Data Structures | |
| struct | announce_listitem |
| struct | ast_conf_user |
| The MeetMe User object. More... | |
| 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 | DATE_FORMAT "%Y-%m-%d %H:%M:%S" |
| #define | DEFAULT_AUDIO_BUFFERS 32 |
| #define | MAX_CONFNUM 80 |
| #define | MAX_PIN 80 |
| #define | MC_DATA_FORMAT "%-12.12s %4.4d %4.4s %02d:%02d:%02d %-8s %-6s\n" |
| #define | MC_HEADER_FORMAT "%-14s %-14s %-10s %-8s %-8s %-6s\n" |
| #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), ADMINFLAG_T_REQUEST = (1 << 4) } |
| enum | { CONFFLAG_ADMIN = (1 << 0), CONFFLAG_MONITOR = (1 << 1), CONFFLAG_KEYEXIT = (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_KICK_CONTINUE = (1 << 28), CONFFLAG_DURATION_STOP = (1 << 29), CONFFLAG_DURATION_LIMIT = (1 << 30), CONFFLAG_NO_AUDIO_UNTIL_UP = (1 << 31) } |
| enum | { OPT_ARG_WAITMARKED = 0, OPT_ARG_EXITKEYS = 1, OPT_ARG_DURATION_STOP = 2, OPT_ARG_DURATION_LIMIT = 3, OPT_ARG_MOH_CLASS = 4, OPT_ARG_ARRAY_SIZE = 5 } |
| enum | { SLA_TRUNK_OPT_MOH = (1 << 0) } |
| enum | { SLA_TRUNK_OPT_ARG_MOH_CLASS = 0, SLA_TRUNK_OPT_ARG_ARRAY_SIZE = 1 } |
| 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, SLA_EVENT_RELOAD, SLA_EVENT_CHECK_RELOAD } |
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 | acf_meetme_info (struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len) |
| static int | acf_meetme_info_eval (char *keyword, struct ast_conference *conf) |
| static int | action_meetmelist (struct mansession *s, const struct message *m) |
| 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, const struct ast_channel *chan) |
| 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 int | channel_admin_exec (struct ast_channel *chan, void *data) |
| 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 void | conf_start_moh (struct ast_channel *chan, const char *musicclass) |
| 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, char *optargs[], int *too_early) |
| 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 char * | meetme_cmd (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static int | meetmemute (struct mansession *s, const struct message *m, int mute) |
| static enum ast_device_state | 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 void | sla_check_reload (void) |
| Check if we can do a reload of SLA, and do it if we can. | |
| 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 rm) |
| 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 (int reload) |
| 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 char * | sla_show_stations (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | sla_show_trunks (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static enum ast_device_state | sla_state (const char *data) |
| static enum ast_device_state | sla_state_to_devstate (enum sla_trunk_state state) |
| 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 , .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 = "a9c98e5d177805051735cb5b0b16b0a0" , .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 char * | app4 = "MeetMeChannelAdmin" |
| static 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 const char * | descrip4 |
| static int | earlyalert |
| static int | endalert |
| static int | fuzzystart |
| static char const | gain_map [] |
| static char | mandescr_meetmelist [] |
| static struct ast_custom_function | meetme_info_acf |
| static struct ast_app_option | meetme_opts [128] = { [ 'A' ] = { .flag = CONFFLAG_MARKEDUSER }, [ 'a' ] = { .flag = CONFFLAG_ADMIN }, [ 'b' ] = { .flag = CONFFLAG_AGI }, [ 'c' ] = { .flag = CONFFLAG_ANNOUNCEUSERCOUNT }, [ 'C' ] = { .flag = CONFFLAG_KICK_CONTINUE }, [ 'D' ] = { .flag = CONFFLAG_DYNAMICPIN }, [ 'd' ] = { .flag = CONFFLAG_DYNAMIC }, [ 'E' ] = { .flag = CONFFLAG_EMPTYNOPIN }, [ 'e' ] = { .flag = CONFFLAG_EMPTY }, [ 'F' ] = { .flag = CONFFLAG_PASS_DTMF }, [ 'i' ] = { .flag = CONFFLAG_INTROUSER }, [ 'I' ] = { .flag = CONFFLAG_INTROUSERNOREVIEW }, [ 'M' ] = { .flag = CONFFLAG_MOH , .arg_index = OPT_ARG_MOH_CLASS + 1 }, [ 'm' ] = { .flag = CONFFLAG_STARTMUTED }, [ 'o' ] = { .flag = CONFFLAG_OPTIMIZETALKER }, [ 'P' ] = { .flag = CONFFLAG_ALWAYSPROMPT }, [ 'p' ] = { .flag = CONFFLAG_KEYEXIT , .arg_index = OPT_ARG_EXITKEYS + 1 }, [ '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 }, [ 'S' ] = { .flag = CONFFLAG_DURATION_STOP , .arg_index = OPT_ARG_DURATION_STOP + 1 }, [ 'L' ] = { .flag = CONFFLAG_DURATION_LIMIT , .arg_index = OPT_ARG_DURATION_LIMIT + 1 }, } |
| static int | rt_log_members |
| static int | rt_schedule |
| struct { | |
| unsigned int attempt_callerid:1 | |
| ast_cond_t cond | |
| struct { | |
| struct sla_event * first | |
| struct sla_event * last | |
| } event_q | |
| struct { | |
| struct sla_failed_station * first | |
| struct sla_failed_station * last | |
| } failed_stations | |
| ast_mutex_t lock | |
| unsigned int reload:1 | |
| struct { | |
| struct sla_ringing_station * first | |
| struct sla_ringing_station * last | |
| } ringing_stations | |
| struct { | |
| struct sla_ringing_trunk * first | |
| struct 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 struct ast_app_option | sla_trunk_opts [128] = { [ 'M' ] = { .flag = SLA_TRUNK_OPT_MOH , .arg_index = SLA_TRUNK_OPT_ARG_MOH_CLASS + 1 }, } |
| 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" |
| static const char * | synopsis4 = "MeetMe conference Administration (channel specific)" |
Meet me conference bridge and Shared Line Appearances.
Definition in file app_meetme.c.
| #define AST_FRAME_BITS 32 |
Definition at line 86 of file app_meetme.c.
Referenced by conf_free(), conf_run(), and recordthread().
| #define CONF_SIZE 320 |
Definition at line 105 of file app_meetme.c.
| #define CONFIG_FILE_NAME "meetme.conf" |
Definition at line 66 of file app_meetme.c.
| #define DATE_FORMAT "%Y-%m-%d %H:%M:%S" |
String format for scheduled conferences
Definition at line 73 of file app_meetme.c.
Referenced by append_date(), build_radius_record(), execute_cb(), find_conf_realtime(), get_date(), manager_log(), pgsql_log(), and sqlite_log().
| #define DEFAULT_AUDIO_BUFFERS 32 |
each buffer is 20ms, so this is 640ms total
Definition at line 70 of file app_meetme.c.
Referenced by load_config_meetme().
| #define MAX_CONFNUM 80 |
Definition at line 359 of file app_meetme.c.
Referenced by conf_exec(), dial_trunk(), meetme_cmd(), sla_station_exec(), and sla_trunk_exec().
| #define MAX_PIN 80 |
Definition at line 360 of file app_meetme.c.
Referenced by conf_exec().
| #define MC_DATA_FORMAT "%-12.12s %4.4d %4.4s %02d:%02d:%02d %-8s %-6s\n" |
Referenced by meetme_cmd().
| #define MC_HEADER_FORMAT "%-14s %-14s %-10s %-8s %-8s %-6s\n" |
Referenced by meetme_cmd().
| #define MEETME_DELAYDETECTENDTALK 1000 |
Definition at line 84 of file app_meetme.c.
Referenced by conf_run().
| #define MEETME_DELAYDETECTTALK 300 |
Definition at line 83 of file app_meetme.c.
Referenced by conf_run().
| #define S | ( | e | ) | case e: return # e; |
Referenced by sms_readfile(), and trunkstate2str().
| #define SLA_CONFIG_FILE "sla.conf" |
Definition at line 67 of file app_meetme.c.
Referenced by sla_build_station(), sla_build_trunk(), and sla_load_config().
| anonymous enum |
| ADMINFLAG_MUTED |
User is muted |
| ADMINFLAG_SELFMUTED |
User muted self |
| ADMINFLAG_KICKME |
User has been kicked |
| ADMINFLAG_T_REQUEST |
User has requested to speak |
Definition at line 75 of file app_meetme.c.
00075 { 00076 ADMINFLAG_MUTED = (1 << 1), /*!< User is muted */ 00077 ADMINFLAG_SELFMUTED = (1 << 2), /*!< User muted self */ 00078 ADMINFLAG_KICKME = (1 << 3), /*!< User has been kicked */ 00079 /*! User has requested to speak */ 00080 ADMINFLAG_T_REQUEST = (1 << 4), 00081 };
| anonymous enum |
| CONFFLAG_ADMIN |
user has admin access on the conference |
| CONFFLAG_MONITOR |
If set the user can only receive audio from the conference |
| CONFFLAG_KEYEXIT |
If set asterisk will exit conference when key defined in p() option is pressed |
| CONFFLAG_STARMENU |
If set asterisk will provide a menu to the user when '*' is pressed |
| CONFFLAG_TALKER |
If set the use can only send audio to the conference |
| CONFFLAG_QUIET |
If set there will be no enter or leave sounds |
| CONFFLAG_ANNOUNCEUSERCOUNT |
If set, when user joins the conference, they will be told the number of users that are already in |
| CONFFLAG_AGI |
Set to run AGI Script in Background |
| CONFFLAG_MOH |
Set to have music on hold when user is alone in conference |
| CONFFLAG_MARKEDEXIT |
If set the MeetMe will return if all marked with this flag left |
| CONFFLAG_WAITMARKED |
If set, the MeetMe will wait until a marked user enters |
| CONFFLAG_EXIT_CONTEXT |
If set, the MeetMe will exit to the specified context |
| CONFFLAG_MARKEDUSER |
If set, the user will be marked |
| CONFFLAG_INTROUSER |
If set, user will be ask record name on entry of conference |
| CONFFLAG_RECORDCONF |
If set, the MeetMe will be recorded |
| CONFFLAG_MONITORTALKER |
If set, the user will be monitored if the user is talking or not |
| CONFFLAG_DYNAMIC | |
| CONFFLAG_DYNAMICPIN | |
| CONFFLAG_EMPTY | |
| CONFFLAG_EMPTYNOPIN | |
| CONFFLAG_ALWAYSPROMPT | |
| CONFFLAG_OPTIMIZETALKER | |
| CONFFLAG_NOONLYPERSON |
If set, won't speak the extra prompt when the first person enters the conference |
| CONFFLAG_INTROUSERNOREVIEW |
If set, user will be asked to record name on entry of conference without review |
| CONFFLAG_STARTMUTED |
If set, the user will be initially self-muted |
| CONFFLAG_PASS_DTMF |
Pass DTMF through the conference |
| CONFFLAG_SLA_STATION | |
| CONFFLAG_SLA_TRUNK | |
| CONFFLAG_KICK_CONTINUE |
If set, the user should continue in the dialplan if kicked out |
| CONFFLAG_DURATION_STOP | |
| CONFFLAG_DURATION_LIMIT | |
| CONFFLAG_NO_AUDIO_UNTIL_UP |
Do not write any audio to this channel until the state is up. |
Definition at line 107 of file app_meetme.c.
00107 { 00108 /*! user has admin access on the conference */ 00109 CONFFLAG_ADMIN = (1 << 0), 00110 /*! If set the user can only receive audio from the conference */ 00111 CONFFLAG_MONITOR = (1 << 1), 00112 /*! If set asterisk will exit conference when key defined in p() option is pressed */ 00113 CONFFLAG_KEYEXIT = (1 << 2), 00114 /*! If set asterisk will provide a menu to the user when '*' is pressed */ 00115 CONFFLAG_STARMENU = (1 << 3), 00116 /*! If set the use can only send audio to the conference */ 00117 CONFFLAG_TALKER = (1 << 4), 00118 /*! If set there will be no enter or leave sounds */ 00119 CONFFLAG_QUIET = (1 << 5), 00120 /*! If set, when user joins the conference, they will be told the number 00121 * of users that are already in */ 00122 CONFFLAG_ANNOUNCEUSERCOUNT = (1 << 6), 00123 /*! Set to run AGI Script in Background */ 00124 CONFFLAG_AGI = (1 << 7), 00125 /*! Set to have music on hold when user is alone in conference */ 00126 CONFFLAG_MOH = (1 << 8), 00127 /*! If set the MeetMe will return if all marked with this flag left */ 00128 CONFFLAG_MARKEDEXIT = (1 << 9), 00129 /*! If set, the MeetMe will wait until a marked user enters */ 00130 CONFFLAG_WAITMARKED = (1 << 10), 00131 /*! If set, the MeetMe will exit to the specified context */ 00132 CONFFLAG_EXIT_CONTEXT = (1 << 11), 00133 /*! If set, the user will be marked */ 00134 CONFFLAG_MARKEDUSER = (1 << 12), 00135 /*! If set, user will be ask record name on entry of conference */ 00136 CONFFLAG_INTROUSER = (1 << 13), 00137 /*! If set, the MeetMe will be recorded */ 00138 CONFFLAG_RECORDCONF = (1<< 14), 00139 /*! If set, the user will be monitored if the user is talking or not */ 00140 CONFFLAG_MONITORTALKER = (1 << 15), 00141 CONFFLAG_DYNAMIC = (1 << 16), 00142 CONFFLAG_DYNAMICPIN = (1 << 17), 00143 CONFFLAG_EMPTY = (1 << 18), 00144 CONFFLAG_EMPTYNOPIN = (1 << 19), 00145 CONFFLAG_ALWAYSPROMPT = (1 << 20), 00146 /*! If set, treat talking users as muted users */ 00147 CONFFLAG_OPTIMIZETALKER = (1 << 21), 00148 /*! If set, won't speak the extra prompt when the first person 00149 * enters the conference */ 00150 CONFFLAG_NOONLYPERSON = (1 << 22), 00151 /*! If set, user will be asked to record name on entry of conference 00152 * without review */ 00153 CONFFLAG_INTROUSERNOREVIEW = (1 << 23), 00154 /*! If set, the user will be initially self-muted */ 00155 CONFFLAG_STARTMUTED = (1 << 24), 00156 /*! Pass DTMF through the conference */ 00157 CONFFLAG_PASS_DTMF = (1 << 25), 00158 CONFFLAG_SLA_STATION = (1 << 26), 00159 CONFFLAG_SLA_TRUNK = (1 << 27), 00160 /*! If set, the user should continue in the dialplan if kicked out */ 00161 CONFFLAG_KICK_CONTINUE = (1 << 28), 00162 CONFFLAG_DURATION_STOP = (1 << 29), 00163 CONFFLAG_DURATION_LIMIT = (1 << 30), 00164 /*! Do not write any audio to this channel until the state is up. */ 00165 CONFFLAG_NO_AUDIO_UNTIL_UP = (1 << 31), 00166 };
| anonymous enum |
| OPT_ARG_WAITMARKED | |
| OPT_ARG_EXITKEYS | |
| OPT_ARG_DURATION_STOP | |
| OPT_ARG_DURATION_LIMIT | |
| OPT_ARG_MOH_CLASS | |
| OPT_ARG_ARRAY_SIZE |
Definition at line 168 of file app_meetme.c.
00168 { 00169 OPT_ARG_WAITMARKED = 0, 00170 OPT_ARG_EXITKEYS = 1, 00171 OPT_ARG_DURATION_STOP = 2, 00172 OPT_ARG_DURATION_LIMIT = 3, 00173 OPT_ARG_MOH_CLASS = 4, 00174 OPT_ARG_ARRAY_SIZE = 5, 00175 };
| anonymous enum |
Definition at line 5212 of file app_meetme.c.
05212 { 05213 SLA_TRUNK_OPT_MOH = (1 << 0), 05214 };
| anonymous enum |
Definition at line 5216 of file app_meetme.c.
05216 { 05217 SLA_TRUNK_OPT_ARG_MOH_CLASS = 0, 05218 SLA_TRUNK_OPT_ARG_ARRAY_SIZE = 1, 05219 };
| enum announcetypes |
Definition at line 362 of file app_meetme.c.
00362 { 00363 CONF_HASJOIN, 00364 CONF_HASLEFT 00365 };
| enum entrance_sound |
Definition at line 93 of file app_meetme.c.
| enum recording_state |
Definition at line 98 of file app_meetme.c.
00098 { 00099 MEETME_RECORD_OFF, 00100 MEETME_RECORD_STARTED, 00101 MEETME_RECORD_ACTIVE, 00102 MEETME_RECORD_TERMINATE 00103 };
| 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 |
| SLA_EVENT_RELOAD |
A reload of configuration has been requested |
| SLA_EVENT_CHECK_RELOAD |
Poke the SLA thread so it can check if it can perform a reload |
Definition at line 552 of file app_meetme.c.
00552 { 00553 /*! A station has put the call on hold */ 00554 SLA_EVENT_HOLD, 00555 /*! The state of a dial has changed */ 00556 SLA_EVENT_DIAL_STATE, 00557 /*! The state of a ringing trunk has changed */ 00558 SLA_EVENT_RINGING_TRUNK, 00559 /*! A reload of configuration has been requested */ 00560 SLA_EVENT_RELOAD, 00561 /*! Poke the SLA thread so it can check if it can perform a reload */ 00562 SLA_EVENT_CHECK_RELOAD, 00563 };
| enum sla_hold_access |
Definition at line 462 of file app_meetme.c.
00462 { 00463 /*! This means that any station can put it on hold, and any station 00464 * can retrieve the call from hold. */ 00465 SLA_HOLD_OPEN, 00466 /*! This means that only the station that put the call on hold may 00467 * retrieve it from hold. */ 00468 SLA_HOLD_PRIVATE, 00469 };
| enum sla_station_hangup |
Definition at line 589 of file app_meetme.c.
00589 { 00590 SLA_STATION_HANGUP_NORMAL, 00591 SLA_STATION_HANGUP_TIMEOUT, 00592 };
| 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 454 of file app_meetme.c.
00454 { 00455 SLA_TRUNK_STATE_IDLE, 00456 SLA_TRUNK_STATE_RINGING, 00457 SLA_TRUNK_STATE_UP, 00458 SLA_TRUNK_STATE_ONHOLD, 00459 SLA_TRUNK_STATE_ONHOLD_BYME, 00460 };
| enum sla_which_trunk_refs |
Definition at line 449 of file app_meetme.c.
00449 { 00450 ALL_TRUNK_REFS, 00451 INACTIVE_TRUNK_REFS, 00452 };
| enum volume_action |
Definition at line 88 of file app_meetme.c.
| static void __reg_module | ( | void | ) | [static] |
Definition at line 5913 of file app_meetme.c.
| static void __unreg_module | ( | void | ) | [static] |
Definition at line 5913 of file app_meetme.c.
| static int acf_meetme_info | ( | struct ast_channel * | chan, | |
| const char * | cmd, | |||
| char * | data, | |||
| char * | buf, | |||
| size_t | len | |||
| ) | [static] |
Definition at line 5768 of file app_meetme.c.
References acf_meetme_info_eval(), AST_APP_ARG, AST_DECLARE_APP_ARGS, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), ast_conference::confno, ast_conference::list, LOG_ERROR, and parse().
05769 { 05770 struct ast_conference *conf; 05771 char *parse; 05772 int result = -2; /* only non-negative numbers valid, -1 is used elsewhere */ 05773 AST_DECLARE_APP_ARGS(args, 05774 AST_APP_ARG(keyword); 05775 AST_APP_ARG(confno); 05776 ); 05777 05778 if (ast_strlen_zero(data)) { 05779 ast_log(LOG_ERROR, "Syntax: MEETME_INFO() requires two arguments\n"); 05780 return -1; 05781 } 05782 05783 parse = ast_strdupa(data); 05784 AST_STANDARD_APP_ARGS(args, parse); 05785 05786 if (ast_strlen_zero(args.keyword)) { 05787 ast_log(LOG_ERROR, "Syntax: MEETME_INFO() requires a keyword\n"); 05788 return -1; 05789 } 05790 05791 if (ast_strlen_zero(args.confno)) { 05792 ast_log(LOG_ERROR, "Syntax: MEETME_INFO() requires a conference number\n"); 05793 return -1; 05794 } 05795 05796 AST_LIST_LOCK(&confs); 05797 AST_LIST_TRAVERSE(&confs, conf, list) { 05798 if (!strcmp(args.confno, conf->confno)) { 05799 result = acf_meetme_info_eval(args.keyword, conf); 05800 break; 05801 } 05802 } 05803 AST_LIST_UNLOCK(&confs); 05804 05805 if (result > -1) { 05806 snprintf(buf, len, "%d", result); 05807 } else if (result == -1) { 05808 snprintf(buf, len, "%s %s", "Error: invalid keyword:", args.keyword); 05809 } else if (result == -2) { 05810 snprintf(buf, len, "Error: conference (%s) not found", args.confno); 05811 } 05812 05813 return 0; 05814 }
| static int acf_meetme_info_eval | ( | char * | keyword, | |
| struct ast_conference * | conf | |||
| ) | [static] |
Definition at line 5750 of file app_meetme.c.
References ast_conference::isdynamic, ast_conference::locked, ast_conference::start, and ast_conference::users.
Referenced by acf_meetme_info().
05751 { 05752 if (!strcasecmp("lock", keyword)) { 05753 return conf->locked; 05754 } else if (!strcasecmp("parties", keyword)) { 05755 return conf->users; 05756 } else if (!strcasecmp("activity", keyword)) { 05757 time_t now; 05758 now = time(NULL); 05759 return (now - conf->start); 05760 } else if (!strcasecmp("dynamic", keyword)) { 05761 return conf->isdynamic; 05762 } else { 05763 return -1; 05764 } 05765 05766 }
| static int action_meetmelist | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 3720 of file app_meetme.c.
References ADMINFLAG_MUTED, ADMINFLAG_SELFMUTED, ast_conf_user::adminflags, AST_LIST_EMPTY, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_strlen_zero(), astman_append(), astman_get_header(), astman_send_error(), astman_send_listack(), ast_conf_user::chan, ast_channel::cid, ast_callerid::cid_name, ast_callerid::cid_num, CONFFLAG_ADMIN, CONFFLAG_MARKEDUSER, CONFFLAG_MONITOR, CONFFLAG_TALKER, ast_conference::confno, ast_conf_user::list, S_OR, ast_conf_user::talking, total, ast_conf_user::user_no, ast_conf_user::userflags, and ast_conference::userlist.
Referenced by load_module().
03721 { 03722 const char *actionid = astman_get_header(m, "ActionID"); 03723 const char *conference = astman_get_header(m, "Conference"); 03724 char idText[80] = ""; 03725 struct ast_conference *cnf; 03726 struct ast_conf_user *user; 03727 int total = 0; 03728 03729 if (!ast_strlen_zero(actionid)) 03730 snprintf(idText, sizeof(idText), "ActionID: %s\r\n", actionid); 03731 03732 if (AST_LIST_EMPTY(&confs)) { 03733 astman_send_error(s, m, "No active conferences."); 03734 return 0; 03735 } 03736 03737 astman_send_listack(s, m, "Meetme user list will follow", "start"); 03738 03739 /* Find the right conference */ 03740 AST_LIST_LOCK(&confs); 03741 AST_LIST_TRAVERSE(&confs, cnf, list) { 03742 /* If we ask for one particular, and this isn't it, skip it */ 03743 if (!ast_strlen_zero(conference) && strcmp(cnf->confno, conference)) 03744 continue; 03745 03746 /* Show all the users */ 03747 AST_LIST_TRAVERSE(&cnf->userlist, user, list) { 03748 total++; 03749 astman_append(s, 03750 "Event: MeetmeList\r\n" 03751 "%s" 03752 "Conference: %s\r\n" 03753 "UserNumber: %d\r\n" 03754 "CallerIDNum: %s\r\n" 03755 "CallerIDName: %s\r\n" 03756 "Channel: %s\r\n" 03757 "Admin: %s\r\n" 03758 "Role: %s\r\n" 03759 "MarkedUser: %s\r\n" 03760 "Muted: %s\r\n" 03761 "Talking: %s\r\n" 03762 "\r\n", 03763 idText, 03764 cnf->confno, 03765 user->user_no, 03766 S_OR(user->chan->cid.cid_num, "<unknown>"), 03767 S_OR(user->chan->cid.cid_name, "<no name>"), 03768 user->chan->name, 03769 user->userflags & CONFFLAG_ADMIN ? "Yes" : "No", 03770 user->userflags & CONFFLAG_MONITOR ? "Listen only" : user->userflags & CONFFLAG_TALKER ? "Talk only" : "Talk and listen", 03771 user->userflags & CONFFLAG_MARKEDUSER ? "Yes" : "No", 03772 user->adminflags & ADMINFLAG_MUTED ? "By admin" : user->adminflags & ADMINFLAG_SELFMUTED ? "By self" : "No", 03773 user->talking > 0 ? "Yes" : user->talking == 0 ? "No" : "Not monitored"); 03774 } 03775 } 03776 AST_LIST_UNLOCK(&confs); 03777 /* Send final confirmation */ 03778 astman_append(s, 03779 "Event: MeetmeListComplete\r\n" 03780 "EventList: Complete\r\n" 03781 "ListItems: %d\r\n" 03782 "%s" 03783 "\r\n", total, idText); 03784 return 0; 03785 }
| static int action_meetmemute | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 3702 of file app_meetme.c.
References meetmemute().
Referenced by load_module().
03703 { 03704 return meetmemute(s, m, 1); 03705 }
| static int action_meetmeunmute | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 3707 of file app_meetme.c.
References meetmemute().
Referenced by load_module().
03708 { 03709 return meetmemute(s, m, 0); 03710 }
| static int admin_exec | ( | struct ast_channel * | chan, | |
| void * | data | |||
| ) | [static] |
The MeetMeadmin application.
Definition at line 3432 of file app_meetme.c.
References ADMINFLAG_KICKME, ADMINFLAG_MUTED, ADMINFLAG_SELFMUTED, ADMINFLAG_T_REQUEST, 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_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), CONFFLAG_ADMIN, ast_conference::confno, dispose_conf(), find_user(), ast_conf_user::list, 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, VOL_DOWN, and VOL_UP.
Referenced by load_module(), meetme_cmd(), run_station(), sla_station_exec(), and sla_stop_ringing_trunk().
03432 { 03433 char *params; 03434 struct ast_conference *cnf; 03435 struct ast_conf_user *user = NULL; 03436 AST_DECLARE_APP_ARGS(args, 03437 AST_APP_ARG(confno); 03438 AST_APP_ARG(command); 03439 AST_APP_ARG(user); 03440 ); 03441 03442 if (ast_strlen_zero(data)) { 03443 ast_log(LOG_WARNING, "MeetMeAdmin requires an argument!\n"); 03444 return -1; 03445 } 03446 03447 params = ast_strdupa(data); 03448 AST_STANDARD_APP_ARGS(args, params); 03449 03450 if (!args.command) { 03451 ast_log(LOG_WARNING, "MeetmeAdmin requires a command!\n"); 03452 return -1; 03453 } 03454 03455 AST_LIST_LOCK(&confs); 03456 AST_LIST_TRAVERSE(&confs, cnf, list) { 03457 if (!strcmp(cnf->confno, args.confno)) 03458 break; 03459 } 03460 03461 if (!cnf) { 03462 ast_log(LOG_WARNING, "Conference number '%s' not found!\n", args.confno); 03463 AST_LIST_UNLOCK(&confs); 03464 return 0; 03465 } 03466 03467 ast_atomic_fetchadd_int(&cnf->refcount, 1); 03468 03469 if (args.user) 03470 user = find_user(cnf, args.user); 03471 03472 switch (*args.command) { 03473 case 76: /* L: Lock */ 03474 cnf->locked = 1; 03475 break; 03476 case 108: /* l: Unlock */ 03477 cnf->locked = 0; 03478 break; 03479 case 75: /* K: kick all users */ 03480 AST_LIST_TRAVERSE(&cnf->userlist, user, list) 03481 user->adminflags |= ADMINFLAG_KICKME; 03482 break; 03483 case 101: /* e: Eject last user*/ 03484 user = AST_LIST_LAST(&cnf->userlist); 03485 if (!(user->userflags & CONFFLAG_ADMIN)) 03486 user->adminflags |= ADMINFLAG_KICKME; 03487 else 03488 ast_log(LOG_NOTICE, "Not kicking last user, is an Admin!\n"); 03489 break; 03490 case 77: /* M: Mute */ 03491 if (user) { 03492 user->adminflags |= ADMINFLAG_MUTED; 03493 } else 03494 ast_log(LOG_NOTICE, "Specified User not found!\n"); 03495 break; 03496 case 78: /* N: Mute all (non-admin) users */ 03497 AST_LIST_TRAVERSE(&cnf->userlist, user, list) { 03498 if (!(user->userflags & CONFFLAG_ADMIN)) 03499 user->adminflags |= ADMINFLAG_MUTED; 03500 } 03501 break; 03502 case 109: /* m: Unmute */ 03503 if (user) { 03504 user->adminflags &= ~(ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED | ADMINFLAG_T_REQUEST); 03505 } else 03506 ast_log(LOG_NOTICE, "Specified User not found!\n"); 03507 break; 03508 case 110: /* n: Unmute all users */ 03509 AST_LIST_TRAVERSE(&cnf->userlist, user, list) 03510 user->adminflags &= ~(ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED | ADMINFLAG_T_REQUEST); 03511 break; 03512 case 107: /* k: Kick user */ 03513 if (user) 03514 user->adminflags |= ADMINFLAG_KICKME; 03515 else 03516 ast_log(LOG_NOTICE, "Specified User not found!\n"); 03517 break; 03518 case 118: /* v: Lower all users listen volume */ 03519 AST_LIST_TRAVERSE(&cnf->userlist, user, list) 03520 tweak_listen_volume(user, VOL_DOWN); 03521 break; 03522 case 86: /* V: Raise all users listen volume */ 03523 AST_LIST_TRAVERSE(&cnf->userlist, user, list) 03524 tweak_listen_volume(user, VOL_UP); 03525 break; 03526 case 115: /* s: Lower all users speaking volume */ 03527 AST_LIST_TRAVERSE(&cnf->userlist, user, list) 03528 tweak_talk_volume(user, VOL_DOWN); 03529 break; 03530 case 83: /* S: Raise all users speaking volume */ 03531 AST_LIST_TRAVERSE(&cnf->userlist, user, list) 03532 tweak_talk_volume(user, VOL_UP); 03533 break; 03534 case 82: /* R: Reset all volume levels */ 03535 AST_LIST_TRAVERSE(&cnf->userlist, user, list) 03536 reset_volumes(user); 03537 break; 03538 case 114: /* r: Reset user's volume level */ 03539 if (user) 03540 reset_volumes(user); 03541 else 03542 ast_log(LOG_NOTICE, "Specified User not found!\n"); 03543 break; 03544 case 85: /* U: Raise user's listen volume */ 03545 if (user) 03546 tweak_listen_volume(user, VOL_UP); 03547 else 03548 ast_log(LOG_NOTICE, "Specified User not found!\n"); 03549 break; 03550 case 117: /* u: Lower user's listen volume */ 03551 if (user) 03552 tweak_listen_volume(user, VOL_DOWN); 03553 else 03554 ast_log(LOG_NOTICE, "Specified User not found!\n"); 03555 break; 03556 case 84: /* T: Raise user's talk volume */ 03557 if (user) 03558 tweak_talk_volume(user, VOL_UP); 03559 else 03560 ast_log(LOG_NOTICE, "Specified User not found!\n"); 03561 break; 03562 case 116: /* t: Lower user's talk volume */ 03563 if (user) 03564 tweak_talk_volume(user, VOL_DOWN); 03565 else 03566 ast_log(LOG_NOTICE, "Specified User not found!\n"); 03567 break; 03568 } 03569 03570 AST_LIST_UNLOCK(&confs); 03571 03572 dispose_conf(cnf); 03573 03574 return 0; 03575 }
| static void* announce_thread | ( | void * | data | ) | [static] |
Definition at line 1570 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(), CONF_HASLEFT, announce_listitem::confchan, announce_listitem::confusers, get_announce_filename(), announce_listitem::language, LOG_DEBUG, and announce_listitem::namerecloc.
Referenced by conf_run().
01571 { 01572 struct announce_listitem *current; 01573 struct ast_conference *conf = data; 01574 int res = 0; 01575 char filename[PATH_MAX] = ""; 01576 AST_LIST_HEAD_NOLOCK(, announce_listitem) local_list; 01577 AST_LIST_HEAD_INIT_NOLOCK(&local_list); 01578 01579 while (!conf->announcethread_stop) { 01580 ast_mutex_lock(&conf->announcelistlock); 01581 if (conf->announcethread_stop) { 01582 ast_mutex_unlock(&conf->announcelistlock); 01583 break; 01584 } 01585 if (AST_LIST_EMPTY(&conf->announcelist)) 01586 ast_cond_wait(&conf->announcelist_addition, &conf->announcelistlock); 01587 01588 AST_LIST_APPEND_LIST(&local_list, &conf->announcelist, entry); 01589 AST_LIST_HEAD_INIT_NOLOCK(&conf->announcelist); 01590 01591 ast_mutex_unlock(&conf->announcelistlock); 01592 if (conf->announcethread_stop) { 01593 break; 01594 } 01595 01596 for (res = 1; !conf->announcethread_stop && (current = AST_LIST_REMOVE_HEAD(&local_list, entry)); ao2_ref(current, -1)) { 01597 ast_log(LOG_DEBUG, "About to play %s\n", current->namerecloc); 01598 if (!ast_fileexists(current->namerecloc, NULL, NULL)) 01599 continue; 01600 if ((current->confchan) && (current->confusers > 1) && !ast_check_hangup(current->confchan)) { 01601 if (!ast_streamfile(current->confchan, current->namerecloc, current->language)) 01602 res = ast_waitstream(current->confchan, ""); 01603 if (!res) { 01604 ast_copy_string(filename, get_announce_filename(current->announcetype), sizeof(filename)); 01605 if (!ast_streamfile(current->confchan, filename, current->language)) 01606 ast_waitstream(current->confchan, ""); 01607 } 01608 } 01609 if (current->announcetype == CONF_HASLEFT) { 01610 ast_filedelete(current->namerecloc, NULL); 01611 } 01612 } 01613 } 01614 01615 /* thread marked to stop, clean up */ 01616 while ((current = AST_LIST_REMOVE_HEAD(&local_list, entry))) { 01617 ast_filedelete(current->namerecloc, NULL); 01618 ao2_ref(current, -1); 01619 } 01620 return NULL; 01621 }
| static void answer_trunk_chan | ( | struct ast_channel * | chan | ) | [static] |
Definition at line 4084 of file app_meetme.c.
References ast_answer(), and ast_indicate().
Referenced by run_station(), sla_handle_dial_state_event(), and sla_station_exec().
04085 { 04086 ast_answer(chan); 04087 ast_indicate(chan, -1); 04088 }
| static struct ast_conference* build_conf | ( | char * | confno, | |
| char * | pin, | |||
| char * | pinadmin, | |||
| int | make, | |||
| int | dynamic, | |||
| int | refcount, | |||
| const struct ast_channel * | chan | |||
| ) | [static, read] |
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 | |
| chan | The asterisk channel |
Definition at line 828 of file app_meetme.c.
References ast_conference::announcethread, ast_conference::announcethreadlock, ast_atomic_fetchadd_int(), ast_calloc, ast_copy_string(), AST_FORMAT_SLINEAR, ast_free, 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_verb, ast_conference::chan, conf_map, ast_conference::confno, ast_conference::dahdiconf, ast_conference::fd, ast_channel::fds, ast_conference::isdynamic, ast_conference::listenlock, LOG_WARNING, ast_conference::maxusers, ast_conference::pin, ast_conference::pinadmin, ast_conference::playlock, ast_conference::recordthread, ast_conference::recordthreadlock, ast_conference::refcount, ast_conference::start, and ast_conference::uniqueid.
Referenced by dial_trunk(), find_conf(), find_conf_realtime(), run_station(), sla_station_exec(), and sla_trunk_exec().
00829 { 00830 struct ast_conference *cnf; 00831 struct dahdi_confinfo dahdic = { 0, }; 00832 int confno_int = 0; 00833 00834 AST_LIST_LOCK(&confs); 00835 00836 AST_LIST_TRAVERSE(&confs, cnf, list) { 00837 if (!strcmp(confno, cnf->confno)) 00838 break; 00839 } 00840 00841 if (cnf || (!make && !dynamic)) 00842 goto cnfout; 00843 00844 /* Make a new one */ 00845 if (!(cnf = ast_calloc(1, sizeof(*cnf)))) 00846 goto cnfout; 00847 00848 ast_mutex_init(&cnf->playlock); 00849 ast_mutex_init(&cnf->listenlock); 00850 cnf->recordthread = AST_PTHREADT_NULL; 00851 ast_mutex_init(&cnf->recordthreadlock); 00852 cnf->announcethread = AST_PTHREADT_NULL; 00853 ast_mutex_init(&cnf->announcethreadlock); 00854 ast_copy_string(cnf->confno, confno, sizeof(cnf->confno)); 00855 ast_copy_string(cnf->pin, pin, sizeof(cnf->pin)); 00856 ast_copy_string(cnf->pinadmin, pinadmin, sizeof(cnf->pinadmin)); 00857 ast_copy_string(cnf->uniqueid, chan->uniqueid, sizeof(cnf->uniqueid)); 00858 00859 /* Setup a new dahdi conference */ 00860 dahdic.confno = -1; 00861 dahdic.confmode = DAHDI_CONF_CONFANN | DAHDI_CONF_CONFANNMON; 00862 cnf->fd = open("/dev/dahdi/pseudo", O_RDWR); 00863 if (cnf->fd < 0 || ioctl(cnf->fd, DAHDI_SETCONF, &dahdic)) { 00864 ast_log(LOG_WARNING, "Unable to open pseudo device\n"); 00865 if (cnf->fd >= 0) 00866 close(cnf->fd); 00867 ast_free(cnf); 00868 cnf = NULL; 00869 goto cnfout; 00870 } 00871 00872 cnf->dahdiconf = dahdic.confno; 00873 00874 /* Setup a new channel for playback of audio files */ 00875 cnf->chan = ast_request("DAHDI", AST_FORMAT_SLINEAR, "pseudo", NULL); 00876 if (cnf->chan) { 00877 ast_set_read_format(cnf->chan, AST_FORMAT_SLINEAR); 00878 ast_set_write_format(cnf->chan, AST_FORMAT_SLINEAR); 00879 dahdic.chan = 0; 00880 dahdic.confno = cnf->dahdiconf; 00881 dahdic.confmode = DAHDI_CONF_CONFANN | DAHDI_CONF_CONFANNMON; 00882 if (ioctl(cnf->chan->fds[0], DAHDI_SETCONF, &dahdic)) { 00883 ast_log(LOG_WARNING, "Error setting conference\n"); 00884 if (cnf->chan) 00885 ast_hangup(cnf->chan); 00886 else 00887 close(cnf->fd); 00888 00889 ast_free(cnf); 00890 cnf = NULL; 00891 goto cnfout; 00892 } 00893 } 00894 00895 /* Fill the conference struct */ 00896 cnf->start = time(NULL); 00897 cnf->maxusers = 0x7fffffff; 00898 cnf->isdynamic = dynamic ? 1 : 0; 00899 ast_verb(3, "Created MeetMe conference %d for conference '%s'\n", cnf->dahdiconf, cnf->confno); 00900 AST_LIST_INSERT_HEAD(&confs, cnf, list); 00901 00902 /* Reserve conference number in map */ 00903 if ((sscanf(cnf->confno, "%30d", &confno_int) == 1) && (confno_int >= 0 && confno_int < 1024)) 00904 conf_map[confno_int] = 1; 00905 00906 cnfout: 00907 if (cnf) 00908 ast_atomic_fetchadd_int(&cnf->refcount, refcount); 00909 00910 AST_LIST_UNLOCK(&confs); 00911 00912 return cnf; 00913 }
| static int can_write | ( | struct ast_channel * | chan, | |
| int | confflags | |||
| ) | [static] |
Definition at line 1623 of file app_meetme.c.
References ast_channel::_state, AST_STATE_UP, and CONFFLAG_NO_AUDIO_UNTIL_UP.
Referenced by conf_run().
01624 { 01625 if (!(confflags & CONFFLAG_NO_AUDIO_UNTIL_UP)) { 01626 return 1; 01627 } 01628 01629 return (chan->_state == AST_STATE_UP); 01630 }
| static int careful_write | ( | int | fd, | |
| unsigned char * | data, | |||
| int | len, | |||
| int | block | |||
| ) | [static] |
Definition at line 662 of file app_meetme.c.
References ast_log(), errno, and LOG_WARNING.
Referenced by conf_play(), and conf_run().
00663 { 00664 int res; 00665 int x; 00666 00667 while (len) { 00668 if (block) { 00669 x = DAHDI_IOMUX_WRITE | DAHDI_IOMUX_SIGEVENT; 00670 res = ioctl(fd, DAHDI_IOMUX, &x); 00671 } else 00672 res = 0; 00673 if (res >= 0) 00674 res = write(fd, data, len); 00675 if (res < 1) { 00676 if (errno != EAGAIN) { 00677 ast_log(LOG_WARNING, "Failed to write audio data to conference: %s\n", strerror(errno)); 00678 return -1; 00679 } else 00680 return 0; 00681 } 00682 len -= res; 00683 data += res; 00684 } 00685 00686 return 0; 00687 }
| static int channel_admin_exec | ( | struct ast_channel * | chan, | |
| void * | data | |||
| ) | [static] |
Definition at line 3579 of file app_meetme.c.
References ADMINFLAG_KICKME, ADMINFLAG_MUTED, ast_conf_user::adminflags, AST_APP_ARG, AST_DECLARE_APP_ARGS, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), ast_conf_user::chan, ast_conf_user::list, LOG_NOTICE, LOG_WARNING, and ast_conference::userlist.
Referenced by load_module().
03579 { 03580 char *params; 03581 struct ast_conference *conf = NULL; 03582 struct ast_conf_user *user = NULL; 03583 AST_DECLARE_APP_ARGS(args, 03584 AST_APP_ARG(channel); 03585 AST_APP_ARG(command); 03586 ); 03587 03588 if (ast_strlen_zero(data)) { 03589 ast_log(LOG_WARNING, "MeetMeChannelAdmin requires two arguments!\n"); 03590 return -1; 03591 } 03592 03593 params = ast_strdupa(data); 03594 AST_STANDARD_APP_ARGS(args, params); 03595 03596 if (!args.channel) { 03597 ast_log(LOG_WARNING, "MeetMeChannelAdmin requires a channel name!\n"); 03598 return -1; 03599 } 03600 03601 if (!args.command) { 03602 ast_log(LOG_WARNING, "MeetMeChannelAdmin requires a command!\n"); 03603 return -1; 03604 } 03605 03606 AST_LIST_LOCK(&confs); 03607 AST_LIST_TRAVERSE(&confs, conf, list) { 03608 AST_LIST_TRAVERSE(&conf->userlist, user, list) { 03609 if (!strcmp(user->chan->name, args.channel)) 03610 break; 03611 } 03612 } 03613 03614 if (!user) { 03615 ast_log(LOG_NOTICE, "Specified user (%s) not found\n", args.channel); 03616 AST_LIST_UNLOCK(&confs); 03617 return 0; 03618 } 03619 03620 /* perform the specified action */ 03621 switch (*args.command) { 03622 case 77: /* M: Mute */ 03623 user->adminflags |= ADMINFLAG_MUTED; 03624 break; 03625 case 109: /* m: Unmute */ 03626 user->adminflags &= ~ADMINFLAG_MUTED; 03627 break; 03628 case 107: /* k: Kick user */ 03629 user->adminflags |= ADMINFLAG_KICKME; 03630 break; 03631 default: /* unknown command */ 03632 ast_log(LOG_WARNING, "Unknown MeetMeChannelAdmin command '%s'\n", args.command); 03633 break; 03634 } 03635 03636 AST_LIST_UNLOCK(&confs); 03637 03638 return 0; 03639 }
| static char* complete_meetmecmd | ( | const char * | line, | |
| const char * | word, | |||
| int | pos, | |||
| int | state | |||
| ) | [static] |
Definition at line 916 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, strsep(), ast_conf_user::user_no, and ast_conference::userlist.
Referenced by meetme_cmd().
00917 { 00918 static char *cmds[] = {"concise", "lock", "unlock", "mute", "unmute", "kick", "list", NULL}; 00919 00920 int len = strlen(word); 00921 int which = 0; 00922 struct ast_conference *cnf = NULL; 00923 struct ast_conf_user *usr = NULL; 00924 char *confno = NULL; 00925 char usrno[50] = ""; 00926 char *myline, *ret = NULL; 00927 00928 if (pos == 1) { /* Command */ 00929 return ast_cli_complete(word, cmds, state); 00930 } else if (pos == 2) { /* Conference Number */ 00931 AST_LIST_LOCK(&confs); 00932 AST_LIST_TRAVERSE(&confs, cnf, list) { 00933 if (!strncasecmp(word, cnf->confno, len) && ++which > state) { 00934 ret = cnf->confno; 00935 break; 00936 } 00937 } 00938 ret = ast_strdup(ret); /* dup before releasing the lock */ 00939 AST_LIST_UNLOCK(&confs); 00940 return ret; 00941 } else if (pos == 3) { 00942 /* User Number || Conf Command option*/ 00943 if (strstr(line, "mute") || strstr(line, "kick")) { 00944 if (state == 0 && (strstr(line, "kick") || strstr(line, "mute")) && !strncasecmp(word, "all", len)) 00945 return ast_strdup("all"); 00946 which++; 00947 AST_LIST_LOCK(&confs); 00948 00949 /* TODO: Find the conf number from the cmdline (ignore spaces) <- test this and make it fail-safe! */ 00950 myline = ast_strdupa(line); 00951 if (strsep(&myline, " ") && strsep(&myline, " ") && !confno) { 00952 while((confno = strsep(&myline, " ")) && (strcmp(confno, " ") == 0)) 00953 ; 00954 } 00955 00956 AST_LIST_TRAVERSE(&confs, cnf, list) { 00957 if (!strcmp(confno, cnf->confno)) 00958 break; 00959 } 00960 00961 if (cnf) { 00962 /* Search for the user */ 00963 AST_LIST_TRAVERSE(&cnf->userlist, usr, list) { 00964 snprintf(usrno, sizeof(usrno), "%d", usr->user_no); 00965 if (!strncasecmp(word, usrno, len) && ++which > state) 00966 break; 00967 } 00968 } 00969 AST_LIST_UNLOCK(&confs); 00970 return usr ? ast_strdup(usrno) : NULL; 00971 } else if (strstr(line, "list") && (state == 0)) 00972 return ast_strdup("concise"); 00973 } 00974 00975 return NULL; 00976 }
| static int conf_exec | ( | struct ast_channel * | chan, | |
| void * | data | |||
| ) | [static] |
The meetme() application.
Definition at line 3168 of file app_meetme.c.
References ast_channel::_state, ARRAY_LEN, 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_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_ADMIN, CONFFLAG_ALWAYSPROMPT, CONFFLAG_DYNAMIC, CONFFLAG_DYNAMICPIN, CONFFLAG_EMPTY, CONFFLAG_EMPTYNOPIN, CONFFLAG_QUIET, CONFIG_FILE_NAME, config_flags, ast_conference::confno, dispose_conf(), find_conf(), find_conf_realtime(), ast_flags::flags, LOG_ERROR, LOG_WARNING, MAX_CONFNUM, MAX_PIN, meetme_opts, ast_variable::name, ast_variable::next, OPT_ARG_ARRAY_SIZE, ast_conference::pin, ast_conference::pinadmin, strsep(), ast_variable::value, and var.
Referenced by load_module().
03169 { 03170 int res = -1; 03171 char confno[MAX_CONFNUM] = ""; 03172 int allowretry = 0; 03173 int retrycnt = 0; 03174 struct ast_conference *cnf = NULL; 03175 struct ast_flags confflags = {0}, config_flags = { 0 }; 03176 int dynamic = 0; 03177 int empty = 0, empty_no_pin = 0; 03178 int always_prompt = 0; 03179 char *notdata, *info, the_pin[MAX_PIN] = ""; 03180 AST_DECLARE_APP_ARGS(args, 03181 AST_APP_ARG(confno); 03182 AST_APP_ARG(options); 03183 AST_APP_ARG(pin); 03184 ); 03185 char *optargs[OPT_ARG_ARRAY_SIZE] = { NULL, }; 03186 03187 if (ast_strlen_zero(data)) { 03188 allowretry = 1; 03189 notdata = ""; 03190 } else { 03191 notdata = data; 03192 } 03193 03194 if (chan->_state != AST_STATE_UP) 03195 ast_answer(chan); 03196 03197 info = ast_strdupa(notdata); 03198 03199 AST_STANDARD_APP_ARGS(args, info); 03200 03201 if (args.confno) { 03202 ast_copy_string(confno, args.confno, sizeof(confno)); 03203 if (ast_strlen_zero(confno)) { 03204 allowretry = 1; 03205 } 03206 } 03207 03208 if (args.pin) 03209 ast_copy_string(the_pin, args.pin, sizeof(the_pin)); 03210 03211 if (args.options) { 03212 ast_app_parse_options(meetme_opts, &confflags, optargs, args.options); 03213 dynamic = ast_test_flag(&confflags, CONFFLAG_DYNAMIC | CONFFLAG_DYNAMICPIN); 03214 if (ast_test_flag(&confflags, CONFFLAG_DYNAMICPIN) && ast_strlen_zero(args.pin)) 03215 strcpy(the_pin, "q"); 03216 03217 empty = ast_test_flag(&confflags, CONFFLAG_EMPTY | CONFFLAG_EMPTYNOPIN); 03218 empty_no_pin = ast_test_flag(&confflags, CONFFLAG_EMPTYNOPIN); 03219 always_prompt = ast_test_flag(&confflags, CONFFLAG_ALWAYSPROMPT | CONFFLAG_DYNAMICPIN); 03220 } 03221 03222 do { 03223 if (retrycnt > 3) 03224 allowretry = 0; 03225 if (empty) { 03226 int i; 03227 struct ast_config *cfg; 03228 struct ast_variable *var; 03229 int confno_int; 03230 03231 /* We only need to load the config file for static and empty_no_pin (otherwise we don't care) */ 03232 if ((empty_no_pin) || (!dynamic)) { 03233 cfg = ast_config_load(CONFIG_FILE_NAME, config_flags); 03234 if (cfg) { 03235 var = ast_variable_browse(cfg, "rooms"); 03236 while (var) { 03237 if (!strcasecmp(var->name, "conf")) { 03238 char *stringp = ast_strdupa(var->value); 03239 if (stringp) { 03240 char *confno_tmp = strsep(&stringp, "|,"); 03241 int found = 0; 03242 if (!dynamic) { 03243 /* For static: run through the list and see if this conference is empty */ 03244 AST_LIST_LOCK(&confs); 03245 AST_LIST_TRAVERSE(&confs, cnf, list) { 03246 if (!strcmp(confno_tmp, cnf->confno)) { 03247 /* The conference exists, therefore it's not empty */ 03248 found = 1; 03249 break; 03250 } 03251 } 03252 AST_LIST_UNLOCK(&confs); 03253 if (!found) { 03254 /* At this point, we have a confno_tmp (static conference) that is empty */ 03255 if ((empty_no_pin && ast_strlen_zero(stringp)) || (!empty_no_pin)) { 03256 /* Case 1: empty_no_pin and pin is nonexistent (NULL) 03257 * Case 2: empty_no_pin and pin is blank (but not NULL) 03258 * Case 3: not empty_no_pin 03259 */ 03260 ast_copy_string(confno, confno_tmp, sizeof(confno)); 03261 break; 03262 /* XXX the map is not complete (but we do have a confno) */ 03263 } 03264 } 03265 } 03266 } 03267 } 03268 var = var->next; 03269 } 03270 ast_config_destroy(cfg); 03271 } 03272 } 03273 03274 /* Select first conference number not in use */ 03275 if (ast_strlen_zero(confno) && dynamic) { 03276 AST_LIST_LOCK(&confs); 03277 for (i = 0; i < ARRAY_LEN(conf_map); i++) { 03278 if (!conf_map[i]) { 03279 snprintf(confno, sizeof(confno), "%d", i); 03280 conf_map[i] = 1; 03281 break; 03282 } 03283 } 03284 AST_LIST_UNLOCK(&confs); 03285 } 03286 03287 /* Not found? */ 03288 if (ast_strlen_zero(confno)) { 03289 res = ast_streamfile(chan, "conf-noempty", chan->language); 03290 if (!res) 03291 ast_waitstream(chan, ""); 03292 } else { 03293 if (sscanf(confno, "%30d", &confno_int) == 1) { 03294 if (!ast_test_flag(&confflags, CONFFLAG_QUIET)) { 03295 res = ast_streamfile(chan, "conf-enteringno", chan->language); 03296 if (!res) { 03297 ast_waitstream(chan, ""); 03298 res = ast_say_digits(chan, confno_int, "", chan->language); 03299 } 03300 } 03301 } else { 03302 ast_log(LOG_ERROR, "Could not scan confno '%s'\n", confno); 03303 } 03304 } 03305 } 03306 03307 while (allowretry && (ast_strlen_zero(confno)) && (++retrycnt < 4)) { 03308 /* Prompt user for conference number */ 03309 res = ast_app_getdata(chan, "conf-getconfno", confno, sizeof(confno) - 1, 0); 03310 if (res < 0) { 03311 /* Don't try to validate when we catch an error */ 03312 confno[0] = '\0'; 03313 allowretry = 0; 03314 break; 03315 } 03316 } 03317 if (!ast_strlen_zero(confno)) { 03318 /* Check the validity of the conference */ 03319 cnf = find_conf(chan, confno, 1, dynamic, the_pin, 03320 sizeof(the_pin), 1, &confflags); 03321 if (!cnf) { 03322 int too_early = 0; 03323 cnf = find_conf_realtime(chan, confno, 1, dynamic, 03324 the_pin, sizeof(the_pin), 1, &confflags, optargs, &too_early); 03325 if (rt_schedule && too_early) 03326 allowretry = 0; 03327 } 03328 03329 if (!cnf) { 03330 if (allowretry) { 03331 confno[0] = '\0'; 03332 res = ast_streamfile(chan, "conf-invalid", chan->language); 03333 if (!res) 03334 ast_waitstream(chan, ""); 03335 res = -1; 03336 } 03337 } else { 03338 if ((!ast_strlen_zero(cnf->pin) && 03339 !ast_test_flag(&confflags, CONFFLAG_ADMIN)) || 03340 (!ast_strlen_zero(cnf->pinadmin) && 03341 ast_test_flag(&confflags, CONFFLAG_ADMIN))) { 03342 char pin[MAX_PIN] = ""; 03343 int j; 03344 03345 /* Allow the pin to be retried up to 3 times */ 03346 for (j = 0; j < 3; j++) { 03347 if (*the_pin && (always_prompt == 0)) { 03348 ast_copy_string(pin, the_pin, sizeof(pin)); 03349 res = 0; 03350 } else { 03351 /* Prompt user for pin if pin is required */ 03352 res = ast_app_getdata(chan, "conf-getpin", pin + strlen(pin), sizeof(pin) - 1 - strlen(pin), 0); 03353 } 03354 if (res >= 0) { 03355 if (!strcasecmp(pin, cnf->pin) || 03356 (!ast_strlen_zero(cnf->pinadmin) && 03357 !strcasecmp(pin, cnf->pinadmin))) { 03358 /* Pin correct */ 03359 allowretry = 0; 03360 if (!ast_strlen_zero(cnf->pinadmin) && !strcasecmp(pin, cnf->pinadmin)) 03361 ast_set_flag(&confflags, CONFFLAG_ADMIN); 03362 /* Run the conference */ 03363 res = conf_run(chan, cnf, confflags.flags, optargs); 03364 break; 03365 } else { 03366 /* Pin invalid */ 03367 if (!ast_streamfile(chan, "conf-invalidpin", chan->language)) { 03368 res = ast_waitstream(chan, AST_DIGIT_ANY); 03369 ast_stopstream(chan); 03370 } 03371 else { 03372 ast_log(LOG_WARNING, "Couldn't play invalid pin msg!\n"); 03373 break; 03374 } 03375 if (res < 0) 03376 break; 03377 pin[0] = res; 03378 pin[1] = '\0'; 03379 res = -1; 03380 if (allowretry) 03381 confno[0] = '\0'; 03382 } 03383 } else { 03384 /* failed when getting the pin */ 03385 res = -1; 03386 allowretry = 0; 03387 /* see if we need to get rid of the conference */ 03388 break; 03389 } 03390 03391 /* Don't retry pin with a static pin */ 03392 if (*the_pin && (always_prompt == 0)) { 03393 break; 03394 } 03395 } 03396 } else { 03397 /* No pin required */ 03398 allowretry = 0; 03399 03400 /* Run the conference */ 03401 res = conf_run(chan, cnf, confflags.flags, optargs); 03402 } 03403 dispose_conf(cnf); 03404 cnf = NULL; 03405 } 03406 } 03407 } while (allowretry); 03408 03409 if (cnf) 03410 dispose_conf(cnf); 03411 03412 return res; 03413 }
| static void conf_flush | ( | int | fd, | |
| struct ast_channel * | chan | |||
| ) | [static] |
Definition at line 1343 of file app_meetme.c.
References ast_frfree, ast_log(), ast_read(), ast_waitfor(), f, and LOG_WARNING.
Referenced by conf_run().
01344 { 01345 int x; 01346 01347 /* read any frames that may be waiting on the channel 01348 and throw them away 01349 */ 01350 if (chan) { 01351 struct ast_frame *f; 01352 01353 /* when no frames are available, this will wait 01354 for 1 millisecond maximum 01355 */ 01356 while (ast_waitfor(chan, 1)) { 01357 f = ast_read(chan); 01358 if (f) 01359 ast_frfree(f); 01360 else /* channel was hung up or something else happened */ 01361 break; 01362 } 01363 } 01364 01365 /* flush any data sitting in the pseudo channel */ 01366 x = DAHDI_FLUSH_ALL; 01367 if (ioctl(fd, DAHDI_FLUSH, &x)) 01368 ast_log(LOG_WARNING, "Error flushing channel\n"); 01369 01370 }
| static int conf_free | ( | struct ast_conference * | conf | ) | [static] |
Definition at line 1374 of file app_meetme.c.
References ast_conference::announcelist, ast_conference::announcelist_addition, ast_conference::announcelistlock, ast_conference::announcethread, ast_conference::announcethread_stop, ast_conference::announcethreadlock, ao2_ref, ast_cond_signal(), ast_filedelete(), AST_FRAME_BITS, ast_free, ast_frfree, ast_hangup(), AST_LIST_LOCK, AST_LIST_REMOVE, AST_LIST_REMOVE_HEAD, AST_LIST_UNLOCK, ast_mutex_destroy(), ast_mutex_lock(), ast_mutex_unlock(), AST_PTHREADT_NULL, ast_softhangup(), AST_SOFTHANGUP_EXPLICIT, ast_translator_free_path(), ast_conference::chan, ast_conference::confno, EVENT_FLAG_CALL, ast_conference::fd, ast_conference::lchan, ast_conference::listenlock, manager_event, MEETME_RECORD_ACTIVE, MEETME_RECORD_OFF, MEETME_RECORD_TERMINATE, announce_listitem::namerecloc, ast_conference::origframe, ast_conference::playlock, ast_conference::recordingfilename, ast_conference::recordingformat, ast_conference::recordthreadlock, ast_conference::transframe, and ast_conference::transpath.
Referenced by dispose_conf().
01375 { 01376 int x; 01377 struct announce_listitem *item; 01378 01379 AST_LIST_REMOVE(&confs, conf, list); 01380 manager_event(EVENT_FLAG_CALL, "MeetmeEnd", "Meetme: %s\r\n", conf->confno); 01381 01382 if (conf->recording == MEETME_RECORD_ACTIVE) { 01383 conf->recording = MEETME_RECORD_TERMINATE; 01384 AST_LIST_UNLOCK(&confs); 01385 while (1) { 01386 usleep(1); 01387 AST_LIST_LOCK(&confs); 01388 if (conf->recording == MEETME_RECORD_OFF) 01389 break; 01390 AST_LIST_UNLOCK(&confs); 01391 } 01392 } 01393 01394 for (x = 0; x < AST_FRAME_BITS; x++) { 01395 if (conf->transframe[x]) 01396 ast_frfree(conf->transframe[x]); 01397 if (conf->transpath[x]) 01398 ast_translator_free_path(conf->transpath[x]); 01399 } 01400 if (conf->announcethread != AST_PTHREADT_NULL) { 01401 ast_mutex_lock(&conf->announcelistlock); 01402 conf->announcethread_stop = 1; 01403 ast_softhangup(conf->chan, AST_SOFTHANGUP_EXPLICIT); 01404 ast_cond_signal(&conf->announcelist_addition); 01405 ast_mutex_unlock(&conf->announcelistlock); 01406 pthread_join(conf->announcethread, NULL); 01407 01408 while ((item = AST_LIST_REMOVE_HEAD(&conf->announcelist, entry))) { 01409 ast_filedelete(item->namerecloc, NULL); 01410 ao2_ref(item, -1); 01411 } 01412 ast_mutex_destroy(&conf->announcelistlock); 01413 } 01414 if (conf->origframe) 01415 ast_frfree(conf->origframe); 01416 if (conf->lchan) 01417 ast_hangup(conf->lchan); 01418 if (conf->chan) 01419 ast_hangup(conf->chan); 01420 if (conf->fd >= 0) 01421 close(conf->fd); 01422 if (conf->recordingfilename) { 01423 ast_free(conf->recordingfilename); 01424 } 01425 if (conf->recordingformat) { 01426 ast_free(conf->recordingformat); 01427 } 01428 ast_mutex_destroy(&conf->playlock); 01429 ast_mutex_destroy(&conf->listenlock); 01430 ast_mutex_destroy(&conf->recordthreadlock); 01431 ast_mutex_destroy(&conf->announcethreadlock); 01432 ast_free(conf); 01433 01434 return 0; 01435 }
| static void conf_play | ( | struct ast_channel * | chan, | |
| struct ast_conference * | conf, | |||
| enum entrance_sound | sound | |||
| ) | [static] |
Definition at line 780 of file app_meetme.c.
References ast_autoservice_start(), ast_autoservice_stop(), ast_check_hangup(), AST_LIST_LOCK, AST_LIST_UNLOCK, careful_write(), enter, ENTER, ast_conference::fd, leave, LEAVE, and len().
Referenced by conf_run().
00781 { 00782 unsigned char *data; 00783 int len; 00784 int res = -1; 00785 00786 if (!ast_check_hangup(chan)) 00787 res = ast_autoservice_start(chan); 00788 00789 AST_LIST_LOCK(&confs); 00790 00791 switch(sound) { 00792 case ENTER: 00793 data = enter; 00794 len = sizeof(enter); 00795 break; 00796 case LEAVE: 00797 data = leave; 00798 len = sizeof(leave); 00799 break; 00800 default: 00801 data = NULL; 00802 len = 0; 00803 } 00804 if (data) { 00805 careful_write(conf->fd, data, len, 1); 00806 } 00807 00808 AST_LIST_UNLOCK(&confs); 00809 00810 if (!res) 00811 ast_autoservice_stop(chan); 00812 }
| static void conf_queue_dtmf | ( | const struct ast_conference * | conf, | |
| const struct ast_conf_user * | sender, | |||
| struct ast_frame * | f | |||
| ) | [static] |
Definition at line 1437 of file app_meetme.c.
References AST_LIST_TRAVERSE, ast_log(), ast_write(), ast_conf_user::chan, ast_conf_user::list, LOG_WARNING, and ast_conference::userlist.
Referenced by conf_run().
01439 { 01440 struct ast_conf_user *user; 01441 01442 AST_LIST_TRAVERSE(&conf->userlist, user, list) { 01443 if (user == sender) 01444 continue; 01445 if (ast_write(user->chan, f) < 0) 01446 ast_log(LOG_WARNING, "Error writing frame to channel %s\n", user->chan->name); 01447 } 01448 }
| static int conf_run | ( | struct ast_channel * | chan, | |
| struct ast_conference * | conf, | |||
| int | confflags, | |||
| char * | optargs[] | |||
| ) | [static] |
Definition at line 1632 of file app_meetme.c.
References volume::actual, ADMINFLAG_KICKME, ADMINFLAG_MUTED, ADMINFLAG_SELFMUTED, ADMINFLAG_T_REQUEST, ast_conf_user::adminflags, announce_thread(), ast_conference::announcelist, ast_conference::announcelist_addition, ast_conference::announcelistlock, ast_conference::announcethread, ast_conference::announcethreadlock, announce_listitem::announcetype, ao2_alloc, ao2_ref, ast_calloc, ast_channel_lock, ast_channel_setoption(), ast_channel_unlock, ast_check_hangup(), ast_cond_signal(), ast_config_AST_SPOOL_DIR, AST_CONTROL_HOLD, ast_copy_string(), ast_debug, AST_DEVICE_INUSE, AST_DEVICE_NOT_INUSE, ast_devstate_changed(), AST_DIGIT_ANY, ast_dsp_free(), ast_dsp_get_threshold_from_settings(), ast_dsp_new(), ast_dsp_silence(), ast_exists_extension(), ast_filedelete(), 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_free, ast_frfree, AST_FRIENDLY_OFFSET, ast_goto_if_exists(), ast_hangup(), ast_indicate(), AST_LIST_EMPTY, AST_LIST_HEAD_INIT_NOLOCK, AST_LIST_INSERT_TAIL, AST_LIST_LAST, AST_LIST_LOCK, AST_LIST_NEXT, AST_LIST_REMOVE, AST_LIST_UNLOCK, ast_log(), AST_MAX_CONTEXT, AST_MAX_EXTENSION, ast_mkdir(), 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_pthread_create_detached_background, AST_PTHREADT_NULL, ast_read(), ast_read_noaudio(), ast_realtime_require_field(), ast_record_review(), ast_request(), ast_safe_sleep(), ast_samp2tv(), ast_say_digits(), ast_say_number(), ast_set_read_format(), ast_set_write_format(), ast_stopstream(), ast_strdup, ast_strdupa, ast_streamfile(), ast_strlen_zero(), ast_translate(), ast_translator_build_path(), ast_tvadd(), ast_tvdiff_ms(), ast_tvnow(), ast_tvsub(), ast_tvzero(), ast_update_realtime(), ast_verb, ast_waitfor_nandfds(), ast_waitstream(), ast_write(), ast_channel::audiohooks, buf, can_write(), careful_write(), ast_conference::chan, ast_conf_user::chan, ast_channel::cid, ast_callerid::cid_name, ast_callerid::cid_num, conf_flush(), CONF_HASJOIN, CONF_HASLEFT, conf_play(), conf_queue_dtmf(), CONF_SIZE, conf_start_moh(), announce_listitem::confchan, CONFFLAG_ADMIN, CONFFLAG_AGI, CONFFLAG_ANNOUNCEUSERCOUNT, CONFFLAG_DURATION_LIMIT, CONFFLAG_DURATION_STOP, CONFFLAG_EXIT_CONTEXT, CONFFLAG_INTROUSER, CONFFLAG_INTROUSERNOREVIEW, CONFFLAG_KEYEXIT, CONFFLAG_KICK_CONTINUE, CONFFLAG_MARKEDEXIT, CONFFLAG_MARKEDUSER, CONFFLAG_MOH, CONFFLAG_MONITOR, CONFFLAG_MONITORTALKER, CONFFLAG_NO_AUDIO_UNTIL_UP, CONFFLAG_NOONLYPERSON, CONFFLAG_OPTIMIZETALKER, CONFFLAG_PASS_DTMF, CONFFLAG_QUIET, CONFFLAG_RECORDCONF, CONFFLAG_SLA_STATION, CONFFLAG_STARMENU, CONFFLAG_STARTMUTED, CONFFLAG_TALKER, CONFFLAG_WAITMARKED, ast_conference::confno, announce_listitem::confusers, ast_channel::context, ast_conf_user::dahdichannel, ast_conference::dahdiconf, ast_frame::data, ast_frame::datalen, volume::desired, dtmfstr, ast_conf_user::end_sound, ast_conference::endalert, ast_conference::endtime, ENTER, errno, EVENT_FLAG_CALL, exitcontext, f, ast_channel::fds, ast_frame::frametype, ast_conf_user::jointime, ast_conf_user::kicktime, announce_listitem::language, ast_conference::lchan, LEAVE, ast_conf_user::listen, ast_conference::listenlock, ast_conference::locked, LOG_WARNING, ast_channel::macrocontext, manager_event, ast_conference::markedusers, ast_conference::maxusers, MEETME_DELAYDETECTENDTALK, MEETME_DELAYDETECTTALK, ast_channel::monitor, announce_listitem::namerecloc, ast_conf_user::namerecloc, ast_frame::offset, OPT_ARG_DURATION_LIMIT, OPT_ARG_DURATION_STOP, OPT_ARG_EXITKEYS, OPT_ARG_MOH_CLASS, OPT_ARG_WAITMARKED, ast_conference::origframe, parse(), pbx_builtin_getvar_helper(), pbx_builtin_setvar_helper(), pbx_exec(), pbx_findapp(), ast_conf_user::play_warning, ast_conference::playlock, ast_frame::ptr, ast_channel::rawwriteformat, ast_conference::recordingfilename, ast_conference::recordingformat, ast_conference::recordthread, ast_conference::recordthreadlock, reset_volumes(), RQ_UINTEGER1, RQ_UINTEGER2, RQ_UINTEGER3, RQ_UINTEGER4, S_OR, ast_frame::samples, sec, set_talk_volume(), SLA_EVENT_HOLD, sla_queue_event_conf(), ast_conf_user::start_time, strsep(), ast_frame::subclass, ast_conf_user::talk, ast_conf_user::talking, ast_channel::tech, THRESHOLD_SILENCE, ast_conf_user::timelimit, ast_conference::transframe, ast_conference::transpath, tweak_listen_volume(), tweak_talk_volume(), ast_channel_tech::type, ast_conference::uniqueid, ast_conf_user::user_no, ast_conf_user::userflags, ast_conference::userlist, ast_conference::users, var, VOL_DOWN, VOL_UP, ast_conf_user::warning_freq, and ast_conf_user::warning_sound.
Referenced by conf_exec(), dial_trunk(), run_station(), sla_station_exec(), and sla_trunk_exec().
01633 { 01634 struct ast_conf_user *user = NULL; 01635 struct ast_conf_user *usr = NULL; 01636 int fd; 01637 struct dahdi_confinfo dahdic, dahdic_empty; 01638 struct ast_frame *f; 01639 struct ast_channel *c; 01640 struct ast_frame fr; 01641 int outfd; 01642 int ms; 01643 int nfds; 01644 int res; 01645 int retrydahdi; 01646 int origfd; 01647 int musiconhold = 0; 01648 int firstpass = 0; 01649 int lastmarked = 0; 01650 int currentmarked = 0; 01651 int ret = -1; 01652 int x; 01653 int menu_active = 0; 01654 int talkreq_manager = 0; 01655 int using_pseudo = 0; 01656 int duration = 20; 01657 int hr, min, sec; 01658 int sent_event = 0; 01659 int checked = 0; 01660 int announcement_played = 0; 01661 struct timeval now; 01662 struct ast_dsp *dsp = NULL; 01663 struct ast_app *agi_app; 01664 char *agifile; 01665 const char *agifiledefault = "conf-background.agi", *tmpvar; 01666 char meetmesecs[30] = ""; 01667 char exitcontext[AST_MAX_CONTEXT] = ""; 01668 char recordingtmp[AST_MAX_EXTENSION] = ""; 01669 char members[10] = ""; 01670 int dtmf, opt_waitmarked_timeout = 0; 01671 time_t timeout = 0; 01672 struct dahdi_bufferinfo bi; 01673 char __buf[CONF_SIZE + AST_FRIENDLY_OFFSET]; 01674 char *buf = __buf + AST_FRIENDLY_OFFSET; 01675 char *exitkeys = NULL; 01676 unsigned int calldurationlimit = 0; 01677 long timelimit = 0; 01678 long play_warning = 0; 01679 long warning_freq = 0; 01680 const char *warning_sound = NULL; 01681 const char *end_sound = NULL; 01682 char *parse; 01683 long time_left_ms = 0; 01684 struct timeval nexteventts = { 0, }; 01685 int to; 01686 int setusercount = 0; 01687 01688 if (!(user = ast_calloc(1, sizeof(*user)))) 01689 return ret; 01690 01691 /* Possible timeout waiting for marked user */ 01692 if ((confflags & CONFFLAG_WAITMARKED) && 01693 !ast_strlen_zero(optargs[OPT_ARG_WAITMARKED]) && 01694 (sscanf(optargs[OPT_ARG_WAITMARKED], "%30d", &opt_waitmarked_timeout) == 1) && 01695 (opt_waitmarked_timeout > 0)) { 01696 timeout = time(NULL) + opt_waitmarked_timeout; 01697 } 01698 01699 if ((confflags & CONFFLAG_DURATION_STOP) && !ast_strlen_zero(optargs[OPT_ARG_DURATION_STOP])) { 01700 calldurationlimit = atoi(optargs[OPT_ARG_DURATION_STOP]); 01701 ast_verb(3, "Setting call duration limit to %d seconds.\n", calldurationlimit); 01702 } 01703 01704 if ((confflags & CONFFLAG_DURATION_LIMIT) && !ast_strlen_zero(optargs[OPT_ARG_DURATION_LIMIT])) { 01705 char *limit_str, *warning_str, *warnfreq_str; 01706 const char *var; 01707 01708 parse = optargs[OPT_ARG_DURATION_LIMIT]; 01709 limit_str = strsep(&parse, ":"); 01710 warning_str = strsep(&parse, ":"); 01711 warnfreq_str = parse; 01712 01713 timelimit = atol(limit_str); 01714 if (warning_str) 01715 play_warning = atol(warning_str); 01716 if (warnfreq_str) 01717 warning_freq = atol(warnfreq_str); 01718 01719 if (!timelimit) { 01720 timelimit = play_warning = warning_freq = 0; 01721 warning_sound = NULL; 01722 } else if (play_warning > timelimit) { 01723 if (!warning_freq) { 01724 play_warning = 0; 01725 } else { 01726 while (play_warning > timelimit) 01727 play_warning -= warning_freq; 01728 if (play_warning < 1) 01729 play_warning = warning_freq = 0; 01730 } 01731 } 01732 01733 ast_channel_lock(chan); 01734 if ((var = pbx_builtin_getvar_helper(chan, "CONF_LIMIT_WARNING_FILE"))) { 01735 var = ast_strdupa(var); 01736 } 01737 ast_channel_unlock(chan); 01738 01739 warning_sound = var ? var : "timeleft"; 01740 01741 ast_channel_lock(chan); 01742 if ((var = pbx_builtin_getvar_helper(chan, "CONF_LIMIT_TIMEOUT_FILE"))) { 01743 var = ast_strdupa(var); 01744 } 01745 ast_channel_unlock(chan); 01746 01747 end_sound = var ? var : NULL; 01748 01749 /* undo effect of S(x) in case they are both used */ 01750 calldurationlimit = 0; 01751 /* more efficient do it like S(x) does since no advanced opts */ 01752 if (!play_warning && !end_sound && timelimit) { 01753 calldurationlimit = timelimit / 1000; 01754 timelimit = play_warning = warning_freq = 0; 01755 } else { 01756 ast_debug(2, "Limit Data for this call:\n"); 01757 ast_debug(2, "- timelimit = %ld\n", timelimit); 01758 ast_debug(2, "- play_warning = %ld\n", play_warning); 01759 ast_debug(2, "- warning_freq = %ld\n", warning_freq); 01760 ast_debug(2, "- warning_sound = %s\n", warning_sound ? warning_sound : "UNDEF"); 01761 ast_debug(2, "- end_sound = %s\n", end_sound ? end_sound : "UNDEF"); 01762 } 01763 } 01764 01765 /* Get exit keys */ 01766 if ((confflags & CONFFLAG_KEYEXIT)) { 01767 if (!ast_strlen_zero(optargs[OPT_ARG_EXITKEYS])) 01768 exitkeys = ast_strdupa(optargs[OPT_ARG_EXITKEYS]); 01769 else 01770 exitkeys = ast_strdupa("#"); /* Default */ 01771 } 01772 01773 if (confflags & CONFFLAG_RECORDCONF) { 01774 if (!conf->recordingfilename) { 01775 const char *var; 01776 ast_channel_lock(chan); 01777 if ((var = pbx_builtin_getvar_helper(chan, "MEETME_RECORDINGFILE"))) { 01778 conf->recordingfilename = ast_strdup(var); 01779 } 01780 if ((var = pbx_builtin_getvar_helper(chan, "MEETME_RECORDINGFORMAT"))) { 01781 conf->recordingformat = ast_strdup(var); 01782 } 01783 ast_channel_unlock(chan); 01784 if (!conf->recordingfilename) { 01785 snprintf(recordingtmp, sizeof(recordingtmp), "meetme-conf-rec-%s-%s", conf->confno, chan->uniqueid); 01786 conf->recordingfilename = ast_strdup(recordingtmp); 01787 } 01788 if (!conf->recordingformat) { 01789 conf->recordingformat = ast_strdup("wav"); 01790 } 01791 ast_verb(4, "Starting recording of MeetMe Conference %s into file %s.%s.\n", 01792 conf->confno, conf->recordingfilename, conf->recordingformat); 01793 } 01794 } 01795 01796 ast_mutex_lock(&conf->recordthreadlock); 01797 if ((conf->recordthread == AST_PTHREADT_NULL) && (confflags & CONFFLAG_RECORDCONF) && ((conf->lchan = ast_request("DAHDI", AST_FORMAT_SLINEAR, "pseudo", NULL)))) { 01798 ast_set_read_format(conf->lchan, AST_FORMAT_SLINEAR); 01799 ast_set_write_format(conf->lchan, AST_FORMAT_SLINEAR); 01800 dahdic.chan = 0; 01801 dahdic.confno = conf->dahdiconf; 01802 dahdic.confmode = DAHDI_CONF_CONFANN | DAHDI_CONF_CONFANNMON; 01803 if (ioctl(conf->lchan->fds[0], DAHDI_SETCONF, &dahdic)) { 01804 ast_log(LOG_WARNING, "Error starting listen channel\n"); 01805 ast_hangup(conf->lchan); 01806 conf->lchan = NULL; 01807 } else { 01808 ast_pthread_create_detached_background(&conf->recordthread, NULL, recordthread, conf); 01809 } 01810 } 01811 ast_mutex_unlock(&conf->recordthreadlock); 01812 01813 ast_mutex_lock(&conf->announcethreadlock); 01814 if ((conf->announcethread == AST_PTHREADT_NULL) && !(confflags & CONFFLAG_QUIET) && ((confflags & CONFFLAG_INTROUSER) || (confflags & CONFFLAG_INTROUSERNOREVIEW))) { 01815 ast_mutex_init(&conf->announcelistlock); 01816 AST_LIST_HEAD_INIT_NOLOCK(&conf->announcelist); 01817 ast_pthread_create_background(&conf->announcethread, NULL, announce_thread, conf); 01818 } 01819 ast_mutex_unlock(&conf->announcethreadlock); 01820 01821 time(&user->jointime); 01822 01823 user->timelimit = timelimit; 01824 user->play_warning = play_warning; 01825 user->warning_freq = warning_freq; 01826 user->warning_sound = warning_sound; 01827 user->end_sound = end_sound; 01828 01829 if (calldurationlimit > 0) { 01830 time(&user->kicktime); 01831 user->kicktime = user->kicktime + calldurationlimit; 01832 } 01833 01834 if (ast_tvzero(user->start_time)) 01835 user->start_time = ast_tvnow(); 01836 time_left_ms = user->timelimit; 01837 01838 if (user->timelimit) { 01839 nexteventts = ast_tvadd(user->start_time, ast_samp2tv(user->timelimit, 1000)); 01840 nexteventts = ast_tvsub(nexteventts, ast_samp2tv(user->play_warning, 1000)); 01841 } 01842 01843 if (conf->locked && (!(confflags & CONFFLAG_ADMIN))) { 01844 /* Sorry, but this conference is locked! */ 01845 if (!ast_streamfile(chan, "conf-locked", chan->language)) 01846 ast_waitstream(chan, ""); 01847 goto outrun; 01848 } 01849 01850 ast_mutex_lock(&conf->playlock); 01851 01852 if (AST_LIST_EMPTY(&conf->userlist)) 01853 user->user_no = 1; 01854 else 01855 user->user_no = AST_LIST_LAST(&conf->userlist)->user_no + 1; 01856 01857 if (rt_schedule && conf->maxusers) 01858 if (conf->users >= conf->maxusers) { 01859 /* Sorry, but this confernce has reached the participant limit! */ 01860 if (!ast_streamfile(chan, "conf-full", chan->language)) 01861 ast_waitstream(chan, ""); 01862 ast_mutex_unlock(&conf->playlock); 01863 user->user_no = 0; 01864 goto outrun; 01865 } 01866 01867 AST_LIST_INSERT_TAIL(&conf->userlist, user, list); 01868 01869 user->chan = chan; 01870 user->userflags = confflags; 01871 user->adminflags = (confflags & CONFFLAG_STARTMUTED) ? ADMINFLAG_SELFMUTED : 0; 01872 user->talking = -1; 01873 01874 ast_mutex_unlock(&conf->playlock); 01875 01876 if (!(confflags & CONFFLAG_QUIET) && ((confflags & CONFFLAG_INTROUSER) || (confflags & CONFFLAG_INTROUSERNOREVIEW))) { 01877 char destdir[PATH_MAX]; 01878 01879 snprintf(destdir, sizeof(destdir), "%s/meetme", ast_config_AST_SPOOL_DIR); 01880 01881 if (ast_mkdir(destdir, 0777) != 0) { 01882 ast_log(LOG_WARNING, "mkdir '%s' failed: %s\n", destdir, strerror(errno)); 01883 goto outrun; 01884 } 01885 01886 snprintf(user->namerecloc, sizeof(user->namerecloc), 01887 "%s/meetme-username-%s-%d", destdir, 01888 conf->confno, user->user_no); 01889 if (confflags & CONFFLAG_INTROUSERNOREVIEW) 01890 res = ast_play_and_record(chan, "vm-rec-name", user->namerecloc, 10, "sln", &duration, ast_dsp_get_threshold_from_settings(THRESHOLD_SILENCE), 0, NULL); 01891 else 01892 res = ast_record_review(chan, "vm-rec-name", user->namerecloc, 10, "sln", &duration, NULL); 01893 if (res == -1) 01894 goto outrun; 01895 } 01896 01897 ast_mutex_lock(&conf->playlock); 01898 01899 if (confflags & CONFFLAG_MARKEDUSER) 01900 conf->markedusers++; 01901 conf->users++; 01902 if (rt_log_members) { 01903 /* Update table */ 01904 snprintf(members, sizeof(members), "%d", conf->users); 01905 ast_realtime_require_field("meetme", 01906 "confno", strlen(conf->confno) > 7 ? RQ_UINTEGER4 : strlen(conf->confno) > 4 ? RQ_UINTEGER3 : RQ_UINTEGER2, strlen(conf->confno), 01907 "members", RQ_UINTEGER1, strlen(members), 01908 NULL); 01909 ast_update_realtime("meetme", "confno", conf->confno, "members", members, NULL); 01910 } 01911 setusercount = 1; 01912 01913 /* This device changed state now - if this is the first user */ 01914 if (conf->users == 1) 01915 ast_devstate_changed(AST_DEVICE_INUSE, "meetme:%s", conf->confno); 01916 01917 ast_mutex_unlock(&conf->playlock); 01918 01919 /* return the unique ID of the conference */ 01920 pbx_builtin_setvar_helper(chan, "MEETMEUNIQUEID", conf->uniqueid); 01921 01922 if (confflags & CONFFLAG_EXIT_CONTEXT) { 01923 ast_channel_lock(chan); 01924 if ((tmpvar = pbx_builtin_getvar_helper(chan, "MEETME_EXIT_CONTEXT"))) { 01925 ast_copy_string(exitcontext, tmpvar, sizeof(exitcontext)); 01926 } else if (!ast_strlen_zero(chan->macrocontext)) { 01927 ast_copy_string(exitcontext, chan->macrocontext, sizeof(exitcontext)); 01928 } else { 01929 ast_copy_string(exitcontext, chan->context, sizeof(exitcontext)); 01930 } 01931 ast_channel_unlock(chan); 01932 } 01933 01934 if (!(confflags & (CONFFLAG_QUIET | CONFFLAG_NOONLYPERSON))) { 01935 if (conf->users == 1 && !(confflags & CONFFLAG_WAITMARKED)) 01936 if (!ast_streamfile(chan, "conf-onlyperson", chan->language)) 01937 ast_waitstream(chan, ""); 01938 if ((confflags & CONFFLAG_WAITMARKED) && conf->markedusers == 0) 01939 if (!ast_streamfile(chan, "conf-waitforleader", chan->language)) 01940 ast_waitstream(chan, ""); 01941 } 01942 01943 if (!(confflags & CONFFLAG_QUIET) && (confflags & CONFFLAG_ANNOUNCEUSERCOUNT) && conf->users > 1) { 01944 int keepplaying = 1; 01945 01946 if (conf->users == 2) { 01947 if (!ast_streamfile(chan, "conf-onlyone", chan->language)) { 01948 res = ast_waitstream(chan, AST_DIGIT_ANY); 01949 ast_stopstream(chan); 01950 if (res > 0) 01951 keepplaying = 0; 01952 else if (res == -1) 01953 goto outrun; 01954 } 01955 } else { 01956 if (!ast_streamfile(chan, "conf-thereare", chan->language)) { 01957 res = ast_waitstream(chan, AST_DIGIT_ANY); 01958 ast_stopstream(chan); 01959 if (res > 0) 01960 keepplaying = 0; 01961 else if (res == -1) 01962 goto outrun; 01963 } 01964 if (keepplaying) { 01965 res = ast_say_number(chan, conf->users - 1, AST_DIGIT_ANY, chan->language, (char *) NULL); 01966 if (res > 0) 01967 keepplaying = 0; 01968 else if (res == -1) 01969 goto outrun; 01970 } 01971 if (keepplaying && !ast_streamfile(chan, "conf-otherinparty", chan->language)) { 01972 res = ast_waitstream(chan, AST_DIGIT_ANY); 01973 ast_stopstream(chan); 01974 if (res > 0) 01975 keepplaying = 0; 01976 else if (res == -1) 01977 goto outrun; 01978 } 01979 } 01980 } 01981 01982 if (!(confflags & CONFFLAG_NO_AUDIO_UNTIL_UP)) { 01983 /* We're leaving this alone until the state gets changed to up */ 01984 ast_indicate(chan, -1); 01985 } 01986 01987 if (ast_set_write_format(chan, AST_FORMAT_SLINEAR) < 0) { 01988 ast_log(LOG_WARNING, "Unable to set '%s' to write linear mode\n", chan->name); 01989 goto outrun; 01990 } 01991 01992 if (ast_set_read_format(chan, AST_FORMAT_SLINEAR) < 0) { 01993 ast_log(LOG_WARNING, "Unable to set '%s' to read linear mode\n", chan->name); 01994 goto outrun; 01995 } 01996 01997 retrydahdi = (strcasecmp(chan->tech->type, "DAHDI") || (chan->audiohooks || chan->monitor) ? 1 : 0); 01998 user->dahdichannel = !retrydahdi; 01999 02000 dahdiretry: 02001 origfd = chan->fds[0]; 02002 if (retrydahdi) { 02003 /* open pseudo in non-blocking mode */ 02004 fd = open("/dev/dahdi/pseudo", O_RDWR | O_NONBLOCK); 02005 if (fd < 0) { 02006 ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno)); 02007 goto outrun; 02008 } 02009 using_pseudo = 1; 02010 /* Setup buffering information */ 02011 memset(&bi, 0, sizeof(bi)); 02012 bi.bufsize = CONF_SIZE / 2; 02013 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE; 02014 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE; 02015 bi.numbufs = audio_buffers; 02016 if (ioctl(fd, DAHDI_SET_BUFINFO, &bi)) { 02017 ast_log(LOG_WARNING, "Unable to set buffering information: %s\n", strerror(errno)); 02018 close(fd); 02019 goto outrun; 02020 } 02021 x = 1; 02022 if (ioctl(fd, DAHDI_SETLINEAR, &x)) { 02023 ast_log(LOG_WARNING, "Unable to set linear mode: %s\n", strerror(errno)); 02024 close(fd); 02025 goto outrun; 02026 } 02027 nfds = 1; 02028 } else { 02029 /* XXX Make sure we're not running on a pseudo channel XXX */ 02030 fd = chan->fds[0]; 02031 nfds = 0; 02032 } 02033 memset(&dahdic, 0, sizeof(dahdic)); 02034 memset(&dahdic_empty, 0, sizeof(dahdic_empty)); 02035 /* Check to see if we're in a conference... */ 02036 dahdic.chan = 0; 02037 if (ioctl(fd, DAHDI_GETCONF, &dahdic)) { 02038 ast_log(LOG_WARNING, "Error getting conference\n"); 02039 close(fd); 02040 goto outrun; 02041 } 02042 if (dahdic.confmode) { 02043 /* Whoa, already in a conference... Retry... */ 02044 if (!retrydahdi) { 02045 ast_debug(1, "DAHDI channel is in a conference already, retrying with pseudo\n"); 02046 retrydahdi = 1; 02047 goto dahdiretry; 02048 } 02049 } 02050 memset(&dahdic, 0, sizeof(dahdic)); 02051 /* Add us to the conference */ 02052 dahdic.chan = 0; 02053 dahdic.confno = conf->dahdiconf; 02054 02055 if (!(confflags & CONFFLAG_QUIET) && ((confflags & CONFFLAG_INTROUSER) || (confflags & CONFFLAG_INTROUSERNOREVIEW)) && conf->users > 1) { 02056 struct announce_listitem *item; 02057 if (!(item = ao2_alloc(sizeof(*item), NULL))) 02058 return -1; 02059 ast_copy_string(item->namerecloc, user->namerecloc, sizeof(item->namerecloc)); 02060 ast_copy_string(item->language, chan->language, sizeof(item->language)); 02061 item->confchan = conf->chan; 02062 item->confusers = conf->users; 02063 item->announcetype = CONF_HASJOIN; 02064 ast_mutex_lock(&conf->announcelistlock); 02065 ao2_ref(item, +1); /* add one more so we can determine when announce_thread is done playing it */ 02066 AST_LIST_INSERT_TAIL(&conf->announcelist, item, entry); 02067 ast_cond_signal(&conf->announcelist_addition); 02068 ast_mutex_unlock(&conf->announcelistlock); 02069 02070 while (!ast_check_hangup(conf->chan) && ao2_ref(item, 0) == 2 && !ast_safe_sleep(chan, 1000)) { 02071 ; 02072 } 02073 ao2_ref(item, -1); 02074 } 02075 02076 if (confflags & CONFFLAG_WAITMARKED && !conf->markedusers) 02077 dahdic.confmode = DAHDI_CONF_CONF; 02078 else if (confflags & CONFFLAG_MONITOR) 02079 dahdic.confmode = DAHDI_CONF_CONFMON | DAHDI_CONF_LISTENER; 02080 else if (confflags & CONFFLAG_TALKER) 02081 dahdic.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER; 02082 else 02083 dahdic.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER; 02084 02085 if (ioctl(fd, DAHDI_SETCONF, &dahdic)) { 02086 ast_log(LOG_WARNING, "Error setting conference\n"); 02087 close(fd); 02088 goto outrun; 02089 } 02090 ast_debug(1, "Placed channel %s in DAHDI conf %d\n", chan->name, conf->dahdiconf); 02091 02092 if (!sent_event) { 02093 manager_event(EVENT_FLAG_CALL, "MeetmeJoin", 02094 "Channel: %s\r\n" 02095 "Uniqueid: %s\r\n" 02096 "Meetme: %s\r\n" 02097 "Usernum: %d\r\n" 02098 "CallerIDnum: %s\r\n" 02099 "CallerIDname: %s\r\n", 02100 chan->name, chan->uniqueid, conf->confno, 02101 user->user_no, 02102 S_OR(user->chan->cid.cid_num, "<unknown>"), 02103 S_OR(user->chan->cid.cid_name, "<unknown>") 02104 ); 02105 sent_event = 1; 02106 } 02107 02108 if (!firstpass && !(confflags & CONFFLAG_MONITOR) && !(confflags & CONFFLAG_ADMIN)) { 02109 firstpass = 1; 02110 if (!(confflags & CONFFLAG_QUIET)) 02111 if (!(confflags & CONFFLAG_WAITMARKED) || ((confflags & CONFFLAG_MARKEDUSER) && (conf->markedusers >= 1))) 02112 conf_play(chan, conf, ENTER); 02113 } 02114 02115 conf_flush(fd, chan); 02116 02117 if (confflags & CONFFLAG_AGI) { 02118 /* Get name of AGI file to run from $(MEETME_AGI_BACKGROUND) 02119 or use default filename of conf-background.agi */ 02120 02121 ast_channel_lock(chan); 02122 if ((tmpvar = pbx_builtin_getvar_helper(chan, "MEETME_AGI_BACKGROUND"))) { 02123 agifile = ast_strdupa(tmpvar); 02124 } else { 02125 agifile = ast_strdupa(agifiledefault); 02126 } 02127 ast_channel_unlock(chan); 02128 02129 if (user->dahdichannel) { 02130 /* Set CONFMUTE mode on DAHDI channel to mute DTMF tones */ 02131 x = 1; 02132 ast_channel_setoption(chan, AST_OPTION_TONE_VERIFY, &x, sizeof(char), 0); 02133 } 02134 /* Find a pointer to the agi app and execute the script */ 02135 agi_app = pbx_findapp("agi"); 02136 if (agi_app) { 02137 ret = pbx_exec(chan, agi_app, agifile); 02138 } else { 02139 ast_log(LOG_WARNING, "Could not find application (agi)\n"); 02140 ret = -2; 02141 } 02142 if (user->dahdichannel) { 02143 /* Remove CONFMUTE mode on DAHDI channel */ 02144 x = 0; 02145 ast_channel_setoption(chan, AST_OPTION_TONE_VERIFY, &x, sizeof(char), 0); 02146 } 02147 } else { 02148 if (user->dahdichannel && (confflags & CONFFLAG_STARMENU)) { 02149 /* Set CONFMUTE mode on DAHDI channel to mute DTMF tones when the menu is enabled */ 02150 x = 1; 02151 ast_channel_setoption(chan, AST_OPTION_TONE_VERIFY, &x, sizeof(char), 0); 02152 } 02153 if (confflags & (CONFFLAG_OPTIMIZETALKER | CONFFLAG_MONITORTALKER) && !(dsp = ast_dsp_new())) { 02154 ast_log(LOG_WARNING, "Unable to allocate DSP!\n"); 02155 res = -1; 02156 } 02157 for (;;) { 02158 int menu_was_active = 0; 02159 02160 outfd = -1; 02161 ms = -1; 02162 now = ast_tvnow(); 02163 02164 if (rt_schedule) { 02165 if (now.tv_sec % 60 == 0) { 02166 if (!checked) { 02167 if (now.tv_sec >= conf->endtime) { 02168 goto outrun; 02169 } 02170 02171 if (!announcement_played && conf->endalert) { 02172 if (now.tv_sec + conf->endalert >= conf->endtime) { 02173 if (!ast_streamfile(chan, "conf-will-end-in", chan->language)) 02174 ast_waitstream(chan, ""); 02175 ast_say_digits(chan, (conf->endtime - now.tv_sec) / 60, "", chan->language); 02176 if (!ast_streamfile(chan, "minutes", chan->language)) 02177 ast_waitstream(chan, ""); 02178 announcement_played = 1; 02179 } 02180 } 02181 checked = 1; 02182 02183 } 02184 } else { 02185 checked = 0; 02186 } 02187 } 02188 02189 if (user->kicktime && (user->kicktime <= now.tv_sec)) 02190 break; 02191 02192 to = -1; 02193 if (user->timelimit) { 02194 int minutes = 0, seconds = 0, remain = 0; 02195 02196 to = ast_tvdiff_ms(nexteventts, now); 02197 if (to < 0) 02198 to = 0; 02199 time_left_ms = user->timelimit - ast_tvdiff_ms(now, user->start_time); 02200 if (time_left_ms < to) 02201 to = time_left_ms; 02202 02203 if (time_left_ms <= 0) { 02204 if (user->end_sound) { 02205 res = ast_streamfile(chan, user->end_sound, chan->language); 02206 res = ast_waitstream(chan, ""); 02207 } 02208 break; 02209 } 02210 02211 if (!to) { 02212 if (time_left_ms >= 5000) { 02213 02214 remain = (time_left_ms + 500) / 1000; 02215 if (remain / 60 >= 1) { 02216 minutes = remain / 60; 02217 seconds = remain % 60; 02218 } else { 02219 seconds = remain; 02220 } 02221 02222 /* force the time left to round up if appropriate */ 02223 if (user->warning_sound && user->play_warning) { 02224 if (!strcmp(user->warning_sound, "timeleft")) { 02225 02226 res = ast_streamfile(chan, "vm-youhave", chan->language); 02227 res = ast_waitstream(chan, ""); 02228 if (minutes) { 02229 res = ast_say_number(chan, minutes, AST_DIGIT_ANY, chan->language, (char *) NULL); 02230 res = ast_streamfile(chan, "queue-minutes", chan->language); 02231 res = ast_waitstream(chan, ""); 02232 } 02233 if (seconds) { 02234 res = ast_say_number(chan, seconds, AST_DIGIT_ANY, chan->language, (char *) NULL); 02235 res = ast_streamfile(chan, "queue-seconds", chan->language); 02236 res = ast_waitstream(chan, ""); 02237 } 02238 } else { 02239 res = ast_streamfile(chan, user->warning_sound, chan->language); 02240 res = ast_waitstream(chan, ""); 02241 } 02242 } 02243 } 02244 if (user->warning_freq) 02245 nexteventts = ast_tvadd(nexteventts, ast_samp2tv(user->warning_freq, 1000)); 02246 else 02247 nexteventts = ast_tvadd(user->start_time, ast_samp2tv(user->timelimit, 1000)); 02248 } 02249 } 02250 02251 now = ast_tvnow(); 02252 if (timeout && now.tv_sec >= timeout) 02253 break; 02254 02255 /* if we have just exited from the menu, and the user had a channel-driver 02256 volume adjustment, restore it 02257 */ 02258 if (!menu_active && menu_was_active && user->listen.desired && !user->listen.actual) 02259 set_talk_volume(user, user->listen.desired); 02260 02261 menu_was_active = menu_active; 02262 02263 currentmarked = conf->markedusers; 02264 if (!(confflags & CONFFLAG_QUIET) && 02265 (confflags & CONFFLAG_MARKEDUSER) && 02266 (confflags & CONFFLAG_WAITMARKED) && 02267 lastmarked == 0) { 02268 if (currentmarked == 1 && conf->users > 1) { 02269 ast_say_number(chan, conf->users - 1, AST_DIGIT_ANY, chan->language, (char *) NULL); 02270 if (conf->users - 1 == 1) { 02271 if (!ast_streamfile(chan, "conf-userwilljoin", chan->language)) 02272 ast_waitstream(chan, ""); 02273 } else { 02274 if (!ast_streamfile(chan, "conf-userswilljoin", chan->language)) 02275 ast_waitstream(chan, ""); 02276 } 02277 } 02278 if (conf->users == 1 && ! (confflags & CONFFLAG_MARKEDUSER)) 02279 if (!ast_streamfile(chan, "conf-onlyperson", chan->language)) 02280 ast_waitstream(chan, ""); 02281 } 02282 02283 /* Update the struct with the actual confflags */ 02284 user->userflags = confflags; 02285 02286 if (confflags & CONFFLAG_WAITMARKED) { 02287 if (currentmarked == 0) { 02288 if (lastmarked != 0) { 02289 if (!(confflags & CONFFLAG_QUIET)) 02290 if (!ast_streamfile(chan, "conf-leaderhasleft", chan->language)) 02291 ast_waitstream(chan, ""); 02292 if (confflags & CONFFLAG_MARKEDEXIT) { 02293 if (confflags & CONFFLAG_KICK_CONTINUE) 02294 ret = 0; 02295 break; 02296 } else { 02297 dahdic.confmode = DAHDI_CONF_CONF; 02298 if (ioctl(fd, DAHDI_SETCONF, &dahdic)) { 02299 ast_log(LOG_WARNING, "Error setting conference\n"); 02300 close(fd); 02301 goto outrun; 02302 } 02303 } 02304 } 02305 if (!musiconhold && (confflags & CONFFLAG_MOH)) { 02306 conf_start_moh(chan, optargs[OPT_ARG_MOH_CLASS]); 02307 musiconhold = 1; 02308 } 02309 } else if (currentmarked >= 1 && lastmarked == 0) { 02310 /* Marked user entered, so cancel timeout */ 02311 timeout = 0; 02312 if (confflags & CONFFLAG_MONITOR) 02313 dahdic.confmode = DAHDI_CONF_CONFMON | DAHDI_CONF_LISTENER; 02314 else if (confflags & CONFFLAG_TALKER) 02315 dahdic.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER; 02316 else 02317 dahdic.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER; 02318 if (ioctl(fd, DAHDI_SETCONF, &dahdic)) { 02319 ast_log(LOG_WARNING, "Error setting conference\n"); 02320 close(fd); 02321 goto outrun; 02322 } 02323 if (musiconhold && (confflags & CONFFLAG_MOH)) { 02324 ast_moh_stop(chan); 02325 musiconhold = 0; 02326 } 02327 if (!(confflags & CONFFLAG_QUIET) && !(confflags & CONFFLAG_MARKEDUSER)) { 02328 if (!ast_streamfile(chan, "conf-placeintoconf", chan->language)) 02329 ast_waitstream(chan, ""); 02330 conf_play(chan, conf, ENTER); 02331 } 02332 } 02333 } 02334 02335 /* trying to add moh for single person conf */ 02336 if ((confflags & CONFFLAG_MOH) && !(confflags & CONFFLAG_WAITMARKED)) { 02337 if (conf->users == 1) { 02338 if (!musiconhold) { 02339 conf_start_moh(chan, optargs[OPT_ARG_MOH_CLASS]); 02340 musiconhold = 1; 02341 } 02342 } else { 02343 if (musiconhold) { 02344 ast_moh_stop(chan); 02345 musiconhold = 0; 02346 } 02347 } 02348 } 02349 02350 /* Leave if the last marked user left */ 02351 if (currentmarked == 0 && lastmarked != 0 && (confflags & CONFFLAG_MARKEDEXIT)) { 02352 if (confflags & CONFFLAG_KICK_CONTINUE) 02353 ret = 0; 02354 else 02355 ret = -1; 02356 break; 02357 } 02358 02359 /* Check if my modes have changed */ 02360 02361 /* If I should be muted but am still talker, mute me */ 02362 if ((user->adminflags & (ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED)) && (dahdic.confmode & DAHDI_CONF_TALKER)) { 02363 dahdic.confmode ^= DAHDI_CONF_TALKER; 02364 if (ioctl(fd, DAHDI_SETCONF, &dahdic)) { 02365 ast_log(LOG_WARNING, "Error setting conference - Un/Mute \n"); 02366 ret = -1; 02367 break; 02368 } 02369 02370 manager_event(EVENT_FLAG_CALL, "MeetmeMute", 02371 "Channel: %s\r\n" 02372 "Uniqueid: %s\r\n" 02373 "Meetme: %s\r\n" 02374 "Usernum: %i\r\n" 02375 "Status: on\r\n", 02376 chan->name, chan->uniqueid, conf->confno, user->user_no); 02377 } 02378 02379 /* If I should be un-muted but am not talker, un-mute me */ 02380 if (!(user->adminflags & (ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED)) && !(confflags & CONFFLAG_MONITOR) && !(dahdic.confmode & DAHDI_CONF_TALKER)) { 02381 dahdic.confmode |= DAHDI_CONF_TALKER; 02382 if (ioctl(fd, DAHDI_SETCONF, &dahdic)) { 02383 ast_log(LOG_WARNING, "Error setting conference - Un/Mute \n"); 02384 ret = -1; 02385 break; 02386 } 02387 02388 manager_event(EVENT_FLAG_CALL, "MeetmeMute", 02389 "Channel: %s\r\n" 02390 "Uniqueid: %s\r\n" 02391 "Meetme: %s\r\n" 02392 "Usernum: %i\r\n" 02393 "Status: off\r\n", 02394 chan->name, chan->uniqueid, conf->confno, user->user_no); 02395 } 02396 02397 if ((user->adminflags & (ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED)) && 02398 (user->adminflags & ADMINFLAG_T_REQUEST) && !(talkreq_manager)) { 02399 talkreq_manager = 1; 02400 02401 manager_event(EVENT_FLAG_CALL, "MeetmeTalkRequest", 02402 "Channel: %s\r\n" 02403 "Uniqueid: %s\r\n" 02404 "Meetme: %s\r\n" 02405 "Usernum: %i\r\n" 02406 "Status: on\r\n", 02407 chan->name, chan->uniqueid, conf->confno, user->user_no); 02408 } 02409 02410 02411 if (!(user->adminflags & (ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED)) && 02412 !(user->adminflags & ADMINFLAG_T_REQUEST) && (talkreq_manager)) { 02413 talkreq_manager = 0; 02414 manager_event(EVENT_FLAG_CALL, "MeetmeTalkRequest", 02415 "Channel: %s\r\n" 02416 "Uniqueid: %s\r\n" 02417 "Meetme: %s\r\n" 02418 "Usernum: %i\r\n" 02419 "Status: off\r\n", 02420 chan->name, chan->uniqueid, conf->confno, user->user_no); 02421 } 02422 02423 /* If I have been kicked, exit the conference */ 02424 if (user->adminflags & ADMINFLAG_KICKME) { 02425 /* You have been kicked. */ 02426 if (!(confflags & CONFFLAG_QUIET) && 02427 !ast_streamfile(chan, "conf-kicked", chan->language)) { 02428 ast_waitstream(chan, ""); 02429 } 02430 ret = 0; 02431 break; 02432 } 02433 02434 /* Perform an extra hangup check just in case */ 02435 if (ast_check_hangup(chan)) 02436 break; 02437 02438 c = ast_waitfor_nandfds(&chan, 1, &fd, nfds, NULL, &outfd, &ms); 02439 02440 if (c) { 02441 char dtmfstr[2] = ""; 02442 02443 if (c->fds[0] != origfd || (user->dahdichannel && (c->audiohooks || c->monitor))) { 02444 if (using_pseudo) { 02445 /* Kill old pseudo */ 02446 close(fd); 02447 using_pseudo = 0; 02448 } 02449 ast_debug(1, "Ooh, something swapped out under us, starting over\n"); 02450 retrydahdi = (strcasecmp(c->tech->type, "DAHDI") || (c->audiohooks || c->monitor) ? 1 : 0); 02451 user->dahdichannel = !retrydahdi; 02452 goto dahdiretry; 02453 } 02454 if ((confflags & CONFFLAG_MONITOR) || (user->adminflags & (ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED))) 02455 f = ast_read_noaudio(c); 02456 else 02457 f = ast_read(c); 02458 if (!f) 02459 break; 02460 if (f->frametype == AST_FRAME_DTMF) { 02461 dtmfstr[0] = f->subclass; 02462 dtmfstr[1] = '\0'; 02463 } 02464 02465 if ((f->frametype == AST_FRAME_VOICE) && (f->subclass == AST_FORMAT_SLINEAR)) { 02466 if (user->talk.actual) 02467 ast_frame_adjust_volume(f, user->talk.actual); 02468 02469 if (confflags & (CONFFLAG_OPTIMIZETALKER | CONFFLAG_MONITORTALKER)) { 02470 int totalsilence; 02471 02472 if (user->talking == -1) 02473 user->talking = 0; 02474 02475 res = ast_dsp_silence(dsp, f, &totalsilence); 02476 if (!user->talking && totalsilence < MEETME_DELAYDETECTTALK) { 02477 user->talking = 1; 02478 if (confflags & CONFFLAG_MONITORTALKER) 02479 manager_event(EVENT_FLAG_CALL, "MeetmeTalking", 02480 "Channel: %s\r\n" 02481 "Uniqueid: %s\r\n" 02482 "Meetme: %s\r\n" 02483 "Usernum: %d\r\n" 02484 "Status: on\r\n", 02485 chan->name, chan->uniqueid, conf->confno, user->user_no); 02486 } 02487 if (user->talking && totalsilence > MEETME_DELAYDETECTENDTALK) { 02488 user->talking = 0; 02489 if (confflags & CONFFLAG_MONITORTALKER) 02490 manager_event(EVENT_FLAG_CALL, "MeetmeTalking", 02491 "Channel: %s\r\n" 02492 "Uniqueid: %s\r\n" 02493 "Meetme: %s\r\n" 02494 "Usernum: %d\r\n" 02495 "Status: off\r\n", 02496 chan->name, chan->uniqueid, conf->confno, user->user_no); 02497 } 02498 } 02499 if (using_pseudo) { 02500 /* Absolutely do _not_ use careful_write here... 02501 it is important that we read data from the channel 02502 as fast as it arrives, and feed it into the conference. 02503 The buffering in the pseudo channel will take care of any 02504 timing differences, unless they are so drastic as to lose 02505 audio frames (in which case carefully writing would only 02506 have delayed the audio even further). 02507 */ 02508 /* As it turns out, we do want to use careful write. We just 02509 don't want to block, but we do want to at least *try* 02510 to write out all the samples. 02511 */ 02512 if (user->talking && !(confflags & CONFFLAG_OPTIMIZETALKER)) { 02513 careful_write(fd, f->data.ptr, f->datalen, 0); 02514 } 02515 } 02516 } else if (((f->frametype == AST_FRAME_DTMF) && (f->subclass == '*') && (confflags & CONFFLAG_STARMENU)) || ((f->frametype == AST_FRAME_DTMF) && menu_active)) { 02517 if (confflags & CONFFLAG_PASS_DTMF) 02518 conf_queue_dtmf(conf, user, f); 02519 if (ioctl(fd, DAHDI_SETCONF, &dahdic_empty)) { 02520 ast_log(LOG_WARNING, "Error setting conference\n"); 02521 close(fd); 02522 ast_frfree(f); 02523 goto outrun; 02524 } 02525 02526 /* if we are entering the menu, and the user has a channel-driver 02527 volume adjustment, clear it 02528 */ 02529 if (!menu_active && user->talk.desired && !user->talk.actual) 02530 set_talk_volume(user, 0); 02531 02532 if (musiconhold) { 02533 ast_moh_stop(chan); 02534 } 02535 if ((confflags & CONFFLAG_ADMIN)) { 02536 /* Admin menu */ 02537 if (!menu_active) { 02538 menu_active = 1; 02539 /* Record this sound! */ 02540 if (!ast_streamfile(chan, "conf-adminmenu", chan->language)) { 02541 dtmf = ast_waitstream(chan, AST_DIGIT_ANY); 02542 ast_stopstream(chan); 02543 } else 02544 dtmf = 0; 02545 } else 02546 dtmf = f->subclass; 02547 if (dtmf) { 02548 switch(dtmf) { 02549 case '1': /* Un/Mute */ 02550 menu_active = 0; 02551 02552 /* for admin, change both admin and use flags */ 02553 if (user->adminflags & (ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED)) 02554 user->adminflags &= ~(ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED); 02555 else 02556 user->adminflags |= (ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED); 02557 02558 if ((confflags & CONFFLAG_MONITOR) || (user->adminflags & (ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED))) { 02559 if (!ast_streamfile(chan, "conf-muted", chan->language)) 02560 ast_waitstream(chan, ""); 02561 } else { 02562 if (!ast_streamfile(chan, "conf-unmuted", chan->language)) 02563 ast_waitstream(chan, ""); 02564 } 02565 break; 02566 case '2': /* Un/Lock the Conference */ 02567 menu_active = 0; 02568 if (conf->locked) { 02569 conf->locked = 0; 02570 if (!ast_streamfile(chan, "conf-unlockednow", chan->language)) 02571 ast_waitstream(chan, ""); 02572 } else { 02573 conf->locked = 1; 02574 if (!ast_streamfile(chan, "conf-lockednow", chan->language)) 02575 ast_waitstream(chan, ""); 02576 } 02577 break; 02578 case '3': /* Eject last user */ 02579 menu_active = 0; 02580 usr = AST_LIST_LAST(&conf->userlist); 02581 if ((usr->chan->name == chan->name)||(usr->userflags & CONFFLAG_ADMIN)) { 02582 if (!ast_streamfile(chan, "conf-errormenu", chan->language)) 02583 ast_waitstream(chan, ""); 02584 } else 02585 usr->adminflags |= ADMINFLAG_KICKME; 02586 ast_stopstream(chan); 02587 break; 02588 case '4': 02589 tweak_listen_volume(user, VOL_DOWN); 02590 break; 02591 case '6': 02592 tweak_listen_volume(user, VOL_UP); 02593 break; 02594 case '7': 02595 tweak_talk_volume(user, VOL_DOWN); 02596 break; 02597 case '8': 02598 menu_active = 0; 02599 break; 02600 case '9': 02601 tweak_talk_volume(user, VOL_UP); 02602 break; 02603 default: 02604 menu_active = 0; 02605 /* Play an error message! */ 02606 if (!ast_streamfile(chan, "conf-errormenu", chan->language)) 02607 ast_waitstream(chan, ""); 02608 break; 02609 } 02610 } 02611 } else { 02612 /* User menu */ 02613 if (!menu_active) { 02614 menu_active = 1; 02615 if (!ast_streamfile(chan, "conf-usermenu", chan->language)) { 02616 dtmf = ast_waitstream(chan, AST_DIGIT_ANY); 02617 ast_stopstream(chan); 02618 } else 02619 dtmf = 0; 02620 } else 02621 dtmf = f->subclass; 02622 if (dtmf) { 02623 switch(dtmf) { 02624 case '1': /* Un/Mute */ 02625 menu_active = 0; 02626 02627 /* user can only toggle the self-muted state */ 02628 user->adminflags ^= ADMINFLAG_SELFMUTED; 02629 02630 /* they can't override the admin mute state */ 02631 if ((confflags & CONFFLAG_MONITOR) || (user->adminflags & (ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED))) { 02632 if (!ast_streamfile(chan, "conf-muted", chan->language)) 02633 ast_waitstream(chan, ""); 02634 } else { 02635 if (!ast_streamfile(chan, "conf-unmuted", chan->language)) 02636 ast_waitstream(chan, ""); 02637 } 02638 break; 02639 case '2': 02640 menu_active = 0; 02641 if (user->adminflags & (ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED)) 02642 user->adminflags |= ADMINFLAG_T_REQUEST; 02643 02644 if (user->adminflags & ADMINFLAG_T_REQUEST) 02645 if (!ast_streamfile(chan, "beep", chan->language)) 02646 ast_waitstream(chan, ""); 02647 break; 02648 case '4': 02649 tweak_listen_volume(user, VOL_DOWN); 02650 break; 02651 case '6': 02652 tweak_listen_volume(user, VOL_UP); 02653 break; 02654 case '7': 02655 tweak_talk_volume(user, VOL_DOWN); 02656 break; 02657 case '8': 02658 menu_active = 0; 02659 break; 02660 case '9': 02661 tweak_talk_volume(user, VOL_UP); 02662 break; 02663 default: 02664 menu_active = 0; 02665 if (!ast_streamfile(chan, "conf-errormenu", chan->language)) 02666 ast_waitstream(chan, ""); 02667 break; 02668 } 02669 } 02670 } 02671 if (musiconhold) 02672 conf_start_moh(chan, optargs[OPT_ARG_MOH_CLASS]); 02673 02674 if (ioctl(fd, DAHDI_SETCONF, &dahdic)) { 02675 ast_log(LOG_WARNING, "Error setting conference\n"); 02676 close(fd); 02677 ast_frfree(f); 02678 goto outrun; 02679 } 02680 02681 conf_flush(fd, chan); 02682 /* Since this option could absorb dtmf meant for the previous (menu), we have to check this one last */ 02683 } else if ((f->frametype == AST_FRAME_DTMF) && (confflags & CONFFLAG_EXIT_CONTEXT) && ast_exists_extension(chan, exitcontext, dtmfstr, 1, "")) { 02684 if (confflags & CONFFLAG_PASS_DTMF) 02685 conf_queue_dtmf(conf, user, f); 02686 02687 if (!ast_goto_if_exists(chan, exitcontext, dtmfstr, 1)) { 02688 ast_debug(1, "Got DTMF %c, goto context %s\n", dtmfstr[0], exitcontext); 02689 ret = 0; 02690 ast_frfree(f); 02691 break; 02692 } else { 02693 ast_debug(2, "Exit by single digit did not work in meetme. Extension %s does not exist in context %s\n", dtmfstr, exitcontext); 02694 } 02695 } else if ((f->frametype == AST_FRAME_DTMF) && (confflags & CONFFLAG_KEYEXIT) && (strchr(exitkeys, f->subclass))) { 02696 pbx_builtin_setvar_helper(chan, "MEETME_EXIT_KEY", dtmfstr); 02697 02698 if (confflags & CONFFLAG_PASS_DTMF) 02699 conf_queue_dtmf(conf, user, f); 02700 ret = 0; 02701 ast_frfree(f); 02702 break; 02703 } else if ((f->frametype == AST_FRAME_DTMF_BEGIN || f->frametype == AST_FRAME_DTMF_END) 02704 && confflags & CONFFLAG_PASS_DTMF) { 02705 conf_queue_dtmf(conf, user, f); 02706 } else if ((confflags & CONFFLAG_SLA_STATION) && f->frametype == AST_FRAME_CONTROL) { 02707 switch (f->subclass) { 02708 case AST_CONTROL_HOLD: 02709 sla_queue_event_conf(SLA_EVENT_HOLD, chan, conf); 02710 break; 02711 default: 02712 break; 02713 } 02714 } else if (f->frametype == AST_FRAME_NULL) { 02715 /* Ignore NULL frames. It is perfectly normal to get these if the person is muted. */ 02716 } else { 02717 ast_debug(1, 02718 "Got unrecognized frame on channel %s, f->frametype=%d,f->subclass=%d\n", 02719 chan->name, f->frametype, f->subclass); 02720 } 02721 ast_frfree(f); 02722 } else if (outfd > -1) { 02723 res = read(outfd, buf, CONF_SIZE); 02724 if (res > 0) { 02725 memset(&fr, 0, sizeof(fr)); 02726 fr.frametype = AST_FRAME_VOICE; 02727 fr.subclass = AST_FORMAT_SLINEAR; 02728 fr.datalen = res; 02729 fr.samples = res / 2; 02730 fr.data.ptr = buf; 02731 fr.offset = AST_FRIENDLY_OFFSET; 02732 if (!user->listen.actual && 02733 ((confflags & CONFFLAG_MONITOR) || 02734 (user->adminflags & (ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED)) || 02735 (!user->talking && (confflags & CONFFLAG_OPTIMIZETALKER)) 02736 )) { 02737 int idx; 02738 for (idx = 0; idx < AST_FRAME_BITS; idx++) 02739 if (chan->rawwriteformat & (1 << idx)) 02740 break; 02741 if (idx >= AST_FRAME_BITS) 02742 goto bailoutandtrynormal; 02743 ast_mutex_lock(&conf->listenlock); 02744 if (!conf->transframe[idx]) { 02745 if (conf->origframe) { 02746 if (!conf->transpath[idx]) 02747 conf->transpath[idx] = ast_translator_build_path((1 << idx), AST_FORMAT_SLINEAR); 02748 if (conf->transpath[idx]) { 02749 conf->transframe[idx] = ast_translate(conf->transpath[idx], conf->origframe, 0); 02750 if (!conf->transframe[idx]) 02751 conf->transframe[idx] = &ast_null_frame; 02752 } 02753 } 02754 } 02755 if (conf->transframe[idx]) { 02756 if ((conf->transframe[idx]->frametype != AST_FRAME_NULL) && 02757 can_write(chan, confflags)) { 02758 struct ast_frame *cur; 02759 02760 /* the translator may have returned a list of frames, so 02761 write each one onto the channel 02762 */ 02763 for (cur = conf->transframe[idx]; cur; cur = AST_LIST_NEXT(cur, frame_list)) { 02764 if (ast_write(chan, cur)) { 02765 ast_log(LOG_WARNING, "Unable to write frame to channel %s\n", chan->name); 02766 break; 02767 } 02768 } 02769 } 02770 } else { 02771 ast_mutex_unlock(&conf->listenlock); 02772 goto bailoutandtrynormal; 02773 } 02774 ast_mutex_unlock(&conf->listenlock); 02775 } else { 02776 bailoutandtrynormal: 02777 if (user->listen.actual) 02778 ast_frame_adjust_volume(&fr, user->listen.actual); 02779 if (can_write(chan, confflags) && ast_write(chan, &fr) < 0) { 02780 ast_log(LOG_WARNING, "Unable to write frame to channel %s\n", chan->name); 02781 } 02782 } 02783 } else 02784 ast_log(LOG_WARNING, "Failed to read frame: %s\n", strerror(errno)); 02785 } 02786 lastmarked = currentmarked; 02787 } 02788 } 02789 02790 if (musiconhold) 02791 ast_moh_stop(chan); 02792 02793 if (using_pseudo) 02794 close(fd); 02795 else { 02796 /* Take out of conference */ 02797 dahdic.chan = 0; 02798 dahdic.confno = 0; 02799 dahdic.confmode = 0; 02800 if (ioctl(fd, DAHDI_SETCONF, &dahdic)) { 02801 ast_log(LOG_WARNING, "Error setting conference\n"); 02802 } 02803 } 02804 02805 reset_volumes(user); 02806 02807 if (!(confflags & CONFFLAG_QUIET) && !(confflags & CONFFLAG_MONITOR) && !(confflags & CONFFLAG_ADMIN)) 02808 conf_play(chan, conf, LEAVE); 02809 02810 if (!(confflags & CONFFLAG_QUIET) && ((confflags & CONFFLAG_INTROUSER) || (confflags & CONFFLAG_INTROUSERNOREVIEW)) && conf->users > 1) { 02811 struct announce_listitem *item; 02812 if (!(item = ao2_alloc(sizeof(*item), NULL))) 02813 return -1; 02814 ast_copy_string(item->namerecloc, user->namerecloc, sizeof(item->namerecloc)); 02815 ast_copy_string(item->language, chan->language, sizeof(item->language)); 02816 item->confchan = conf->chan; 02817 item->confusers = conf->users; 02818 item->announcetype = CONF_HASLEFT; 02819 ast_mutex_lock(&conf->announcelistlock); 02820 AST_LIST_INSERT_TAIL(&conf->announcelist, item, entry); 02821 ast_cond_signal(&conf->announcelist_addition); 02822 ast_mutex_unlock(&conf->announcelistlock); 02823 } else if (!(confflags & CONFFLAG_QUIET) && ((confflags & CONFFLAG_INTROUSER) || (confflags & CONFFLAG_INTROUSERNOREVIEW)) && conf->users == 1) { 02824 /* Last person is leaving, so no reason to try and announce, but should delete the name recording */ 02825 ast_filedelete(user->namerecloc, NULL); 02826 } 02827 02828 outrun: 02829 AST_LIST_LOCK(&confs); 02830 02831 if (dsp) 02832 ast_dsp_free(dsp); 02833 02834 if (user->user_no) { /* Only cleanup users who really joined! */ 02835 now = ast_tvnow(); 02836 hr = (now.tv_sec - user->jointime) / 3600; 02837 min = ((now.tv_sec - user->jointime) % 3600) / 60; 02838 sec = (now.tv_sec - user->jointime) % 60; 02839 02840 if (sent_event) { 02841 manager_event(EVENT_FLAG_CALL, "MeetmeLeave", 02842 "Channel: %s\r\n" 02843 "Uniqueid: %s\r\n" 02844 "Meetme: %s\r\n" 02845 "Usernum: %d\r\n" 02846 "CallerIDNum: %s\r\n" 02847 "CallerIDName: %s\r\n" 02848 "Duration: %ld\r\n", 02849 chan->name, chan->uniqueid, conf->confno, 02850 user->user_no, 02851 S_OR(user->chan->cid.cid_num, "<unknown>"), 02852 S_OR(user->chan->cid.cid_name, "<unknown>"), 02853 (long)(now.tv_sec - user->jointime)); 02854 } 02855 02856 if (setusercount) { 02857 conf->users--; 02858 if (rt_log_members) { 02859 /* Update table */ 02860 snprintf(members, sizeof(members), "%d", conf->users); 02861 ast_realtime_require_field("meetme", 02862 "confno", strlen(conf->confno) > 7 ? RQ_UINTEGER4 : strlen(conf->confno) > 4 ? RQ_UINTEGER3 : RQ_UINTEGER2, strlen(conf->confno), 02863 "members", RQ_UINTEGER1, strlen(members), 02864 NULL); 02865 ast_update_realtime("meetme", "confno", conf->confno, "members", members, NULL); 02866 } 02867 if (confflags & CONFFLAG_MARKEDUSER) 02868 conf->markedusers--; 02869 } 02870 /* Remove ourselves from the list */ 02871 AST_LIST_REMOVE(&conf->userlist, user, list); 02872 02873 /* Change any states */ 02874 if (!conf->users) 02875 ast_devstate_changed(AST_DEVICE_NOT_INUSE, "meetme:%s", conf->confno); 02876 02877 /* Return the number of seconds the user was in the conf */ 02878 snprintf(meetmesecs, sizeof(meetmesecs), "%d", (int) (time(NULL) - user->jointime)); 02879 pbx_builtin_setvar_helper(chan, "MEETMESECS", meetmesecs); 02880 } 02881 ast_free(user); 02882 AST_LIST_UNLOCK(&confs); 02883 02884 return ret; 02885 }
| static void conf_start_moh | ( | struct ast_channel * | chan, | |
| const char * | musicclass | |||
| ) | [static] |
Definition at line 1540 of file app_meetme.c.
References ast_channel_lock, ast_channel_unlock, ast_moh_start(), ast_strdupa, and ast_string_field_set.
Referenced by conf_run().
01541 { 01542 char *original_moh; 01543 01544 ast_channel_lock(chan); 01545 original_moh = ast_strdupa(chan->musicclass); 01546 ast_string_field_set(chan, musicclass, musicclass); 01547 ast_channel_unlock(chan); 01548 01549 ast_moh_start(chan, original_moh, NULL); 01550 01551 ast_channel_lock(chan); 01552 ast_string_field_set(chan, musicclass, original_moh); 01553 ast_channel_unlock(chan); 01554 }
| static int count_exec | ( | struct ast_channel * | chan, | |
| void * | data | |||
| ) | [static] |
The MeetmeCount application.
Definition at line 3123 of file app_meetme.c.
References ast_channel::_state, ast_answer(), AST_APP_ARG, AST_DECLARE_APP_ARGS, ast_log(), ast_say_number(), AST_STANDARD_APP_ARGS, AST_STATE_UP, ast_strdupa, ast_strlen_zero(), dispose_conf(), find_conf(), LOG_WARNING, pbx_builtin_setvar_helper(), and ast_conference::users.
Referenced by load_module().
03124 { 03125 int res = 0; 03126 struct ast_conference *conf; 03127 int count; 03128 char *localdata; 03129 char val[80] = "0"; 03130 AST_DECLARE_APP_ARGS(args, 03131 AST_APP_ARG(confno); 03132 AST_APP_ARG(varname); 03133 ); 03134 03135 if (ast_strlen_zero(data)) { 03136 ast_log(LOG_WARNING, "MeetMeCount requires an argument (conference number)\n"); 03137 return -1; 03138 } 03139 03140 if (!(localdata = ast_strdupa(data))) 03141 return -1; 03142 03143 AST_STANDARD_APP_ARGS(args, localdata); 03144 03145 conf = find_conf(chan, args.confno, 0, 0, NULL, 0, 1, NULL); 03146 03147 if (conf) { 03148 count = conf->users; 03149 dispose_conf(conf); 03150 conf = NULL; 03151 } else 03152 count = 0; 03153 03154 if (!ast_strlen_zero(args.varname)) { 03155 /* have var so load it and exit */ 03156 snprintf(val, sizeof(val), "%d", count); 03157 pbx_builtin_setvar_helper(chan, args.varname, val); 03158 } else { 03159 if (chan->_state != AST_STATE_UP) 03160 ast_answer(chan); 03161 res = ast_say_number(chan, count, "", chan->language, (char *) NULL); /* Needs gender */ 03162 } 03163 03164 return res; 03165 }
| static struct sla_trunk_ref* create_trunk_ref | ( | struct sla_trunk * | trunk | ) | [static, read] |
Definition at line 5179 of file app_meetme.c.
References ast_calloc, and sla_trunk_ref::trunk.
Referenced by sla_add_trunk_to_station().
05180 { 05181 struct sla_trunk_ref *trunk_ref; 05182 05183 if (!(trunk_ref = ast_calloc(1, sizeof(*trunk_ref)))) 05184 return NULL; 05185 05186 trunk_ref->trunk = trunk; 05187 05188 return trunk_ref; 05189 }
| static void destroy_station | ( | struct sla_station * | station | ) | [static] |
Definition at line 5390 of file app_meetme.c.
References ast_context_remove_extension(), ast_free, 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, exten, sla_trunk::name, sla_station::name, PRIORITY_HINT, sla_registrar, sla_trunk_ref::trunk, and sla_station::trunks.
Referenced by sla_build_station(), and sla_destroy().
05391 { 05392 struct sla_trunk_ref *trunk_ref; 05393 05394 if (!ast_strlen_zero(station->autocontext)) { 05395 AST_RWLIST_RDLOCK(&sla_trunks); 05396 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) { 05397 char exten[AST_MAX_EXTENSION]; 05398 char hint[AST_MAX_APP]; 05399 snprintf(exten, sizeof(exten), "%s_%s", station->name, trunk_ref->trunk->name); 05400 snprintf(hint, sizeof(hint), "SLA:%s", exten); 05401 ast_context_remove_extension(station->autocontext, exten, 05402 1, sla_registrar); 05403 ast_context_remove_extension(station->autocontext, hint, 05404 PRIORITY_HINT, sla_registrar); 05405 } 05406 AST_RWLIST_UNLOCK(&sla_trunks); 05407 } 05408 05409 while ((trunk_ref = AST_LIST_REMOVE_HEAD(&station->trunks, entry))) 05410 ast_free(trunk_ref); 05411 05412 ast_string_field_free_memory(station); 05413 ast_free(station); 05414 }
| static void destroy_trunk | ( | struct sla_trunk * | trunk | ) | [static] |
Definition at line 5376 of file app_meetme.c.
References ast_context_remove_extension(), ast_free, AST_LIST_REMOVE_HEAD, ast_string_field_free_memory, ast_strlen_zero(), sla_trunk::autocontext, sla_registrar, and sla_trunk::stations.
Referenced by sla_build_trunk(), and sla_destroy().
05377 { 05378 struct sla_station_ref *station_ref; 05379 05380 if (!ast_strlen_zero(trunk->autocontext)) 05381 ast_context_remove_extension(trunk->autocontext, "s", 1, sla_registrar); 05382 05383 while ((station_ref = AST_LIST_REMOVE_HEAD(&trunk->stations, entry))) 05384 ast_free(station_ref); 05385 05386 ast_string_field_free_memory(trunk); 05387 ast_free(trunk); 05388 }
| static void* dial_trunk | ( | void * | data | ) | [static] |
Definition at line 4891 of file app_meetme.c.
References ALL_TRUNK_REFS, 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_free, ast_mutex_lock(), ast_mutex_unlock(), ast_set_flag, ast_strdup, ast_strdupa, ast_strlen_zero(), build_conf(), 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, conf_run(), CONFFLAG_MARKEDEXIT, CONFFLAG_MARKEDUSER, CONFFLAG_PASS_DTMF, CONFFLAG_QUIET, CONFFLAG_SLA_TRUNK, sla_trunk::device, dispose_conf(), ast_flags::flags, MAX_CONFNUM, sla_trunk::name, sla_trunk::on_hold, sla, sla_change_trunk_state(), SLA_TRUNK_STATE_IDLE, strsep(), sla_trunk_ref::trunk, and dial_trunk_args::trunk_ref.
Referenced by sla_station_exec().
04892 { 04893 struct dial_trunk_args *args = data; 04894 struct ast_dial *dial; 04895 char *tech, *tech_data; 04896 enum ast_dial_result dial_res; 04897 char conf_name[MAX_CONFNUM]; 04898 struct ast_conference *conf; 04899 struct ast_flags conf_flags = { 0 }; 04900 struct sla_trunk_ref *trunk_ref = args->trunk_ref; 04901 const char *cid_name = NULL, *cid_num = NULL; 04902 04903 if (!(dial = ast_dial_create())) { 04904 ast_mutex_lock(args->cond_lock); 04905 ast_cond_signal(args->cond); 04906 ast_mutex_unlock(args->cond_lock); 04907 return NULL; 04908 } 04909 04910 tech_data = ast_strdupa(trunk_ref->trunk->device); 04911 tech = strsep(&tech_data, "/"); 04912 if (ast_dial_append(dial, tech, tech_data) == -1) { 04913 ast_mutex_lock(args->cond_lock); 04914 ast_cond_signal(args->cond); 04915 ast_mutex_unlock(args->cond_lock); 04916 ast_dial_destroy(dial); 04917 return NULL; 04918 } 04919 04920 if (!sla.attempt_callerid && !ast_strlen_zero(trunk_ref->chan->cid.cid_name)) { 04921 cid_name = ast_strdupa(trunk_ref->chan->cid.cid_name); 04922 ast_free(trunk_ref->chan->cid.cid_name); 04923 trunk_ref->chan->cid.cid_name = NULL; 04924 } 04925 if (!sla.attempt_callerid && !ast_strlen_zero(trunk_ref->chan->cid.cid_num)) { 04926 cid_num = ast_strdupa(trunk_ref->chan->cid.cid_num); 04927 ast_free(trunk_ref->chan->cid.cid_num); 04928 trunk_ref->chan->cid.cid_num = NULL; 04929 } 04930 04931 dial_res = ast_dial_run(dial, trunk_ref->chan, 1); 04932 04933 if (cid_name) 04934 trunk_ref->chan->cid.cid_name = ast_strdup(cid_name); 04935 if (cid_num) 04936 trunk_ref->chan->cid.cid_num = ast_strdup(cid_num); 04937 04938 if (dial_res != AST_DIAL_RESULT_TRYING) { 04939 ast_mutex_lock(args->cond_lock); 04940 ast_cond_signal(args->cond); 04941 ast_mutex_unlock(args->cond_lock); 04942 ast_dial_destroy(dial); 04943 return NULL; 04944 } 04945 04946 for (;;) { 04947 unsigned int done = 0; 04948 switch ((dial_res = ast_dial_state(dial))) { 04949 case AST_DIAL_RESULT_ANSWERED: 04950 trunk_ref->trunk->chan = ast_dial_answered(dial); 04951 case AST_DIAL_RESULT_HANGUP: 04952 case AST_DIAL_RESULT_INVALID: 04953 case AST_DIAL_RESULT_FAILED: 04954 case AST_DIAL_RESULT_TIMEOUT: 04955 case AST_DIAL_RESULT_UNANSWERED: 04956 done = 1; 04957 case AST_DIAL_RESULT_TRYING: 04958 case AST_DIAL_RESULT_RINGING: 04959 case AST_DIAL_RESULT_PROGRESS: 04960 case AST_DIAL_RESULT_PROCEEDING: 04961 break; 04962 } 04963 if (done) 04964 break; 04965 } 04966 04967 if (!trunk_ref->trunk->chan) { 04968 ast_mutex_lock(args->cond_lock); 04969 ast_cond_signal(args->cond); 04970 ast_mutex_unlock(args->cond_lock); 04971 ast_dial_join(dial); 04972 ast_dial_destroy(dial); 04973 return NULL; 04974 } 04975 04976 snprintf(conf_name, sizeof(conf_name), "SLA_%s", trunk_ref->trunk->name); 04977 ast_set_flag(&conf_flags, 04978 CONFFLAG_QUIET | CONFFLAG_MARKEDEXIT | CONFFLAG_MARKEDUSER | 04979 CONFFLAG_PASS_DTMF | CONFFLAG_SLA_TRUNK); 04980 conf = build_conf(conf_name, "", "", 1, 1, 1, trunk_ref->trunk->chan); 04981 04982 ast_mutex_lock(args->cond_lock); 04983 ast_cond_signal(args->cond); 04984 ast_mutex_unlock(args->cond_lock); 04985 04986 if (conf) { 04987 conf_run(trunk_ref->trunk->chan, conf, conf_flags.flags, NULL); 04988 dispose_conf(conf); 04989 conf = NULL; 04990 } 04991 04992 /* If the trunk is going away, it is definitely now IDLE. */ 04993 sla_change_trunk_state(trunk_ref->trunk, SLA_TRUNK_STATE_IDLE, ALL_TRUNK_REFS, NULL); 04994 04995 trunk_ref->trunk->chan = NULL; 04996 trunk_ref->trunk->on_hold = 0; 04997 04998 ast_dial_join(dial); 04999 ast_dial_destroy(dial); 05000 05001 return NULL; 05002 }
| static int dispose_conf | ( | struct ast_conference * | conf | ) | [static] |
Definition at line 1522 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(), dial_trunk(), run_station(), sla_station_exec(), and sla_trunk_exec().
01523 { 01524 int res = 0; 01525 int confno_int = 0; 01526 01527 AST_LIST_LOCK(&confs); 01528 if (ast_atomic_dec_and_test(&conf->refcount)) { 01529 /* Take the conference room number out of an inuse state */ 01530 if ((sscanf(conf->confno, "%4d", &confno_int) == 1) && (confno_int >= 0 && confno_int < 1024)) 01531 conf_map[confno_int] = 0; 01532 conf_free(conf); 01533 res = 1; 01534 } 01535 AST_LIST_UNLOCK(&confs); 01536 01537 return res; 01538 }
| 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, read] |
Definition at line 3025 of file app_meetme.c.
References AST_APP_ARG, ast_app_getdata(), ast_clear_flag, ast_config_destroy(), ast_config_load, ast_debug, AST_DECLARE_APP_ARGS, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), AST_STANDARD_APP_ARGS, ast_strdupa, ast_test_flag, ast_variable_browse(), build_conf(), ast_conference::chan, CONFFLAG_INTROUSER, CONFFLAG_INTROUSERNOREVIEW, CONFFLAG_QUIET, CONFFLAG_RECORDCONF, CONFIG_FILE_NAME, ast_conference::confno, ast_conference::list, LOG_WARNING, ast_variable::name, ast_variable::next, parse(), ast_conference::refcount, S_OR, ast_variable::value, and var.
Referenced by conf_exec(), and count_exec().
03027 { 03028 struct ast_config *cfg; 03029 struct ast_variable *var; 03030 struct ast_flags config_flags = { 0 }; 03031 struct ast_conference *cnf; 03032 char *parse; 03033 AST_DECLARE_APP_ARGS(args, 03034 AST_APP_ARG(confno); 03035 AST_APP_ARG(pin); 03036 AST_APP_ARG(pinadmin); 03037 ); 03038 03039 /* Check first in the conference list */ 03040 ast_debug(1, "The requested confno is '%s'?\n", confno); 03041 AST_LIST_LOCK(&confs); 03042 AST_LIST_TRAVERSE(&confs, cnf, list) { 03043 ast_debug(3, "Does conf %s match %s?\n", confno, cnf->confno); 03044 if (!strcmp(confno, cnf->confno)) 03045 break; 03046 } 03047 if (cnf) { 03048 cnf->refcount += refcount; 03049 } 03050 AST_LIST_UNLOCK(&confs); 03051 03052 if (!cnf) { 03053 if (dynamic) { 03054 /* No need to parse meetme.conf */ 03055 ast_debug(1, "Building dynamic conference '%s'\n", confno); 03056 if (dynamic_pin) { 03057 if (dynamic_pin[0] == 'q') { 03058 /* Query the user to enter a PIN */ 03059 if (ast_app_getdata(chan, "conf-getpin", dynamic_pin, pin_buf_len - 1, 0) < 0) 03060 return NULL; 03061 } 03062 cnf = build_conf(confno, dynamic_pin, "", make, dynamic, refcount, chan); 03063 } else { 03064 cnf = build_conf(confno, "", "", make, dynamic, refcount, chan); 03065 } 03066 } else { 03067 /* Check the config */ 03068 cfg = ast_config_load(CONFIG_FILE_NAME, config_flags); 03069 if (!cfg) { 03070 ast_log(LOG_WARNING, "No %s file :(\n", CONFIG_FILE_NAME); 03071 return NULL; 03072 } 03073 for (var = ast_variable_browse(cfg, "rooms"); var; var = var->next) { 03074 if (strcasecmp(var->name, "conf")) 03075 continue; 03076 03077 if (!(parse = ast_strdupa(var->value))) 03078 return NULL; 03079 03080 AST_STANDARD_APP_ARGS(args, parse); 03081 ast_debug(3, "Will conf %s match %s?\n", confno, args.confno); 03082 if (!strcasecmp(args.confno, confno)) { 03083 /* Bingo it's a valid conference */ 03084 cnf = build_conf(args.confno, 03085 S_OR(args.pin, ""), 03086 S_OR(args.pinadmin, ""), 03087 make, dynamic, refcount, chan); 03088 break; 03089 } 03090 } 03091 if (!var) { 03092 ast_debug(1, "%s isn't a valid conference\n", confno); 03093 } 03094 ast_config_destroy(cfg); 03095 } 03096 } else if (dynamic_pin) { 03097 /* Correct for the user selecting 'D' instead of 'd' to have 03098 someone join into a conference that has already been created 03099 with a pin. */ 03100 if (dynamic_pin[0] == 'q') 03101 dynamic_pin[0] = '\0'; 03102 } 03103 03104 if (cnf) { 03105 if (confflags && !cnf->chan && 03106 !ast_test_flag(confflags, CONFFLAG_QUIET) && 03107 ast_test_flag(confflags, CONFFLAG_INTROUSER | CONFFLAG_INTROUSERNOREVIEW)) { 03108 ast_log(LOG_WARNING, "No DAHDI channel available for conference, user introduction disabled (is chan_dahdi loaded?)\n"); 03109 ast_clear_flag(confflags, CONFFLAG_INTROUSER | CONFFLAG_INTROUSERNOREVIEW); 03110 } 03111 03112 if (confflags && !cnf->chan && 03113 ast_test_flag(confflags, CONFFLAG_RECORDCONF)) { 03114 ast_log(LOG_WARNING, "No DAHDI channel available for conference, conference recording disabled (is chan_dahdi loaded?)\n"); 03115 ast_clear_flag(confflags, CONFFLAG_RECORDCONF); 03116 } 03117 } 03118 03119 return cnf; 03120 }
| 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, | |||
| char * | optargs[], | |||
| int * | too_early | |||
| ) | [static, read] |
Definition at line 2887 of file app_meetme.c.
References ast_clear_flag, ast_copy_string(), ast_debug, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_load_realtime(), ast_localtime(), ast_log(), ast_mktime(), ast_strdupa, ast_streamfile(), ast_strftime(), ast_test_flag, ast_tvnow(), ast_variables_destroy(), ast_waitstream(), build_conf(), ast_conference::chan, CONFFLAG_INTROUSER, CONFFLAG_INTROUSERNOREVIEW, CONFFLAG_QUIET, CONFFLAG_RECORDCONF, ast_conference::confno, DATE_FORMAT, ast_conference::endalert, ast_conference::endtime, ast_conference::list, LOG_WARNING, ast_conference::maxusers, ast_variable::name, ast_variable::next, ast_conference::refcount, ast_variable::value, and var.
Referenced by conf_exec().
02890 { 02891 struct ast_variable *var; 02892 struct ast_conference *cnf; 02893 02894 *too_early = 0; 02895 02896 /* Check first in the conference list */ 02897 AST_LIST_LOCK(&confs); 02898 AST_LIST_TRAVERSE(&confs, cnf, list) { 02899 if (!strcmp(confno, cnf->confno)) 02900 break; 02901 } 02902 if (cnf) { 02903 cnf->refcount += refcount; 02904 } 02905 AST_LIST_UNLOCK(&confs); 02906 02907 if (!cnf) { 02908 char *pin = NULL, *pinadmin = NULL; /* For temp use */ 02909 int maxusers = 0; 02910 struct timeval now; 02911 char currenttime[19] = ""; 02912 char eatime[19] = ""; 02913 char useropts[32] = ""; 02914 char adminopts[32] = ""; 02915 struct ast_tm tm, etm; 02916 struct timeval endtime = { .tv_sec = 0 }; 02917 02918 if (rt_schedule) { 02919 now = ast_tvnow(); 02920 02921 ast_localtime(&now, &tm, NULL); 02922 ast_strftime(currenttime, sizeof(currenttime), DATE_FORMAT, &tm); 02923 02924 ast_debug(1, "Looking for conference %s that starts after %s\n", confno, eatime); 02925 02926 var = ast_load_realtime("meetme", "confno", 02927 confno, "starttime <= ", currenttime, "endtime >= ", 02928 currenttime, NULL); 02929 02930 if (!var && fuzzystart) { 02931 now = ast_tvnow(); 02932 now.tv_sec += fuzzystart; 02933 02934 ast_localtime(&now, &tm, NULL); 02935 ast_strftime(currenttime, sizeof(currenttime), DATE_FORMAT, &tm); 02936 var = ast_load_realtime("meetme", "confno", 02937 confno, "starttime <= ", currenttime, "endtime >= ", 02938 currenttime, NULL); 02939 } 02940 02941 if (!var && earlyalert) { 02942 now = ast_tvnow(); 02943 now.tv_sec += earlyalert; 02944 ast_localtime(&now, &etm, NULL); 02945 ast_strftime(eatime, sizeof(eatime), DATE_FORMAT, &etm); 02946 var = ast_load_realtime("meetme", "confno", 02947 confno, "starttime <= ", eatime, "endtime >= ", 02948 currenttime, NULL); 02949 if (var) 02950 *too_early = 1; 02951 } 02952 02953 } else 02954 var = ast_load_realtime("meetme", "confno", confno, NULL); 02955 02956 if (!var) 02957 return NULL; 02958 02959 if (rt_schedule && *too_early) { 02960 /* Announce that the caller is early and exit */ 02961 if (!ast_streamfile(chan, "conf-has-not-started", chan->language)) 02962 ast_waitstream(chan, ""); 02963 ast_variables_destroy(var); 02964 return NULL; 02965 } 02966 02967 while (var) { 02968 if (!strcasecmp(var->name, "pin")) { 02969 pin = ast_strdupa(var->value); 02970 } else if (!strcasecmp(var->name, "adminpin")) { 02971 pinadmin = ast_strdupa(var->value); 02972 } else if (!strcasecmp(var->name, "opts")) { 02973 ast_copy_string(useropts, var->value, sizeof(useropts)); 02974 } else if (!strcasecmp(var->name, "maxusers")) { 02975 maxusers = atoi(var->value); 02976 } else if (!strcasecmp(var->name, "adminopts")) { 02977 ast_copy_string(adminopts, var->value, sizeof(adminopts)); 02978 } else if (!strcasecmp(var->name, "endtime")) { 02979 union { 02980 struct ast_tm atm; 02981 struct tm tm; 02982 } t = { { 0, }, }; 02983 strptime(var->value, "%Y-%m-%d %H:%M:%S", &t.tm); 02984 /* strptime does not determine if a time is 02985 * in DST or not. Set tm_isdst to -1 to 02986 * allow ast_mktime to adjust for DST 02987 * if needed */ 02988 t.tm.tm_isdst = -1; 02989 endtime = ast_mktime(&t.atm, NULL); 02990 } 02991 02992 var = var->next; 02993 } 02994 02995 ast_variables_destroy(var); 02996 02997 cnf = build_conf(confno, pin ? pin : "", pinadmin ? pinadmin : "", make, dynamic, refcount, chan); 02998 02999 if (cnf) { 03000 cnf->maxusers = maxusers; 03001 cnf->endalert = endalert; 03002 cnf->endtime = endtime.tv_sec; 03003 } 03004 } 03005 03006 if (cnf) { 03007 if (confflags && !cnf->chan && 03008 !ast_test_flag(confflags, CONFFLAG_QUIET) && 03009 ast_test_flag(confflags, CONFFLAG_INTROUSER | CONFFLAG_INTROUSERNOREVIEW)) { 03010 ast_log(LOG_WARNING, "No DAHDI channel available for conference, user introduction disabled (is chan_dahdi loaded?)\n"); 03011 ast_clear_flag(confflags, CONFFLAG_INTROUSER | CONFFLAG_INTROUSERNOREVIEW); 03012 } 03013 03014 if (confflags && !cnf->chan && 03015 ast_test_flag(confflags, CONFFLAG_RECORDCONF)) { 03016 ast_log(LOG_WARNING, "No DAHDI channel available for conference, conference recording disabled (is chan_dahdi loaded?)\n"); 03017 ast_clear_flag(confflags, CONFFLAG_RECORDCONF); 03018 } 03019 } 03020 03021 return cnf; 03022 }
| static struct ast_conf_user* find_user | ( | struct ast_conference * | conf, | |
| char * | callerident | |||
| ) | [static, read] |
Definition at line 3415 of file app_meetme.c.
References AST_LIST_TRAVERSE, ast_conf_user::list, ast_conf_user::user_no, and ast_conference::userlist.
Referenced by admin_exec().
03416 { 03417 struct ast_conf_user *user = NULL; 03418 int cid; 03419 03420 sscanf(callerident, "%30i", &cid); 03421 if (conf && callerident) { 03422 AST_LIST_TRAVERSE(&conf->userlist, user, list) { 03423 if (cid == user->user_no) 03424 return user; 03425 } 03426 } 03427 return NULL; 03428 }
| static const char* get_announce_filename | ( | enum announcetypes | type | ) | [static] |
Definition at line 1556 of file app_meetme.c.
References CONF_HASJOIN, and CONF_HASLEFT.
Referenced by announce_thread().
01557 { 01558 switch (type) { 01559 case CONF_HASLEFT: 01560 return "conf-hasleft"; 01561 break; 01562 case CONF_HASJOIN: 01563 return "conf-hasjoin"; 01564 break; 01565 default: 01566 return ""; 01567 } 01568 }
| static char* istalking | ( | int | x | ) | [static] |
Definition at line 652 of file app_meetme.c.
Referenced by meetme_cmd().
| static int load_config | ( | int | reload | ) | [static] |
Definition at line 5832 of file app_meetme.c.
References ast_log(), load_config_meetme(), LOG_NOTICE, SLA_EVENT_RELOAD, sla_load_config(), and sla_queue_event().
Referenced by load_module(), and reload().
05833 { 05834 load_config_meetme(); 05835 05836 if (reload) { 05837 sla_queue_event(SLA_EVENT_RELOAD); 05838 ast_log(LOG_NOTICE, "A reload of the SLA configuration has been requested " 05839 "and will be completed when the system is idle.\n"); 05840 return 0; 05841 } 05842 05843 return sla_load_config(0); 05844 }
| static void load_config_meetme | ( | void | ) | [static] |
Definition at line 3874 of file app_meetme.c.
References ast_config_destroy(), ast_config_load, ast_log(), ast_true(), ast_variable_retrieve(), CONFIG_FILE_NAME, DEFAULT_AUDIO_BUFFERS, LOG_NOTICE, and LOG_WARNING.
Referenced by load_config().
03875 { 03876 struct ast_config *cfg; 03877 struct ast_flags config_flags = { 0 }; 03878 const char *val; 03879 03880 if (!(cfg = ast_config_load(CONFIG_FILE_NAME, config_flags))) 03881 return; 03882 03883 audio_buffers = DEFAULT_AUDIO_BUFFERS; 03884 03885 /* Scheduling support is off by default */ 03886 rt_schedule = 0; 03887 fuzzystart = 0; 03888 earlyalert = 0; 03889 endalert = 0; 03890 03891 /* Logging of participants defaults to ON for compatibility reasons */ 03892 rt_log_members = 1; 03893 03894 if ((val = ast_variable_retrieve(cfg, "general", "audiobuffers"))) { 03895 if ((sscanf(val, "%30d", &audio_buffers) != 1)) { 03896 ast_log(LOG_WARNING, "audiobuffers setting must be a number, not '%s'\n", val); 03897 audio_buffers = DEFAULT_AUDIO_BUFFERS; 03898 } else if ((audio_buffers < DAHDI_DEFAULT_NUM_BUFS) || (audio_buffers > DAHDI_MAX_NUM_BUFS)) { 03899 ast_log(LOG_WARNING, "audiobuffers setting must be between %d and %d\n", 03900 DAHDI_DEFAULT_NUM_BUFS, DAHDI_MAX_NUM_BUFS); 03901 audio_buffers = DEFAULT_AUDIO_BUFFERS; 03902 } 03903 if (audio_buffers != DEFAULT_AUDIO_BUFFERS) 03904 ast_log(LOG_NOTICE, "Audio buffers per channel set to %d\n", audio_buffers); 03905 } 03906 03907 if ((val = ast_variable_retrieve(cfg, "general", "schedule"))) 03908 rt_schedule = ast_true(val); 03909 if ((val = ast_variable_retrieve(cfg, "general", "logmembercount"))) 03910 rt_log_members = ast_true(val); 03911 if ((val = ast_variable_retrieve(cfg, "general", "fuzzystart"))) { 03912 if ((sscanf(val, "%30d", &fuzzystart) != 1)) { 03913 ast_log(LOG_WARNING, "fuzzystart must be a number, not '%s'\n", val); 03914 fuzzystart = 0; 03915 } 03916 } 03917 if ((val = ast_variable_retrieve(cfg, "general", "earlyalert"))) { 03918 if ((sscanf(val, "%30d", &earlyalert) != 1)) { 03919 ast_log(LOG_WARNING, "earlyalert must be a number, not '%s'\n", val); 03920 earlyalert = 0; 03921 } 03922 } 03923 if ((val = ast_variable_retrieve(cfg, "general", "endalert"))) { 03924 if ((sscanf(val, "%30d", &endalert) != 1)) { 03925 ast_log(LOG_WARNING, "endalert must be a number, not '%s'\n", val); 03926 endalert = 0; 03927 } 03928 } 03929 03930 ast_config_destroy(cfg); 03931 }
| static int load_module | ( | void | ) | [static] |
Definition at line 5872 of file app_meetme.c.
References action_meetmelist(), action_meetmemute(), action_meetmeunmute(), admin_exec(), ARRAY_LEN, ast_cli_register_multiple(), ast_custom_function_register, ast_devstate_prov_add(), ast_manager_register, ast_manager_register2(), ast_realtime_require_field(), ast_register_application, channel_admin_exec(), conf_exec(), count_exec(), EVENT_FLAG_CALL, EVENT_FLAG_REPORTING, load_config(), meetmestate(), RQ_UINTEGER1, RQ_UINTEGER2, sla_state(), sla_station_exec(), and sla_trunk_exec().
05873 { 05874 int res = 0; 05875 05876 res |= load_config(0); 05877 05878 ast_cli_register_multiple(cli_meetme, ARRAY_LEN(cli_meetme)); 05879 res |= ast_manager_register("MeetmeMute", EVENT_FLAG_CALL, 05880 action_meetmemute, "Mute a Meetme user"); 05881 res |= ast_manager_register("MeetmeUnmute", EVENT_FLAG_CALL, 05882 action_meetmeunmute, "Unmute a Meetme user"); 05883 res |= ast_manager_register2("MeetmeList", EVENT_FLAG_REPORTING, 05884 action_meetmelist, "List participants in a conference", mandescr_meetmelist); 05885 res |= ast_register_application(app4, channel_admin_exec, synopsis4, descrip4); 05886 res |= ast_register_application(app3, admin_exec, synopsis3, descrip3); 05887 res |= ast_register_application(app2, count_exec, synopsis2, descrip2); 05888 res |= ast_register_application(app, conf_exec, synopsis, descrip); 05889 res |= ast_register_application(slastation_app, sla_station_exec, 05890 slastation_synopsis, slastation_desc); 05891 res |= ast_register_application(slatrunk_app, sla_trunk_exec, 05892 slatrunk_synopsis, slatrunk_desc); 05893 05894 res |= ast_devstate_prov_add("Meetme", meetmestate); 05895 res |= ast_devstate_prov_add("SLA", sla_state); 05896 05897 res |= ast_custom_function_register(&meetme_info_acf); 05898 ast_realtime_require_field("meetme", "confno", RQ_UINTEGER2, 3, "members", RQ_UINTEGER1, 3, NULL); 05899 05900 return res; 05901 }
| static char* meetme_cmd | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 978 of file app_meetme.c.
References admin_exec(), ADMINFLAG_MUTED, ADMINFLAG_SELFMUTED, ADMINFLAG_T_REQUEST, ast_conf_user::adminflags, ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_debug, ast_free, AST_LIST_EMPTY, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_str_append(), ast_str_create(), ast_str_set(), ast_conf_user::chan, ast_channel::cid, ast_callerid::cid_name, ast_callerid::cid_num, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_meetmecmd(), CONFFLAG_ADMIN, CONFFLAG_MONITOR, ast_conference::confno, ast_cli_args::fd, ast_conference::isdynamic, istalking(), ast_conf_user::jointime, ast_cli_args::line, ast_conference::locked, ast_conference::markedusers, MAX_CONFNUM, MC_DATA_FORMAT, MC_HEADER_FORMAT, ast_cli_args::n, ast_cli_args::pos, S_OR, sec, ast_conference::start, ast_str::str, ast_conf_user::talking, total, ast_cli_entry::usage, ast_conf_user::user_no, ast_conf_user::userflags, ast_conference::userlist, ast_conference::users, and ast_cli_args::word.
00979 { 00980 /* Process the command */ 00981 struct ast_conference *cnf; 00982 struct ast_conf_user *user; 00983 int hr, min, sec; 00984 int i = 0, total = 0; 00985 time_t now; 00986 struct ast_str *cmdline = NULL; 00987 #define MC_HEADER_FORMAT "%-14s %-14s %-10s %-8s %-8s %-6s\n" 00988 #define MC_DATA_FORMAT "%-12.12s %4.4d %4.4s %02d:%02d:%02d %-8s %-6s\n" 00989 00990 switch (cmd) { 00991 case CLI_INIT: 00992 e->command = "meetme"; 00993 e->usage = 00994 "Usage: meetme (un)lock|(un)mute|kick|list [concise] <confno> <usernumber>\n" 00995 " Executes a command for the conference or on a conferee\n"; 00996 return NULL; 00997 case CLI_GENERATE: 00998 return complete_meetmecmd(a->line, a->word, a->pos, a->n); 00999 } 01000 01001 if (a->argc > 8) 01002 ast_cli(a->fd, "Invalid Arguments.\n"); 01003 /* Check for length so no buffer will overflow... */ 01004 for (i = 0; i < a->argc; i++) { 01005 if (strlen(a->argv[i]) > 100) 01006 ast_cli(a->fd, "Invalid Arguments.\n"); 01007 } 01008 01009 /* Max confno length */ 01010 if (!(cmdline = ast_str_create(MAX_CONFNUM))) { 01011 return CLI_FAILURE; 01012 } 01013 01014 if (a->argc == 1 || (a->argc == 2 && !strcasecmp(a->argv[1], "concise"))) { 01015 /* 'MeetMe': List all the conferences */ 01016 int concise = (a->argc == 2 && !strcasecmp(a->argv[1], "concise")); 01017 now = time(NULL); 01018 AST_LIST_LOCK(&confs); 01019 if (AST_LIST_EMPTY(&confs)) { 01020 if (!concise) { 01021 ast_cli(a->fd, "No active MeetMe conferences.\n"); 01022 } 01023 AST_LIST_UNLOCK(&confs); 01024 ast_free(cmdline); 01025 return CLI_SUCCESS; 01026 } 01027 if (!concise) { 01028 ast_cli(a->fd, MC_HEADER_FORMAT, "Conf Num", "Parties", "Marked", "Activity", "Creation", "Locked"); 01029 } 01030 AST_LIST_TRAVERSE(&confs, cnf, list) { 01031 if (cnf->markedusers == 0) { 01032 ast_str_set(&cmdline, 0, "N/A "); 01033 } else { 01034 ast_str_set(&cmdline, 0, "%4.4d", cnf->markedusers); 01035 } 01036 hr = (now - cnf->start) / 3600; 01037 min = ((now - cnf->start) % 3600) / 60; 01038 sec = (now - cnf->start) % 60; 01039 if (!concise) { 01040 ast_cli(a->fd, MC_DATA_FORMAT, cnf->confno, cnf->users, cmdline->str, hr, min, sec, cnf->isdynamic ? "Dynamic" : "Static", cnf->locked ? "Yes" : "No"); 01041 } else { 01042 ast_cli(a->fd, "%s!%d!%d!%02d:%02d:%02d!%d!%d\n", 01043 cnf->confno, 01044 cnf->users, 01045 cnf->markedusers, 01046 hr, min, sec, 01047 cnf->isdynamic, 01048 cnf->locked); 01049 } 01050 01051 total += cnf->users; 01052 } 01053 AST_LIST_UNLOCK(&confs); 01054 if (!concise) { 01055 ast_cli(a->fd, "* Total number of MeetMe users: %d\n", total); 01056 } 01057 ast_free(cmdline); 01058 return CLI_SUCCESS; 01059 } 01060 if (a->argc < 3) { 01061 ast_free(cmdline); 01062 return CLI_SHOWUSAGE; 01063 } 01064 01065 ast_str_set(&cmdline, 0, "%s", a->argv[2]); /* Argv 2: conference number */ 01066 if (strstr(a->argv[1], "lock")) { 01067 if (strcmp(a->argv[1], "lock") == 0) { 01068 /* Lock */ 01069 ast_str_append(&cmdline, 0, ",L"); 01070 } else { 01071 /* Unlock */ 01072 ast_str_append(&cmdline, 0, ",l"); 01073 } 01074 } else if (strstr(a->argv[1], "mute")) { 01075 if (a->argc < 4) { 01076 ast_free(cmdline); 01077 return CLI_SHOWUSAGE; 01078 } 01079 if (strcmp(a->argv[1], "mute") == 0) { 01080 /* Mute */ 01081 if (strcmp(a->argv[3], "all") == 0) { 01082 ast_str_append(&cmdline, 0, ",N"); 01083 } else { 01084 ast_str_append(&cmdline, 0, ",M,%s", a->argv[3]); 01085 } 01086 } else { 01087 /* Unmute */ 01088 if (strcmp(a->argv[3], "all") == 0) { 01089 ast_str_append(&cmdline, 0, ",n"); 01090 } else { 01091 ast_str_append(&cmdline, 0, ",m,%s", a->argv[3]); 01092 } 01093 } 01094 } else if (strcmp(a->argv[1], "kick") == 0) { 01095 if (a->argc < 4) { 01096 ast_free(cmdline); 01097 return CLI_SHOWUSAGE; 01098 } 01099 if (strcmp(a->argv[3], "all") == 0) { 01100 /* Kick all */ 01101 ast_str_append(&cmdline, 0, ",K"); 01102 } else { 01103 /* Kick a single user */ 01104 ast_str_append(&cmdline, 0, ",k,%s", a->argv[3]); 01105 } 01106 } else if (strcmp(a->argv[1], "list") == 0) { 01107 int concise = (a->argc == 4 && (!strcasecmp(a->argv[3], "concise"))); 01108 /* List all the users in a conference */ 01109 if (AST_LIST_EMPTY(&confs)) { 01110 if (!concise) { 01111 ast_cli(a->fd, "No active conferences.\n"); 01112 } 01113 ast_free(cmdline); 01114 return CLI_SUCCESS; 01115 } 01116 /* Find the right conference */ 01117 AST_LIST_LOCK(&confs); 01118 AST_LIST_TRAVERSE(&confs, cnf, list) { 01119 if (strcmp(cnf->confno, a->argv[2]) == 0) { 01120 break; 01121 } 01122 } 01123 if (!cnf) { 01124 if (!concise) 01125 ast_cli(a->fd, "No such conference: %s.\n", a->argv[2]); 01126 AST_LIST_UNLOCK(&confs); 01127 ast_free(cmdline); 01128 return CLI_SUCCESS; 01129 } 01130 /* Show all the users */ 01131 time(&now); 01132 AST_LIST_TRAVERSE(&cnf->userlist, user, list) { 01133 hr = (now - user->jointime) / 3600; 01134 min = ((now - user->jointime) % 3600) / 60; 01135 sec = (now - user->jointime) % 60; 01136 if (!concise) { 01137 ast_cli(a->fd, "User #: %-2.2d %12.12s %-20.20s Channel: %s %s %s %s %s %s %02d:%02d:%02d\n", 01138 user->user_no, 01139 S_OR(user->chan->cid.cid_num, "<unknown>"), 01140 S_OR(user->chan->cid.cid_name, "<no name>"), 01141 user->chan->name, 01142 user->userflags & CONFFLAG_ADMIN ? "(Admin)" : "", 01143 user->userflags & CONFFLAG_MONITOR ? "(Listen only)" : "", 01144 user->adminflags & ADMINFLAG_MUTED ? "(Admin Muted)" : user->adminflags & ADMINFLAG_SELFMUTED ? "(Muted)" : "", 01145 user->adminflags & ADMINFLAG_T_REQUEST ? "(Request to Talk)" : "", 01146 istalking(user->talking), hr, min, sec); 01147 } else { 01148 ast_cli(a->fd, "%d!%s!%s!%s!%s!%s!%s!%s!%d!%02d:%02d:%02d\n", 01149 user->user_no, 01150 S_OR(user->chan->cid.cid_num, ""), 01151 S_OR(user->chan->cid.cid_name, ""), 01152 user->chan->name, 01153 user->userflags & CONFFLAG_ADMIN ? "1" : "", 01154 user->userflags & CONFFLAG_MONITOR ? "1" : "", 01155 user->adminflags & (ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED) ? "1" : "", 01156 user->adminflags & ADMINFLAG_T_REQUEST ? "1" : "", 01157 user->talking, hr, min, sec); 01158 } 01159 } 01160 if (!concise) { 01161 ast_cli(a->fd, "%d users in that conference.\n", cnf->users); 01162 } 01163 AST_LIST_UNLOCK(&confs); 01164 ast_free(cmdline); 01165 return CLI_SUCCESS; 01166 } else { 01167 ast_free(cmdline); 01168 return CLI_SHOWUSAGE; 01169 } 01170 01171 ast_debug(1, "Cmdline: %s\n", cmdline->str); 01172 01173 admin_exec(NULL, cmdline->str); 01174 ast_free(cmdline); 01175 01176 return CLI_SUCCESS; 01177 }
| static int meetmemute | ( | struct mansession * | s, | |
| const struct message * | m, | |||
| int | mute | |||
| ) | [static] |
Definition at line 3641 of file app_meetme.c.
References ADMINFLAG_MUTED, ADMINFLAG_SELFMUTED, ADMINFLAG_T_REQUEST, 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_conf_user::user_no, and ast_conference::userlist.
Referenced by action_meetmemute(), and action_meetmeunmute().
03642 { 03643 struct ast_conference *conf; 03644 struct ast_conf_user *user; 03645 const char *confid = astman_get_header(m, "Meetme"); 03646 char *userid = ast_strdupa(astman_get_header(m, "Usernum")); 03647 int userno; 03648 03649 if (ast_strlen_zero(confid)) { 03650 astman_send_error(s, m, "Meetme conference not specified"); 03651 return 0; 03652 } 03653 03654 if (ast_strlen_zero(userid)) { 03655 astman_send_error(s, m, "Meetme user number not specified"); 03656 return 0; 03657 } 03658 03659 userno = strtoul(userid, &userid, 10); 03660 03661 if (*userid) { 03662 astman_send_error(s, m, "Invalid user number"); 03663 return 0; 03664 } 03665 03666 /* Look in the conference list */ 03667 AST_LIST_LOCK(&confs); 03668 AST_LIST_TRAVERSE(&confs, conf, list) { 03669 if (!strcmp(confid, conf->confno)) 03670 break; 03671 } 03672 03673 if (!conf) { 03674 AST_LIST_UNLOCK(&confs); 03675 astman_send_error(s, m, "Meetme conference does not exist"); 03676 return 0; 03677 } 03678 03679 AST_LIST_TRAVERSE(&conf->userlist, user, list) 03680 if (user->user_no == userno) 03681 break; 03682 03683 if (!user) { 03684 AST_LIST_UNLOCK(&confs); 03685 astman_send_error(s, m, "User number not found"); 03686 return 0; 03687 } 03688 03689 if (mute) 03690 user->adminflags |= ADMINFLAG_MUTED; /* request user muting */ 03691 else 03692 user->adminflags &= ~(ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED | ADMINFLAG_T_REQUEST); /* request user unmuting */ 03693 03694 AST_LIST_UNLOCK(&confs); 03695 03696 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); 03697 03698 astman_send_ack(s, m, mute ? "User muted" : "User unmuted"); 03699 return 0; 03700 }
| static enum ast_device_state meetmestate | ( | const char * | data | ) | [static] |
Callback for devicestate providers.
Definition at line 3852 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().
03853 { 03854 struct ast_conference *conf; 03855 03856 /* Find conference */ 03857 AST_LIST_LOCK(&confs); 03858 AST_LIST_TRAVERSE(&confs, conf, list) { 03859 if (!strcmp(data, conf->confno)) 03860 break; 03861 } 03862 AST_LIST_UNLOCK(&confs); 03863 if (!conf) 03864 return AST_DEVICE_INVALID; 03865 03866 03867 /* SKREP to fill */ 03868 if (!conf->users) 03869 return AST_DEVICE_NOT_INUSE; 03870 03871 return AST_DEVICE_INUSE; 03872 }
| static struct sla_ringing_trunk* queue_ringing_trunk | ( | struct sla_trunk * | trunk | ) | [static, read] |
Definition at line 5191 of file app_meetme.c.
References ALL_TRUNK_REFS, ast_calloc, AST_LIST_INSERT_HEAD, ast_mutex_lock(), ast_mutex_unlock(), ast_tvnow(), sla_ringing_trunk::ring_begin, 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().
05192 { 05193 struct sla_ringing_trunk *ringing_trunk; 05194 05195 if (!(ringing_trunk = ast_calloc(1, sizeof(*ringing_trunk)))) 05196 return NULL; 05197 05198 ringing_trunk->trunk = trunk; 05199 ringing_trunk->ring_begin = ast_tvnow(); 05200 05201 sla_change_trunk_state(trunk, SLA_TRUNK_STATE_RINGING, ALL_TRUNK_REFS, NULL); 05202 05203 ast_mutex_lock(&sla.lock); 05204 AST_LIST_INSERT_HEAD(&sla.ringing_trunks, ringing_trunk, entry); 05205 ast_mutex_unlock(&sla.lock); 05206 05207 sla_queue_event(SLA_EVENT_RINGING_TRUNK); 05208 05209 return ringing_trunk; 05210 }
| static void * recordthread | ( | void * | args | ) | [static] |
Definition at line 3787 of file app_meetme.c.
References ast_closestream(), AST_FILE_MODE, 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_frame::frametype, ast_conference::lchan, ast_conference::listenlock, MEETME_RECORD_ACTIVE, MEETME_RECORD_OFF, MEETME_RECORD_TERMINATE, ast_conference::origframe, ast_conference::recordingfilename, ast_conference::recordingformat, s, and ast_conference::transframe.
03788 { 03789 struct ast_conference *cnf = args; 03790 struct ast_frame *f = NULL; 03791 int flags; 03792 struct ast_filestream *s = NULL; 03793 int res = 0; 03794 int x; 03795 const char *oldrecordingfilename = NULL; 03796 03797 if (!cnf || !cnf->lchan) { 03798 pthread_exit(0); 03799 } 03800 03801 ast_stopstream(cnf->lchan); 03802 flags = O_CREAT | O_TRUNC | O_WRONLY; 03803 03804 03805 cnf->recording = MEETME_RECORD_ACTIVE; 03806 while (ast_waitfor(cnf->lchan, -1) > -1) { 03807 if (cnf->recording == MEETME_RECORD_TERMINATE) { 03808 AST_LIST_LOCK(&confs); 03809 AST_LIST_UNLOCK(&confs); 03810 break; 03811 } 03812 if (!s && cnf->recordingfilename && (cnf->recordingfilename != oldrecordingfilename)) { 03813 s = ast_writefile(cnf->recordingfilename, cnf->recordingformat, NULL, flags, 0, AST_FILE_MODE); 03814 oldrecordingfilename = cnf->recordingfilename; 03815 } 03816 03817 f = ast_read(cnf->lchan); 03818 if (!f) { 03819 res = -1; 03820 break; 03821 } 03822 if (f->frametype == AST_FRAME_VOICE) { 03823 ast_mutex_lock(&cnf->listenlock); 03824 for (x = 0; x < AST_FRAME_BITS; x++) { 03825 /* Free any translations that have occured */ 03826 if (cnf->transframe[x]) { 03827 ast_frfree(cnf->transframe[x]); 03828 cnf->transframe[x] = NULL; 03829 } 03830 } 03831 if (cnf->origframe) 03832 ast_frfree(cnf->origframe); 03833 cnf->origframe = ast_frdup(f); 03834 ast_mutex_unlock(&cnf->listenlock); 03835 if (s) 03836 res = ast_writestream(s, f); 03837 if (res) { 03838 ast_frfree(f); 03839 break; 03840 } 03841 } 03842 ast_frfree(f); 03843 } 03844 cnf->recording = MEETME_RECORD_OFF; 03845 if (s) 03846 ast_closestream(s); 03847 03848 pthread_exit(0); 03849 }
| static int reload | ( | void | ) | [static] |
Definition at line 5903 of file app_meetme.c.
References ast_unload_realtime(), and load_config().
05904 { 05905 ast_unload_realtime("meetme"); 05906 return load_config(1); 05907 }
| static void reset_volumes | ( | struct ast_conf_user * | user | ) | [static] |
Definition at line 772 of file app_meetme.c.
References ast_channel_setoption(), AST_OPTION_RXGAIN, AST_OPTION_TXGAIN, and ast_conf_user::chan.
Referenced by admin_exec(), and conf_run().
00773 { 00774 signed char zero_volume = 0; 00775 00776 ast_channel_setoption(user->chan, AST_OPTION_TXGAIN, &zero_volume, sizeof(zero_volume), 0); 00777 ast_channel_setoption(user->chan, AST_OPTION_RXGAIN, &zero_volume, sizeof(zero_volume), 0); 00778 }
| static void* run_station | ( | void * | data | ) | [static] |
Definition at line 4090 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_free, ast_mutex_lock(), ast_mutex_unlock(), ast_set_flag, ast_str_append(), ast_str_create(), ast_str_set(), build_conf(), sla_trunk_ref::chan, run_station_args::cond, run_station_args::cond_lock, conf_run(), CONFFLAG_MARKEDEXIT, CONFFLAG_PASS_DTMF, CONFFLAG_QUIET, CONFFLAG_SLA_STATION, sla_station::dial, dispose_conf(), ast_flags::flags, sla_trunk::hold_stations, sla_trunk::name, sla_change_trunk_state(), SLA_TRUNK_STATE_IDLE, SLA_TRUNK_STATE_ONHOLD_BYME, sla_trunk_ref::state, run_station_args::station, ast_str::str, sla_trunk_ref::trunk, and run_station_args::trunk_ref.
Referenced by sla_handle_dial_state_event().
04091 { 04092 struct sla_station *station; 04093 struct sla_trunk_ref *trunk_ref; 04094 struct ast_str *conf_name = ast_str_create(16); 04095 struct ast_flags conf_flags = { 0 }; 04096 struct ast_conference *conf; 04097 04098 { 04099 struct run_station_args *args = data; 04100 station = args->station; 04101 trunk_ref = args->trunk_ref; 04102 ast_mutex_lock(args->cond_lock); 04103 ast_cond_signal(args->cond); 04104 ast_mutex_unlock(args->cond_lock); 04105 /* args is no longer valid here. */ 04106 } 04107 04108 ast_atomic_fetchadd_int((int *) &trunk_ref->trunk->active_stations, 1); 04109 ast_str_set(&conf_name, 0, "SLA_%s", trunk_ref->trunk->name); 04110 ast_set_flag(&conf_flags, 04111 CONFFLAG_QUIET | CONFFLAG_MARKEDEXIT | CONFFLAG_PASS_DTMF | CONFFLAG_SLA_STATION); 04112 answer_trunk_chan(trunk_ref->chan); 04113 conf = build_conf(conf_name->str, "", "", 0, 0, 1, trunk_ref->chan); 04114 if (conf) { 04115 conf_run(trunk_ref->chan, conf, conf_flags.flags, NULL); 04116 dispose_conf(conf); 04117 conf = NULL; 04118 } 04119 trunk_ref->chan = NULL; 04120 if (ast_atomic_dec_and_test((int *) &trunk_ref->trunk->active_stations) && 04121 trunk_ref->state != SLA_TRUNK_STATE_ONHOLD_BYME) { 04122 ast_str_append(&conf_name, 0, ",K"); 04123 admin_exec(NULL, conf_name->str); 04124 trunk_ref->trunk->hold_stations = 0; 04125 sla_change_trunk_state(trunk_ref->trunk, SLA_TRUNK_STATE_IDLE, ALL_TRUNK_REFS, NULL); 04126 } 04127 04128 ast_dial_join(station->dial); 04129 ast_dial_destroy(station->dial); 04130 station->dial = NULL; 04131 ast_free(conf_name); 04132 04133 return NULL; 04134 }
| static int set_listen_volume | ( | struct ast_conf_user * | user, | |
| int | volume | |||
| ) | [static] |
Definition at line 701 of file app_meetme.c.
References ast_channel_setoption(), AST_OPTION_TXGAIN, and ast_conf_user::chan.
Referenced by tweak_listen_volume().
00702 { 00703 char gain_adjust; 00704 00705 /* attempt to make the adjustment in the channel driver; 00706 if successful, don't adjust in the frame reading routine 00707 */ 00708 gain_adjust = gain_map[volume + 5]; 00709 00710 return ast_channel_setoption(user->chan, AST_OPTION_TXGAIN, &gain_adjust, sizeof(gain_adjust), 0); 00711 }
| static int set_talk_volume | ( | struct ast_conf_user * | user, | |
| int | volume | |||
| ) | [static] |
Definition at line 689 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().
00690 { 00691 char gain_adjust; 00692 00693 /* attempt to make the adjustment in the channel driver; 00694 if successful, don't adjust in the frame reading routine 00695 */ 00696 gain_adjust = gain_map[volume + 5]; 00697 00698 return ast_channel_setoption(user->chan, AST_OPTION_RXGAIN, &gain_adjust, sizeof(gain_adjust), 0); 00699 }
| static void sla_add_trunk_to_station | ( | struct sla_station * | station, | |
| struct ast_variable * | var | |||
| ) | [static] |
Definition at line 5537 of file app_meetme.c.
References ast_atomic_fetchadd_int(), ast_free, AST_LIST_INSERT_TAIL, ast_log(), AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_strdupa, create_trunk_ref(), LOG_ERROR, 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_trunk::stations, strsep(), sla_station::trunks, and ast_variable::value.
Referenced by sla_build_station().
05538 { 05539 struct sla_trunk *trunk; 05540 struct sla_trunk_ref *trunk_ref; 05541 struct sla_station_ref *station_ref; 05542 char *trunk_name, *options, *cur; 05543 05544 options = ast_strdupa(var->value); 05545 trunk_name = strsep(&options, ","); 05546 05547 AST_RWLIST_RDLOCK(&sla_trunks); 05548 AST_RWLIST_TRAVERSE(&sla_trunks, trunk, entry) { 05549 if (!strcasecmp(trunk->name, trunk_name)) 05550 break; 05551 } 05552 05553 AST_RWLIST_UNLOCK(&sla_trunks); 05554 if (!trunk) { 05555 ast_log(LOG_ERROR, "Trunk '%s' not found!\n", var->value); 05556 return; 05557 } 05558 if (!(trunk_ref = create_trunk_ref(trunk))) 05559 return; 05560 trunk_ref->state = SLA_TRUNK_STATE_IDLE; 05561 05562 while ((cur = strsep(&options, ","))) { 05563 char *name, *value = cur; 05564 name = strsep(&value, "="); 05565 if (!strcasecmp(name, "ringtimeout")) { 05566 if (sscanf(value, "%30u", &trunk_ref->ring_timeout) != 1) { 05567 ast_log(LOG_WARNING, "Invalid ringtimeout value '%s' for " 05568 "trunk '%s' on station '%s'\n", value, trunk->name, station->name); 05569 trunk_ref->ring_timeout = 0; 05570 } 05571 } else if (!strcasecmp(name, "ringdelay")) { 05572 if (sscanf(value, "%30u", &trunk_ref->ring_delay) != 1) { 05573 ast_log(LOG_WARNING, "Invalid ringdelay value '%s' for " 05574 "trunk '%s' on station '%s'\n", value, trunk->name, station->name); 05575 trunk_ref->ring_delay = 0; 05576 } 05577 } else { 05578 ast_log(LOG_WARNING, "Invalid option '%s' for " 05579 "trunk '%s' on station '%s'\n", name, trunk->name, station->name); 05580 } 05581 } 05582 05583 if (!(station_ref = sla_create_station_ref(station))) { 05584 ast_free(trunk_ref); 05585 return; 05586 } 05587 ast_atomic_fetchadd_int((int *) &trunk->num_stations, 1); 05588 AST_RWLIST_WRLOCK(&sla_trunks); 05589 AST_LIST_INSERT_TAIL(&trunk->stations, station_ref, entry); 05590 AST_RWLIST_UNLOCK(&sla_trunks); 05591 AST_LIST_INSERT_TAIL(&station->trunks, trunk_ref, entry); 05592 }
| static int sla_build_station | ( | struct ast_config * | cfg, | |
| const char * | cat | |||
| ) | [static] |
Definition at line 5594 of file app_meetme.c.
References ast_add_extension2(), ast_calloc, ast_context_find_or_create(), ast_free, ast_free_ptr(), AST_LIST_TRAVERSE, ast_log(), AST_MAX_APP, AST_MAX_EXTENSION, AST_RWLIST_INSERT_TAIL, AST_RWLIST_RDLOCK, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_strdup, ast_string_field_init, ast_string_field_set, ast_strlen_zero(), ast_variable_browse(), ast_variable_retrieve(), sla_station::autocontext, context, destroy_station(), exten, sla_station::hold_access, ast_variable::lineno, LOG_ERROR, LOG_WARNING, sla_trunk::name, sla_station::name, ast_variable::name, ast_variable::next, PRIORITY_HINT, sla_station::ring_delay, sla_station::ring_timeout, sla_add_trunk_to_station(), SLA_CONFIG_FILE, SLA_HOLD_OPEN, SLA_HOLD_PRIVATE, sla_registrar, sla_trunk_ref::trunk, sla_station::trunks, ast_variable::value, and var.
Referenced by sla_load_config().
05595 { 05596 struct sla_station *station; 05597 struct ast_variable *var; 05598 const char *dev; 05599 05600 if (!(dev = ast_variable_retrieve(cfg, cat, "device"))) { 05601 ast_log(LOG_ERROR, "SLA Station '%s' defined with no device!\n", cat); 05602 return -1; 05603 } 05604 05605 if (!(station = ast_calloc(1, sizeof(*station)))) 05606 return -1; 05607 if (ast_string_field_init(station, 32)) { 05608 ast_free(station); 05609 return -1; 05610 } 05611 05612 ast_string_field_set(station, name, cat); 05613 ast_string_field_set(station, device, dev); 05614 05615 for (var = ast_variable_browse(cfg, cat); var; var = var->next) { 05616 if (!strcasecmp(var->name, "trunk")) 05617 sla_add_trunk_to_station(station, var); 05618 else if (!strcasecmp(var->name, "autocontext")) 05619 ast_string_field_set(station, autocontext, var->value); 05620 else if (!strcasecmp(var->name, "ringtimeout")) { 05621 if (sscanf(var->value, "%30u", &station->ring_timeout) != 1) { 05622 ast_log(LOG_WARNING, "Invalid ringtimeout '%s' specified for station '%s'\n", 05623 var->value, station->name); 05624 station->ring_timeout = 0; 05625 } 05626 } else if (!strcasecmp(var->name, "ringdelay")) { 05627 if (sscanf(var->value, "%30u", &station->ring_delay) != 1) { 05628 ast_log(LOG_WARNING, "Invalid ringdelay '%s' specified for station '%s'\n", 05629 var->value, station->name); 05630 station->ring_delay = 0; 05631 } 05632 } else if (!strcasecmp(var->name, "hold")) { 05633 if (!strcasecmp(var->value, "private")) 05634 station->hold_access = SLA_HOLD_PRIVATE; 05635 else if (!strcasecmp(var->value, "open")) 05636 station->hold_access = SLA_HOLD_OPEN; 05637 else { 05638 ast_log(LOG_WARNING, "Invalid value '%s' for hold on station %s\n", 05639 var->value, station->name); 05640 } 05641 05642 } else if (strcasecmp(var->name, "type") && strcasecmp(var->name, "device")) { 05643 ast_log(LOG_ERROR, "Invalid option '%s' specified at line %d of %s!\n", 05644 var->name, var->lineno, SLA_CONFIG_FILE); 05645 } 05646 } 05647 05648 if (!ast_strlen_zero(station->autocontext)) { 05649 struct ast_context *context; 05650 struct sla_trunk_ref *trunk_ref; 05651 context = ast_context_find_or_create(NULL, NULL, station->autocontext, sla_registrar); 05652 if (!context) { 05653 ast_log(LOG_ERROR, "Failed to automatically find or create " 05654 "context '%s' for SLA!\n", station->autocontext); 05655 destroy_station(station); 05656 return -1; 05657 } 05658 /* The extension for when the handset goes off-hook. 05659 * exten => station1,1,SLAStation(station1) */ 05660 if (ast_add_extension2(context, 0 /* don't replace */, station->name, 1, 05661 NULL, NULL, slastation_app, ast_strdup(station->name), ast_free_ptr, sla_registrar)) { 05662 ast_log(LOG_ERROR, "Failed to automatically create extension " 05663 "for trunk '%s'!\n", station->name); 05664 destroy_station(station); 05665 return -1; 05666 } 05667 AST_RWLIST_RDLOCK(&sla_trunks); 05668 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) { 05669 char exten[AST_MAX_EXTENSION]; 05670 char hint[AST_MAX_APP]; 05671 snprintf(exten, sizeof(exten), "%s_%s", station->name, trunk_ref->trunk->name); 05672 snprintf(hint, sizeof(hint), "SLA:%s", exten); 05673 /* Extension for this line button 05674 * exten => station1_line1,1,SLAStation(station1_line1) */ 05675 if (ast_add_extension2(context, 0 /* don't replace */, exten, 1, 05676 NULL, NULL, slastation_app, ast_strdup(exten), ast_free_ptr, sla_registrar)) { 05677 ast_log(LOG_ERROR, "Failed to automatically create extension " 05678 "for trunk '%s'!\n", station->name); 05679 destroy_station(station); 05680 return -1; 05681 } 05682 /* Hint for this line button 05683 * exten => station1_line1,hint,SLA:station1_line1 */ 05684 if (ast_add_extension2(context, 0 /* don't replace */, exten, PRIORITY_HINT, 05685 NULL, NULL, hint, NULL, NULL, sla_registrar)) { 05686 ast_log(LOG_ERROR, "Failed to automatically create hint " 05687 "for trunk '%s'!\n", station->name); 05688 destroy_station(station); 05689 return -1; 05690 } 05691 } 05692 AST_RWLIST_UNLOCK(&sla_trunks); 05693 } 05694 05695 AST_RWLIST_WRLOCK(&sla_stations); 05696 AST_RWLIST_INSERT_TAIL(&sla_stations, station, entry); 05697 AST_RWLIST_UNLOCK(&sla_stations); 05698 05699 return 0; 05700 }
| static int sla_build_trunk | ( | struct ast_config * | cfg, | |
| const char * | cat | |||
| ) | [static] |
Definition at line 5459 of file app_meetme.c.
References ast_add_extension2(), ast_calloc, ast_context_find_or_create(), ast_false(), ast_free, ast_free_ptr(), ast_log(), AST_RWLIST_INSERT_TAIL, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_strdup, ast_string_field_init, ast_string_field_set, ast_strlen_zero(), ast_variable_browse(), ast_variable_retrieve(), sla_trunk::autocontext, sla_trunk::barge_disabled, context, destroy_trunk(), sla_trunk::hold_access, ast_variable::lineno, LOG_ERROR, LOG_WARNING, sla_trunk::name, ast_variable::name, ast_variable::next, sla_trunk::ring_timeout, sla_check_device(), SLA_CONFIG_FILE, SLA_HOLD_OPEN, SLA_HOLD_PRIVATE, sla_registrar, ast_variable::value, and var.
Referenced by sla_load_config().
05460 { 05461 struct sla_trunk *trunk; 05462 struct ast_variable *var; 05463 const char *dev; 05464 05465 if (!(dev = ast_variable_retrieve(cfg, cat, "device"))) { 05466 ast_log(LOG_ERROR, "SLA Trunk '%s' defined with no device!\n", cat); 05467 return -1; 05468 } 05469 05470 if (sla_check_device(dev)) { 05471 ast_log(LOG_ERROR, "SLA Trunk '%s' define with invalid device '%s'!\n", 05472 cat, dev); 05473 return -1; 05474 } 05475 05476 if (!(trunk = ast_calloc(1, sizeof(*trunk)))) 05477 return -1; 05478 if (ast_string_field_init(trunk, 32)) { 05479 ast_free(trunk); 05480 return -1; 05481 } 05482 05483 ast_string_field_set(trunk, name, cat); 05484 ast_string_field_set(trunk, device, dev); 05485 05486 for (var = ast_variable_browse(cfg, cat); var; var = var->next) { 05487 if (!strcasecmp(var->name, "autocontext")) 05488 ast_string_field_set(trunk, autocontext, var->value); 05489 else if (!strcasecmp(var->name, "ringtimeout")) { 05490 if (sscanf(var->value, "%30u", &trunk->ring_timeout) != 1) { 05491 ast_log(LOG_WARNING, "Invalid ringtimeout '%s' specified for trunk '%s'\n", 05492 var->value, trunk->name); 05493 trunk->ring_timeout = 0; 05494 } 05495 } else if (!strcasecmp(var->name, "barge")) 05496 trunk->barge_disabled = ast_false(var->value); 05497 else if (!strcasecmp(var->name, "hold")) { 05498 if (!strcasecmp(var->value, "private")) 05499 trunk->hold_access = SLA_HOLD_PRIVATE; 05500 else if (!strcasecmp(var->value, "open")) 05501 trunk->hold_access = SLA_HOLD_OPEN; 05502 else { 05503 ast_log(LOG_WARNING, "Invalid value '%s' for hold on trunk %s\n", 05504 var->value, trunk->name); 05505 } 05506 } else if (strcasecmp(var->name, "type") && strcasecmp(var->name, "device")) { 05507 ast_log(LOG_ERROR, "Invalid option '%s' specified at line %d of %s!\n", 05508 var->name, var->lineno, SLA_CONFIG_FILE); 05509 } 05510 } 05511 05512 if (!ast_strlen_zero(trunk->autocontext)) { 05513 struct ast_context *context; 05514 context = ast_context_find_or_create(NULL, NULL, trunk->autocontext, sla_registrar); 05515 if (!context) { 05516 ast_log(LOG_ERROR, "Failed to automatically find or create " 05517 "context '%s' for SLA!\n", trunk->autocontext); 05518 destroy_trunk(trunk); 05519 return -1; 05520 } 05521 if (ast_add_extension2(context, 0 /* don't replace */, "s", 1, 05522 NULL, NULL, slatrunk_app, ast_strdup(trunk->name), ast_free_ptr, sla_registrar)) { 05523 ast_log(LOG_ERROR, "Failed to automatically create extension " 05524 "for trunk '%s'!\n", trunk->name); 05525 destroy_trunk(trunk); 05526 return -1; 05527 } 05528 } 05529 05530 AST_RWLIST_WRLOCK(&sla_trunks); 05531 AST_RWLIST_INSERT_TAIL(&sla_trunks, trunk, entry); 05532 AST_RWLIST_UNLOCK(&sla_trunks); 05533 05534 return 0; 05535 }
| static int sla_calc_station_delays | ( | unsigned int * | timeout | ) | [static] |
Calculate the ring delay for a station.
Definition at line 4703 of file app_meetme.c.
References AST_LIST_TRAVERSE, sla_check_inuse_station(), sla_check_ringing_station(), sla_check_station_delay(), and sla_choose_ringing_trunk().
Referenced by sla_process_timers().
04704 { 04705 struct sla_station *station; 04706 int res = 0; 04707 04708 AST_LIST_TRAVERSE(&sla_stations, station, entry) { 04709 struct sla_ringing_trunk *ringing_trunk; 04710 int time_left; 04711 04712 /* Ignore stations already ringing */ 04713 if (sla_check_ringing_station(station)) 04714 continue; 04715 04716 /* Ignore stations already on a call */ 04717 if (sla_check_inuse_station(station)) 04718 continue; 04719 04720 /* Ignore stations that don't have one of their trunks ringing */ 04721 if (!(ringing_trunk = sla_choose_ringing_trunk(station, NULL, 0))) 04722 continue; 04723 04724 if ((time_left = sla_check_station_delay(station, ringing_trunk)) == INT_MAX) 04725 continue; 04726 04727 /* If there is no time left, then the station needs to start ringing. 04728 * Return non-zero so that an event will be queued up an event to 04729 * make that happen. */ 04730 if (time_left <= 0) { 04731 res = 1; 04732 continue; 04733 } 04734 04735 if (time_left < *timeout) 04736 *timeout = time_left; 04737 } 04738 04739 return res; 04740 }
| static int sla_calc_station_timeouts | ( | unsigned int * | timeout | ) | [static] |
Process station ring timeouts.
Definition at line 4620 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(), 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().
04621 { 04622 struct sla_ringing_trunk *ringing_trunk; 04623 struct sla_ringing_station *ringing_station; 04624 int res = 0; 04625 04626 AST_LIST_TRAVERSE_SAFE_BEGIN(&sla.ringing_stations, ringing_station, entry) { 04627 unsigned int ring_timeout = 0; 04628 int time_elapsed, time_left = INT_MAX, final_trunk_time_left = INT_MIN; 04629 struct sla_trunk_ref *trunk_ref; 04630 04631 /* If there are any ring timeouts specified for a specific trunk 04632 * on the station, then use the highest per-trunk ring timeout. 04633 * Otherwise, use the ring timeout set for the entire station. */ 04634 AST_LIST_TRAVERSE(&ringing_station->station->trunks, trunk_ref, entry) { 04635 struct sla_station_ref *station_ref; 04636 int trunk_time_elapsed, trunk_time_left; 04637 04638 AST_LIST_TRAVERSE(&sla.ringing_trunks, ringing_trunk, entry) { 04639 if (ringing_trunk->trunk == trunk_ref->trunk) 04640 break; 04641 } 04642 if (!ringing_trunk) 04643 continue; 04644 04645 /* If there is a trunk that is ringing without a timeout, then the 04646 * only timeout that could matter is a global station ring timeout. */ 04647 if (!trunk_ref->ring_timeout) 04648 break; 04649 04650 /* This trunk on this station is ringing and has a timeout. 04651 * However, make sure this trunk isn't still ringing from a 04652 * previous timeout. If so, don't consider it. */ 04653 AST_LIST_TRAVERSE(&ringing_trunk->timed_out_stations, station_ref, entry) { 04654 if (station_ref->station == ringing_station->station) 04655 break; 04656 } 04657 if (station_ref) 04658 continue; 04659 04660 trunk_time_elapsed = ast_tvdiff_ms(ast_tvnow(), ringing_trunk->ring_begin); 04661 trunk_time_left = (trunk_ref->ring_timeout * 1000) - trunk_time_elapsed; 04662 if (trunk_time_left > final_trunk_time_left) 04663 final_trunk_time_left = trunk_time_left; 04664 } 04665 04666 /* No timeout was found for ringing trunks, and no timeout for the entire station */ 04667 if (final_trunk_time_left == INT_MIN && !ringing_station->station->ring_timeout) 04668 continue; 04669 04670 /* Compute how much time is left for a global station timeout */ 04671 if (ringing_station->station->ring_timeout) { 04672 ring_timeout = ringing_station->station->ring_timeout; 04673 time_elapsed = ast_tvdiff_ms(ast_tvnow(), ringing_station->ring_begin); 04674 time_left = (ring_timeout * 1000) - time_elapsed; 04675 } 04676 04677 /* If the time left based on the per-trunk timeouts is smaller than the 04678 * global station ring timeout, use that. */ 04679 if (final_trunk_time_left > INT_MIN && final_trunk_time_left < time_left) 04680 time_left = final_trunk_time_left; 04681 04682 /* If there is no time left, the station needs to stop ringing */ 04683 if (time_left <= 0) { 04684 AST_LIST_REMOVE_CURRENT(entry); 04685 sla_stop_ringing_station(ringing_station, SLA_STATION_HANGUP_TIMEOUT); 04686 res = 1; 04687 continue; 04688 } 04689 04690 /* There is still some time left for this station to ring, so save that 04691 * timeout if it is the first event scheduled to occur */ 04692 if (time_left < *timeout) 04693 *timeout = time_left; 04694 } 04695 AST_LIST_TRAVERSE_SAFE_END; 04696 04697 return res; 04698 }
| static int sla_calc_trunk_timeouts | ( | unsigned int * | timeout | ) | [static] |
Process trunk ring timeouts.
Definition at line 4590 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, 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().
04591 { 04592 struct sla_ringing_trunk *ringing_trunk; 04593 int res = 0; 04594 04595 AST_LIST_TRAVERSE_SAFE_BEGIN(&sla.ringing_trunks, ringing_trunk, entry) { 04596 int time_left, time_elapsed; 04597 if (!ringing_trunk->trunk->ring_timeout) 04598 continue; 04599 time_elapsed = ast_tvdiff_ms(ast_tvnow(), ringing_trunk->ring_begin); 04600 time_left = (ringing_trunk->trunk->ring_timeout * 1000) - time_elapsed; 04601 if (time_left <= 0) { 04602 pbx_builtin_setvar_helper(ringing_trunk->trunk->chan, "SLATRUNK_STATUS", "RINGTIMEOUT"); 04603 AST_LIST_REMOVE_CURRENT(entry); 04604 sla_stop_ringing_trunk(ringing_trunk); 04605 res = 1; 04606 continue; 04607 } 04608 if (time_left < *timeout) 04609 *timeout = time_left; 04610 } 04611 AST_LIST_TRAVERSE_SAFE_END; 04612 04613 return res; 04614 }
| 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 4058 of file app_meetme.c.
References ast_devstate_changed(), AST_LIST_TRAVERSE, sla_trunk_ref::chan, sla_trunk::name, sla_station::name, sla_state_to_devstate(), sla_trunk_ref::state, sla_trunk_ref::trunk, and sla_station::trunks.
Referenced by dial_trunk(), 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().
04060 { 04061 struct sla_station *station; 04062 struct sla_trunk_ref *trunk_ref; 04063 04064 AST_LIST_TRAVERSE(&sla_stations, station, entry) { 04065 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) { 04066 if (trunk_ref->trunk != trunk || (inactive_only ? trunk_ref->chan : 0) 04067 || trunk_ref == exclude) 04068 continue; 04069 trunk_ref->state = state; 04070 ast_devstate_changed(sla_state_to_devstate(state), 04071 "SLA:%s_%s", station->name, trunk->name); 04072 break; 04073 } 04074 } 04075 }
| static int sla_check_device | ( | const char * | device | ) | [static] |
Definition at line 5446 of file app_meetme.c.
References ast_strdupa, ast_strlen_zero(), and strsep().
Referenced by sla_build_trunk().
05447 { 05448 char *tech, *tech_data; 05449 05450 tech_data = ast_strdupa(device); 05451 tech = strsep(&tech_data, "/"); 05452 05453 if (ast_strlen_zero(tech) || ast_strlen_zero(tech_data)) 05454 return -1; 05455 05456 return 0; 05457 }
| 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 4338 of file app_meetme.c.
References ast_free, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_tvdiff_ms(), ast_tvnow(), sla_failed_station::last_try, sla, and sla_failed_station::station.
Referenced by sla_ring_stations().
04339 { 04340 struct sla_failed_station *failed_station; 04341 int res = 0; 04342 04343 AST_LIST_TRAVERSE_SAFE_BEGIN(&sla.failed_stations, failed_station, entry) { 04344 if (station != failed_station->station) 04345 continue; 04346 if (ast_tvdiff_ms(ast_tvnow(), failed_station->last_try) > 1000) { 04347 AST_LIST_REMOVE_CURRENT(entry); 04348 ast_free(failed_station); 04349 break; 04350 } 04351 res = 1; 04352 } 04353 AST_LIST_TRAVERSE_SAFE_END 04354 04355 return res; 04356 }
| static int sla_check_inuse_station | ( | const struct sla_station * | station | ) | [static] |
Check to see if a station is in use.
Definition at line 4424 of file app_meetme.c.
References AST_LIST_TRAVERSE, sla_trunk_ref::chan, and sla_station::trunks.
Referenced by sla_calc_station_delays(), and sla_ring_stations().
04425 { 04426 struct sla_trunk_ref *trunk_ref; 04427 04428 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) { 04429 if (trunk_ref->chan) 04430 return 1; 04431 } 04432 04433 return 0; 04434 }
| static void sla_check_reload | ( | void | ) | [static] |
Check if we can do a reload of SLA, and do it if we can.
Definition at line 4782 of file app_meetme.c.
References AST_LIST_EMPTY, ast_mutex_lock(), ast_mutex_unlock(), AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, sla_trunk::ref_count, sla_station::ref_count, sla, and sla_load_config().
Referenced by sla_thread().
04783 { 04784 struct sla_station *station; 04785 struct sla_trunk *trunk; 04786 04787 ast_mutex_lock(&sla.lock); 04788 04789 if (!AST_LIST_EMPTY(&sla.event_q) || !AST_LIST_EMPTY(&sla.ringing_trunks) 04790 || !AST_LIST_EMPTY(&sla.ringing_stations)) { 04791 ast_mutex_unlock(&sla.lock); 04792 return; 04793 } 04794 04795 AST_RWLIST_RDLOCK(&sla_stations); 04796 AST_RWLIST_TRAVERSE(&sla_stations, station, entry) { 04797 if (station->ref_count) 04798 break; 04799 } 04800 AST_RWLIST_UNLOCK(&sla_stations); 04801 if (station) { 04802 ast_mutex_unlock(&sla.lock); 04803 return; 04804 } 04805 04806 AST_RWLIST_RDLOCK(&sla_trunks); 04807 AST_RWLIST_TRAVERSE(&sla_trunks, trunk, entry) { 04808 if (trunk->ref_count) 04809 break; 04810 } 04811 AST_RWLIST_UNLOCK(&sla_trunks); 04812 if (trunk) { 04813 ast_mutex_unlock(&sla.lock); 04814 return; 04815 } 04816 04817 /* yay */ 04818 sla_load_config(1); 04819 sla.reload = 0; 04820 04821 ast_mutex_unlock(&sla.lock); 04822 }
| static int sla_check_ringing_station | ( | const struct sla_station * | station | ) | [static] |
Check to see if this station is already ringing.
Definition at line 4323 of file app_meetme.c.
References AST_LIST_TRAVERSE, sla, and sla_ringing_station::station.
Referenced by sla_calc_station_delays(), and sla_ring_stations().
04324 { 04325 struct sla_ringing_station *ringing_station; 04326 04327 AST_LIST_TRAVERSE(&sla.ringing_stations, ringing_station, entry) { 04328 if (station == ringing_station->station) 04329 return 1; 04330 } 04331 04332 return 0; 04333 }
| 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 | |
| ringing_trunk | the trunk. If NULL, the highest priority ringing trunk will be used |
Definition at line 4454 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().
04456 { 04457 struct sla_trunk_ref *trunk_ref; 04458 unsigned int delay = UINT_MAX; 04459 int time_left, time_elapsed; 04460 04461 if (!ringing_trunk) 04462 ringing_trunk = sla_choose_ringing_trunk(station, &trunk_ref, 0); 04463 else 04464 trunk_ref = sla_find_trunk_ref(station, ringing_trunk->trunk); 04465 04466 if (!ringing_trunk || !trunk_ref) 04467 return delay; 04468 04469 /* If this station has a ring delay specific to the highest priority 04470 * ringing trunk, use that. Otherwise, use the ring delay specified 04471 * globally for the station. */ 04472 delay = trunk_ref->ring_delay; 04473 if (!delay) 04474 delay = station->ring_delay; 04475 if (!delay) 04476 return INT_MAX; 04477 04478 time_elapsed = ast_tvdiff_ms(ast_tvnow(), ringing_trunk->ring_begin); 04479 time_left = (delay * 1000) - time_elapsed; 04480 04481 return time_left; 04482 }
| static int sla_check_station_hold_access | ( | const struct sla_trunk * | trunk, | |
| const struct sla_station * | station | |||
| ) | [static] |
Definition at line 3963 of file app_meetme.c.
References AST_LIST_TRAVERSE, 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().
03965 { 03966 struct sla_station_ref *station_ref; 03967 struct sla_trunk_ref *trunk_ref; 03968 03969 /* For each station that has this call on hold, check for private hold. */ 03970 AST_LIST_TRAVERSE(&trunk->stations, station_ref, entry) { 03971 AST_LIST_TRAVERSE(&station_ref->station->trunks, trunk_ref, entry) { 03972 if (trunk_ref->trunk != trunk || station_ref->station == station) 03973 continue; 03974 if (trunk_ref->state == SLA_TRUNK_STATE_ONHOLD_BYME && 03975 station_ref->station->hold_access == SLA_HOLD_PRIVATE) 03976 return 1; 03977 return 0; 03978 } 03979 } 03980 03981 return 0; 03982 }
| 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 4194 of file app_meetme.c.
References AST_LIST_TRAVERSE, sla_station_ref::station, and sla_ringing_trunk::timed_out_stations.
Referenced by sla_choose_ringing_trunk(), and sla_ring_stations().
04196 { 04197 struct sla_station_ref *timed_out_station; 04198 04199 AST_LIST_TRAVERSE(&ringing_trunk->timed_out_stations, timed_out_station, entry) { 04200 if (station == timed_out_station->station) 04201 return 1; 04202 } 04203 04204 return 0; 04205 }
| static struct sla_trunk_ref* sla_choose_idle_trunk | ( | const struct sla_station * | station | ) | [static, read] |
For a given station, choose the highest priority idle trunk.
Definition at line 5006 of file app_meetme.c.
References AST_LIST_TRAVERSE, SLA_TRUNK_STATE_IDLE, sla_trunk_ref::state, and sla_station::trunks.
Referenced by sla_station_exec().
05007 { 05008 struct sla_trunk_ref *trunk_ref = NULL; 05009 05010 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) { 05011 if (trunk_ref->state == SLA_TRUNK_STATE_IDLE) 05012 break; 05013 } 05014 05015 return trunk_ref; 05016 }
| static struct sla_ringing_trunk* sla_choose_ringing_trunk | ( | struct sla_station * | station, | |
| struct sla_trunk_ref ** | trunk_ref, | |||
| int | rm | |||
| ) | [static, read] |
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 4215 of file app_meetme.c.
References AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, 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().
04217 { 04218 struct sla_trunk_ref *s_trunk_ref; 04219 struct sla_ringing_trunk *ringing_trunk = NULL; 04220 04221 AST_LIST_TRAVERSE(&station->trunks, s_trunk_ref, entry) { 04222 AST_LIST_TRAVERSE_SAFE_BEGIN(&sla.ringing_trunks, ringing_trunk, entry) { 04223 /* Make sure this is the trunk we're looking for */ 04224 if (s_trunk_ref->trunk != ringing_trunk->trunk) 04225 continue; 04226 04227 /* This trunk on the station is ringing. But, make sure this station 04228 * didn't already time out while this trunk was ringing. */ 04229 if (sla_check_timed_out_station(ringing_trunk, station)) 04230 continue; 04231 04232 if (rm) 04233 AST_LIST_REMOVE_CURRENT(entry); 04234 04235 if (trunk_ref) 04236 *trunk_ref = s_trunk_ref; 04237 04238 break; 04239 } 04240 AST_LIST_TRAVERSE_SAFE_END; 04241 04242 if (ringing_trunk) 04243 break; 04244 } 04245 04246 return ringing_trunk; 04247 }
| static struct sla_ringing_station* sla_create_ringing_station | ( | struct sla_station * | station | ) | [static, read] |
Definition at line 4028 of file app_meetme.c.
References ast_calloc, ast_tvnow(), sla_ringing_station::ring_begin, and sla_ringing_station::station.
Referenced by sla_ring_station().
04029 { 04030 struct sla_ringing_station *ringing_station; 04031 04032 if (!(ringing_station = ast_calloc(1, sizeof(*ringing_station)))) 04033 return NULL; 04034 04035 ringing_station->station = station; 04036 ringing_station->ring_begin = ast_tvnow(); 04037 04038 return ringing_station; 04039 }
| static struct sla_station_ref* sla_create_station_ref | ( | struct sla_station * | station | ) | [static, read] |
Definition at line 4016 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().
04017 { 04018 struct sla_station_ref *station_ref; 04019 04020 if (!(station_ref = ast_calloc(1, sizeof(*station_ref)))) 04021 return NULL; 04022 04023 station_ref->station = station; 04024 04025 return station_ref; 04026 }
| static void sla_destroy | ( | void | ) | [static] |
Definition at line 5416 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(), sla, and sla_registrar.
Referenced by unload_module().
05417 { 05418 struct sla_trunk *trunk; 05419 struct sla_station *station; 05420 05421 AST_RWLIST_WRLOCK(&sla_trunks); 05422 while ((trunk = AST_RWLIST_REMOVE_HEAD(&sla_trunks, entry))) 05423 destroy_trunk(trunk); 05424 AST_RWLIST_UNLOCK(&sla_trunks); 05425 05426 AST_RWLIST_WRLOCK(&sla_stations); 05427 while ((station = AST_RWLIST_REMOVE_HEAD(&sla_stations, entry))) 05428 destroy_station(station); 05429 AST_RWLIST_UNLOCK(&sla_stations); 05430 05431 if (sla.thread != AST_PTHREADT_NULL) { 05432 ast_mutex_lock(&sla.lock); 05433 sla.stop = 1; 05434 ast_cond_signal(&sla.cond); 05435 ast_mutex_unlock(&sla.lock); 05436 pthread_join(sla.thread, NULL); 05437 } 05438 05439 /* Drop any created contexts from the dialplan */ 05440 ast_context_destroy(NULL, sla_registrar); 05441 05442 ast_mutex_destroy(&sla.lock); 05443 ast_cond_destroy(&sla.cond); 05444 }
| static void sla_dial_state_callback | ( | struct ast_dial * | dial | ) | [static] |
Definition at line 4186 of file app_meetme.c.
References SLA_EVENT_DIAL_STATE, and sla_queue_event().
Referenced by sla_ring_station().
04187 { 04188 sla_queue_event(SLA_EVENT_DIAL_STATE); 04189 }
| static struct sla_station* sla_find_station | ( | const char * | name | ) | [static, read] |
Find an SLA station by name.
Definition at line 3951 of file app_meetme.c.
References AST_RWLIST_TRAVERSE, and sla_station::name.
Referenced by sla_station_exec().
03952 { 03953 struct sla_station *station = NULL; 03954 03955 AST_RWLIST_TRAVERSE(&sla_stations, station, entry) { 03956 if (!strcasecmp(station->name, name)) 03957 break; 03958 } 03959 03960 return station; 03961 }
| static struct sla_trunk* sla_find_trunk | ( | const char * | name | ) | [static, read] |
Find an SLA trunk by name.
Definition at line 3936 of file app_meetme.c.
References AST_RWLIST_TRAVERSE, and sla_trunk::name.
Referenced by sla_trunk_exec().
03937 { 03938 struct sla_trunk *trunk = NULL; 03939 03940 AST_RWLIST_TRAVERSE(&sla_trunks, trunk, entry) { 03941 if (!strcasecmp(trunk->name, name)) 03942 break; 03943 } 03944 03945 return trunk; 03946 }
| static struct sla_trunk_ref* sla_find_trunk_ref | ( | const struct sla_station * | station, | |
| const struct sla_trunk * | trunk | |||
| ) | [static, read] |
Definition at line 4436 of file app_meetme.c.
References AST_LIST_TRAVERSE, sla_trunk_ref::trunk, and sla_station::trunks.
Referenced by sla_check_station_delay().
04438 { 04439 struct sla_trunk_ref *trunk_ref = NULL; 04440 04441 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) { 04442 if (trunk_ref->trunk == trunk) 04443 break; 04444 } 04445 04446 return trunk_ref; 04447 }
| static struct sla_trunk_ref* sla_find_trunk_ref_byname | ( | const struct sla_station * | station, | |
| const char * | name | |||
| ) | [static, read] |
Find a trunk reference on a station by name.
| station | the station | |
| name | the trunk's name |
Definition at line 3991 of file app_meetme.c.
References AST_LIST_TRAVERSE, sla_trunk::barge_disabled, 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().
03993 { 03994 struct sla_trunk_ref *trunk_ref = NULL; 03995 03996 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) { 03997 if (strcasecmp(trunk_ref->trunk->name, name)) 03998 continue; 03999 04000 if ( (trunk_ref->trunk->barge_disabled 04001 && trunk_ref->state == SLA_TRUNK_STATE_UP) || 04002 (trunk_ref->trunk->hold_stations 04003 && trunk_ref->trunk->hold_access == SLA_HOLD_PRIVATE 04004 && trunk_ref->state != SLA_TRUNK_STATE_ONHOLD_BYME) || 04005 sla_check_station_hold_access(trunk_ref->trunk, station) ) 04006 { 04007 trunk_ref = NULL; 04008 } 04009 04010 break; 04011 } 04012 04013 return trunk_ref; 04014 }
| static void sla_handle_dial_state_event | ( | void | ) | [static] |
Definition at line 4249 of file app_meetme.c.
References ALL_TRUNK_REFS, answer_trunk_chan(), ast_cond_destroy(), ast_cond_init(), ast_cond_wait(), ast_debug, 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_free, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_mutex_destroy(), ast_mutex_init(), ast_mutex_lock(), ast_mutex_unlock(), ast_pthread_create_detached_background, sla_trunk::chan, sla_trunk_ref::chan, run_station_args::cond, run_station_args::cond_lock, sla_station::dial, 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().
04250 { 04251 struct sla_ringing_station *ringing_station; 04252 04253 AST_LIST_TRAVERSE_SAFE_BEGIN(&sla.ringing_stations, ringing_station, entry) { 04254 struct sla_trunk_ref *s_trunk_ref = NULL; 04255 struct sla_ringing_trunk *ringing_trunk = NULL; 04256 struct run_station_args args; 04257 enum ast_dial_result dial_res; 04258 pthread_t dont_care; 04259 ast_mutex_t cond_lock; 04260 ast_cond_t cond; 04261 04262 switch ((dial_res = ast_dial_state(ringing_station->station->dial))) { 04263 case AST_DIAL_RESULT_HANGUP: 04264 case AST_DIAL_RESULT_INVALID: 04265 case AST_DIAL_RESULT_FAILED: 04266 case AST_DIAL_RESULT_TIMEOUT: 04267 case AST_DIAL_RESULT_UNANSWERED: 04268 AST_LIST_REMOVE_CURRENT(entry); 04269 sla_stop_ringing_station(ringing_station, SLA_STATION_HANGUP_NORMAL); 04270 break; 04271 case AST_DIAL_RESULT_ANSWERED: 04272 AST_LIST_REMOVE_CURRENT(entry); 04273 /* Find the appropriate trunk to answer. */ 04274 ast_mutex_lock(&sla.lock); 04275 ringing_trunk = sla_choose_ringing_trunk(ringing_station->station, &s_trunk_ref, 1); 04276 ast_mutex_unlock(&sla.lock); 04277 if (!ringing_trunk) { 04278 ast_debug(1, "Found no ringing trunk for station '%s' to answer!\n", ringing_station->station->name); 04279 break; 04280 } 04281 /* Track the channel that answered this trunk */ 04282 s_trunk_ref->chan = ast_dial_answered(ringing_station->station->dial); 04283 /* Actually answer the trunk */ 04284 answer_trunk_chan(ringing_trunk->trunk->chan); 04285 sla_change_trunk_state(ringing_trunk->trunk, SLA_TRUNK_STATE_UP, ALL_TRUNK_REFS, NULL); 04286 /* Now, start a thread that will connect this station to the trunk. The rest of 04287 * the code here sets up the thread and ensures that it is able to save the arguments 04288 * before they are no longer valid since they are allocated on the stack. */ 04289 args.trunk_ref = s_trunk_ref; 04290 args.station = ringing_station->station; 04291 args.cond = &cond; 04292 args.cond_lock = &cond_lock; 04293 ast_free(ringing_trunk); 04294 ast_free(ringing_station); 04295 ast_mutex_init(&cond_lock); 04296 ast_cond_init(&cond, NULL); 04297 ast_mutex_lock(&cond_lock); 04298 ast_pthread_create_detached_background(&dont_care, NULL, run_station, &args); 04299 ast_cond_wait(&cond, &cond_lock); 04300 ast_mutex_unlock(&cond_lock); 04301 ast_mutex_destroy(&cond_lock); 04302 ast_cond_destroy(&cond); 04303 break; 04304 case AST_DIAL_RESULT_TRYING: 04305 case AST_DIAL_RESULT_RINGING: 04306 case AST_DIAL_RESULT_PROGRESS: 04307 case AST_DIAL_RESULT_PROCEEDING: 04308 break; 04309 } 04310 if (dial_res == AST_DIAL_RESULT_ANSWERED) { 04311 /* Queue up reprocessing ringing trunks, and then ringing stations again */ 04312 sla_queue_event(SLA_EVENT_RINGING_TRUNK); 04313 sla_queue_event(SLA_EVENT_DIAL_STATE); 04314 break; 04315 } 04316 } 04317 AST_LIST_TRAVERSE_SAFE_END; 04318 }
| static void sla_handle_hold_event | ( | struct sla_event * | event | ) | [static] |
Definition at line 4566 of file app_meetme.c.
References sla_trunk::active_stations, ast_atomic_fetchadd_int(), AST_CAUSE_NORMAL, AST_CONTROL_HOLD, AST_DEVICE_ONHOLD, ast_devstate_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_change_trunk_state(), SLA_TRUNK_STATE_ONHOLD, SLA_TRUNK_STATE_ONHOLD_BYME, sla_event::station, sla_trunk_ref::trunk, and sla_event::trunk_ref.
Referenced by sla_thread().
04567 { 04568 ast_atomic_fetchadd_int((int *) &event->trunk_ref->trunk->hold_stations, 1); 04569 event->trunk_ref->state = SLA_TRUNK_STATE_ONHOLD_BYME; 04570 ast_devstate_changed(AST_DEVICE_ONHOLD, "SLA:%s_%s", 04571 event->station->name, event->trunk_ref->trunk->name); 04572 sla_change_trunk_state(event->trunk_ref->trunk, SLA_TRUNK_STATE_ONHOLD, 04573 INACTIVE_TRUNK_REFS, event->trunk_ref); 04574 04575 if (event->trunk_ref->trunk->active_stations == 1) { 04576 /* The station putting it on hold is the only one on the call, so start 04577 * Music on hold to the trunk. */ 04578 event->trunk_ref->trunk->on_hold = 1; 04579 ast_indicate(event->trunk_ref->trunk->chan, AST_CONTROL_HOLD); 04580 } 04581 04582 ast_softhangup(event->trunk_ref->chan, AST_CAUSE_NORMAL); 04583 event->trunk_ref->chan = NULL; 04584 }
| static void sla_handle_ringing_trunk_event | ( | void | ) | [static] |
Definition at line 4556 of file app_meetme.c.
References ast_mutex_lock(), ast_mutex_unlock(), sla, sla_hangup_stations(), and sla_ring_stations().
Referenced by sla_thread().
04557 { 04558 ast_mutex_lock(&sla.lock); 04559 sla_ring_stations(); 04560 ast_mutex_unlock(&sla.lock); 04561 04562 /* Find stations that shouldn't be ringing anymore. */ 04563 sla_hangup_stations(); 04564 }
| static void sla_hangup_stations | ( | void | ) | [static] |
Definition at line 4528 of file app_meetme.c.
References ast_dial_destroy(), ast_dial_join(), ast_free, 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, sla, sla_ringing_station::station, sla_ringing_trunk::trunk, sla_trunk_ref::trunk, and sla_station::trunks.
Referenced by sla_handle_ringing_trunk_event().
04529 { 04530 struct sla_trunk_ref *trunk_ref; 04531 struct sla_ringing_station *ringing_station; 04532 04533 AST_LIST_TRAVERSE_SAFE_BEGIN(&sla.ringing_stations, ringing_station, entry) { 04534 AST_LIST_TRAVERSE(&ringing_station->station->trunks, trunk_ref, entry) { 04535 struct sla_ringing_trunk *ringing_trunk; 04536 ast_mutex_lock(&sla.lock); 04537 AST_LIST_TRAVERSE(&sla.ringing_trunks, ringing_trunk, entry) { 04538 if (trunk_ref->trunk == ringing_trunk->trunk) 04539 break; 04540 } 04541 ast_mutex_unlock(&sla.lock); 04542 if (ringing_trunk) 04543 break; 04544 } 04545 if (!trunk_ref) { 04546 AST_LIST_REMOVE_CURRENT(entry); 04547 ast_dial_join(ringing_station->station->dial); 04548 ast_dial_destroy(ringing_station->station->dial); 04549 ringing_station->station->dial = NULL; 04550 ast_free(ringing_station); 04551 } 04552 } 04553 AST_LIST_TRAVERSE_SAFE_END 04554 }
| static const char* sla_hold_str | ( | unsigned int | hold_access | ) | [static] |
Definition at line 1179 of file app_meetme.c.
References SLA_HOLD_OPEN, and SLA_HOLD_PRIVATE.
Referenced by sla_show_stations(), and sla_show_trunks().
01180 { 01181 const char *hold = "Unknown"; 01182 01183 switch (hold_access) { 01184 case SLA_HOLD_OPEN: 01185 hold = "Open"; 01186 break; 01187 case SLA_HOLD_PRIVATE: 01188 hold = "Private"; 01189 default: 01190 break; 01191 } 01192 01193 return hold; 01194 }
| static int sla_load_config | ( | int | reload | ) | [static] |
Definition at line 5702 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(), CONFIG_FLAG_FILEUNCHANGED, CONFIG_STATUS_FILEUNCHANGED, LOG_WARNING, sla, sla_build_station(), sla_build_trunk(), SLA_CONFIG_FILE, sla_thread(), and type.
Referenced by load_config(), and sla_check_reload().
05703 { 05704 struct ast_config *cfg; 05705 struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; 05706 const char *cat = NULL; 05707 int res = 0; 05708 const char *val; 05709 05710 if (!reload) { 05711 ast_mutex_init(&sla.lock); 05712 ast_cond_init(&sla.cond, NULL); 05713 } 05714 05715 if (!(cfg = ast_config_load(SLA_CONFIG_FILE, config_flags))) 05716 return 0; /* Treat no config as normal */ 05717 else if (cfg == CONFIG_STATUS_FILEUNCHANGED) 05718 return 0; 05719 05720 if ((val = ast_variable_retrieve(cfg, "general", "attemptcallerid"))) 05721 sla.attempt_callerid = ast_true(val); 05722 05723 while ((cat = ast_category_browse(cfg, cat)) && !res) { 05724 const char *type; 05725 if (!strcasecmp(cat, "general")) 05726 continue; 05727 if (!(type = ast_variable_retrieve(cfg, cat, "type"))) { 05728 ast_log(LOG_WARNING, "Invalid entry in %s defined with no type!\n", 05729 SLA_CONFIG_FILE); 05730 continue; 05731 } 05732 if (!strcasecmp(type, "trunk")) 05733 res = sla_build_trunk(cfg, cat); 05734 else if (!strcasecmp(type, "station")) 05735 res = sla_build_station(cfg, cat); 05736 else { 05737 ast_log(LOG_WARNING, "Entry in %s defined with invalid type '%s'!\n", 05738 SLA_CONFIG_FILE, type); 05739 } 05740 } 05741 05742 ast_config_destroy(cfg); 05743 05744 if (!reload && (!AST_LIST_EMPTY(&sla_stations) || !AST_LIST_EMPTY(&sla_stations))) 05745 ast_pthread_create(&sla.thread, NULL, sla_thread, NULL); 05746 05747 return res; 05748 }
| static int sla_process_timers | ( | struct timespec * | ts | ) | [static] |
Calculate the time until the next known event.
Definition at line 4744 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().
04745 { 04746 unsigned int timeout = UINT_MAX; 04747 struct timeval wait; 04748 unsigned int change_made = 0; 04749 04750 /* Check for ring timeouts on ringing trunks */ 04751 if (sla_calc_trunk_timeouts(&timeout)) 04752 change_made = 1; 04753 04754 /* Check for ring timeouts on ringing stations */ 04755 if (sla_calc_station_timeouts(&timeout)) 04756 change_made = 1; 04757 04758 /* Check for station ring delays */ 04759 if (sla_calc_station_delays(&timeout)) 04760 change_made = 1; 04761 04762 /* queue reprocessing of ringing trunks */ 04763 if (change_made) 04764 sla_queue_event_nolock(SLA_EVENT_RINGING_TRUNK); 04765 04766 /* No timeout */ 04767 if (timeout == UINT_MAX) 04768 return 0; 04769 04770 if (ts) { 04771 wait = ast_tvadd(ast_tvnow(), ast_samp2tv(timeout, 1000)); 04772 ts->tv_sec = wait.tv_sec; 04773 ts->tv_nsec = wait.tv_usec * 1000; 04774 } 04775 04776 return 1; 04777 }
| static void sla_queue_event | ( | enum sla_event_type | type | ) | [static] |
Definition at line 1482 of file app_meetme.c.
References sla_queue_event_full().
Referenced by load_config(), queue_ringing_trunk(), sla_dial_state_callback(), sla_handle_dial_state_event(), sla_station_exec(), and sla_trunk_exec().
01483 { 01484 sla_queue_event_full(type, NULL, NULL, 1); 01485 }
| 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 1488 of file app_meetme.c.
References ast_debug, 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, LOG_ERROR, sla_trunk::name, sla_queue_event_full(), strsep(), sla_trunk_ref::trunk, and sla_station::trunks.
Referenced by conf_run().
01490 { 01491 struct sla_station *station; 01492 struct sla_trunk_ref *trunk_ref = NULL; 01493 char *trunk_name; 01494 01495 trunk_name = ast_strdupa(conf->confno); 01496 strsep(&trunk_name, "_"); 01497 if (ast_strlen_zero(trunk_name)) { 01498 ast_log(LOG_ERROR, "Invalid conference name for SLA - '%s'!\n", conf->confno); 01499 return; 01500 } 01501 01502 AST_RWLIST_RDLOCK(&sla_stations); 01503 AST_RWLIST_TRAVERSE(&sla_stations, station, entry) { 01504 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) { 01505 if (trunk_ref->chan == chan && !strcmp(trunk_ref->trunk->name, trunk_name)) 01506 break; 01507 } 01508 if (trunk_ref) 01509 break; 01510 } 01511 AST_RWLIST_UNLOCK(&sla_stations); 01512 01513 if (!trunk_ref) { 01514 ast_debug(1, "Trunk not found for event!\n"); 01515 return; 01516 } 01517 01518 sla_queue_event_full(type, trunk_ref, station, 1); 01519 }
| 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 1450 of file app_meetme.c.
References ast_calloc, ast_cond_signal(), AST_LIST_INSERT_TAIL, ast_mutex_lock(), ast_mutex_unlock(), AST_PTHREADT_NULL, and sla.
Referenced by sla_queue_event(), sla_queue_event_conf(), and sla_queue_event_nolock().
01452 { 01453 struct sla_event *event; 01454 01455 if (sla.thread == AST_PTHREADT_NULL) { 01456 return; 01457 } 01458 01459 if (!(event = ast_calloc(1, sizeof(*event)))) 01460 return; 01461 01462 event->type = type; 01463 event->trunk_ref = trunk_ref; 01464 event->station = station; 01465 01466 if (!lock) { 01467 AST_LIST_INSERT_TAIL(&sla.event_q, event, entry); 01468 return; 01469 } 01470 01471 ast_mutex_lock(&sla.lock); 01472 AST_LIST_INSERT_TAIL(&sla.event_q, event, entry); 01473 ast_cond_signal(&sla.cond); 01474 ast_mutex_unlock(&sla.lock); 01475 }
| static void sla_queue_event_nolock | ( | enum sla_event_type | type | ) | [static] |
Definition at line 1477 of file app_meetme.c.
References sla_queue_event_full().
Referenced by sla_process_timers().
01478 { 01479 sla_queue_event_full(type, NULL, NULL, 0); 01480 }
| static int sla_ring_station | ( | struct sla_ringing_trunk * | ringing_trunk, | |
| struct sla_station * | station | |||
| ) | [static] |
Ring a station.
Definition at line 4361 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_free, 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, sla_failed_station::last_try, sla, sla_create_ringing_station(), sla_dial_state_callback(), sla_failed_station::station, strsep(), and sla_ringing_trunk::trunk.
Referenced by sla_ring_stations().
04362 { 04363 char *tech, *tech_data; 04364 struct ast_dial *dial; 04365 struct sla_ringing_station *ringing_station; 04366 const char *cid_name = NULL, *cid_num = NULL; 04367 enum ast_dial_result res; 04368 04369 if (!(dial = ast_dial_create())) 04370 return -1; 04371 04372 ast_dial_set_state_callback(dial, sla_dial_state_callback); 04373 tech_data = ast_strdupa(station->device); 04374 tech = strsep(&tech_data, "/"); 04375 04376 if (ast_dial_append(dial, tech, tech_data) == -1) { 04377 ast_dial_destroy(dial); 04378 return -1; 04379 } 04380 04381 if (!sla.attempt_callerid && !ast_strlen_zero(ringing_trunk->trunk->chan->cid.cid_name)) { 04382 cid_name = ast_strdupa(ringing_trunk->trunk->chan->cid.cid_name); 04383 ast_free(ringing_trunk->trunk->chan->cid.cid_name); 04384 ringing_trunk->trunk->chan->cid.cid_name = NULL; 04385 } 04386 if (!sla.attempt_callerid && !ast_strlen_zero(ringing_trunk->trunk->chan->cid.cid_num)) { 04387 cid_num = ast_strdupa(ringing_trunk->trunk->chan->cid.cid_num); 04388 ast_free(ringing_trunk->trunk->chan->cid.cid_num); 04389 ringing_trunk->trunk->chan->cid.cid_num = NULL; 04390 } 04391 04392 res = ast_dial_run(dial, ringing_trunk->trunk->chan, 1); 04393 04394 if (cid_name) 04395 ringing_trunk->trunk->chan->cid.cid_name = ast_strdup(cid_name); 04396 if (cid_num) 04397 ringing_trunk->trunk->chan->cid.cid_num = ast_strdup(cid_num); 04398 04399 if (res != AST_DIAL_RESULT_TRYING) { 04400 struct sla_failed_station *failed_station; 04401 ast_dial_destroy(dial); 04402 if (!(failed_station = ast_calloc(1, sizeof(*failed_station)))) 04403 return -1; 04404 failed_station->station = station; 04405 failed_station->last_try = ast_tvnow(); 04406 AST_LIST_INSERT_HEAD(&sla.failed_stations, failed_station, entry); 04407 return -1; 04408 } 04409 if (!(ringing_station = sla_create_ringing_station(station))) { 04410 ast_dial_join(dial); 04411 ast_dial_destroy(dial); 04412 return -1; 04413 } 04414 04415 station->dial = dial; 04416 04417 AST_LIST_INSERT_HEAD(&sla.ringing_stations, ringing_station, entry); 04418 04419 return 0; 04420 }
| static void sla_ring_stations | ( | void | ) | [static] |
Ring stations based on current set of ringing trunks.
Definition at line 4487 of file app_meetme.c.
References AST_LIST_TRAVERSE, 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().
04488 { 04489 struct sla_station_ref *station_ref; 04490 struct sla_ringing_trunk *ringing_trunk; 04491 04492 /* Make sure that every station that uses at least one of the ringing 04493 * trunks, is ringing. */ 04494 AST_LIST_TRAVERSE(&sla.ringing_trunks, ringing_trunk, entry) { 04495 AST_LIST_TRAVERSE(&ringing_trunk->trunk->stations, station_ref, entry) { 04496 int time_left; 04497 04498 /* Is this station already ringing? */ 04499 if (sla_check_ringing_station(station_ref->station)) 04500 continue; 04501 04502 /* Is this station already in a call? */ 04503 if (sla_check_inuse_station(station_ref->station)) 04504 continue; 04505 04506 /* Did we fail to dial this station earlier? If so, has it been 04507 * a minute since we tried? */ 04508 if (sla_check_failed_station(station_ref->station)) 04509 continue; 04510 04511 /* If this station already timed out while this trunk was ringing, 04512 * do not dial it again for this ringing trunk. */ 04513 if (sla_check_timed_out_station(ringing_trunk, station_ref->station)) 04514 continue; 04515 04516 /* Check for a ring delay in progress */ 04517 time_left = sla_check_station_delay(station_ref->station, ringing_trunk); 04518 if (time_left != INT_MAX && time_left > 0) 04519 continue; 04520 04521 /* It is time to make this station begin to ring. Do it! */ 04522 sla_ring_station(ringing_trunk, station_ref->station); 04523 } 04524 } 04525 /* Now, all of the stations that should be ringing, are ringing. */ 04526 }
| static char* sla_show_stations | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 1261 of file app_meetme.c.
References ast_cli(), AST_LIST_TRAVERSE, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, sla_station::autocontext, CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, sla_station::device, ast_cli_args::fd, sla_station::hold_access, sla_trunk::name, sla_station::name, 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, trunkstate2str(), and ast_cli_entry::usage.
01262 { 01263 const struct sla_station *station; 01264 01265 switch (cmd) { 01266 case CLI_INIT: 01267 e->command = "sla show stations"; 01268 e->usage = 01269 "Usage: sla show stations\n" 01270 " This will list all stations defined in sla.conf\n"; 01271 return NULL; 01272 case CLI_GENERATE: 01273 return NULL; 01274 } 01275 01276 ast_cli(a->fd, "\n" 01277 "=============================================================\n" 01278 "=== Configured SLA Stations =================================\n" 01279 "=============================================================\n" 01280 "===\n"); 01281 AST_RWLIST_RDLOCK(&sla_stations); 01282 AST_RWLIST_TRAVERSE(&sla_stations, station, entry) { 01283 struct sla_trunk_ref *trunk_ref; 01284 char ring_timeout[16] = "(none)"; 01285 char ring_delay[16] = "(none)"; 01286 if (station->ring_timeout) { 01287 snprintf(ring_timeout, sizeof(ring_timeout), 01288 "%u", station->ring_timeout); 01289 } 01290 if (station->ring_delay) { 01291 snprintf(ring_delay, sizeof(ring_delay), 01292 "%u", station->ring_delay); 01293 } 01294 ast_cli(a->fd, "=== ---------------------------------------------------------\n" 01295 "=== Station Name: %s\n" 01296 "=== ==> Device: %s\n" 01297 "=== ==> AutoContext: %s\n" 01298 "=== ==> RingTimeout: %s\n" 01299 "=== ==> RingDelay: %s\n" 01300 "=== ==> HoldAccess: %s\n" 01301 "=== ==> Trunks ...\n", 01302 station->name, station->device, 01303 S_OR(station->autocontext, "(none)"), 01304 ring_timeout, ring_delay, 01305 sla_hold_str(station->hold_access)); 01306 AST_RWLIST_RDLOCK(&sla_trunks); 01307 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) { 01308 if (trunk_ref->ring_timeout) { 01309 snprintf(ring_timeout, sizeof(ring_timeout), 01310 "%u", trunk_ref->ring_timeout); 01311 } else 01312 strcpy(ring_timeout, "(none)"); 01313 if (trunk_ref->ring_delay) { 01314 snprintf(ring_delay, sizeof(ring_delay), 01315 "%u", trunk_ref->ring_delay); 01316 } else 01317 strcpy(ring_delay, "(none)"); 01318 ast_cli(a->fd, "=== ==> Trunk Name: %s\n" 01319 "=== ==> State: %s\n" 01320 "=== ==> RingTimeout: %s\n" 01321 "=== ==> RingDelay: %s\n", 01322 trunk_ref->trunk->name, 01323 trunkstate2str(trunk_ref->state), 01324 ring_timeout, ring_delay); 01325 } 01326 AST_RWLIST_UNLOCK(&sla_trunks); 01327 ast_cli(a->fd, "=== ---------------------------------------------------------\n" 01328 "===\n"); 01329 } 01330 AST_RWLIST_UNLOCK(&sla_stations); 01331 ast_cli(a->fd, "============================================================\n" 01332 "\n"); 01333 01334 return CLI_SUCCESS; 01335 }
| static char* sla_show_trunks | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 1196 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, CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, sla_trunk::device, ast_cli_args::fd, sla_trunk::hold_access, sla_station::name, sla_trunk::name, sla_trunk::ring_timeout, S_OR, sla_hold_str(), sla_station_ref::station, sla_trunk::stations, and ast_cli_entry::usage.
01197 { 01198 const struct sla_trunk *trunk; 01199 01200 switch (cmd) { 01201 case CLI_INIT: 01202 e->command = "sla show trunks"; 01203 e->usage = 01204 "Usage: sla show trunks\n" 01205 " This will list all trunks defined in sla.conf\n"; 01206 return NULL; 01207 case CLI_GENERATE: 01208 return NULL; 01209 } 01210 01211 ast_cli(a->fd, "\n" 01212 "=============================================================\n" 01213 "=== Configured SLA Trunks ===================================\n" 01214 "=============================================================\n" 01215 "===\n"); 01216 AST_RWLIST_RDLOCK(&sla_trunks); 01217 AST_RWLIST_TRAVERSE(&sla_trunks, trunk, entry) { 01218 struct sla_station_ref *station_ref; 01219 char ring_timeout[16] = "(none)"; 01220 if (trunk->ring_timeout) 01221 snprintf(ring_timeout, sizeof(ring_timeout), "%u Seconds", trunk->ring_timeout); 01222 ast_cli(a->fd, "=== ---------------------------------------------------------\n" 01223 "=== Trunk Name: %s\n" 01224 "=== ==> Device: %s\n" 01225 "=== ==> AutoContext: %s\n" 01226 "=== ==> RingTimeout: %s\n" 01227 "=== ==> BargeAllowed: %s\n" 01228 "=== ==> HoldAccess: %s\n" 01229 "=== ==> Stations ...\n", 01230 trunk->name, trunk->device, 01231 S_OR(trunk->autocontext, "(none)"), 01232 ring_timeout, 01233 trunk->barge_disabled ? "No" : "Yes", 01234 sla_hold_str(trunk->hold_access)); 01235 AST_RWLIST_RDLOCK(&sla_stations); 01236 AST_LIST_TRAVERSE(&trunk->stations, station_ref, entry) 01237 ast_cli(a->fd, "=== ==> Station name: %s\n", station_ref->station->name); 01238 AST_RWLIST_UNLOCK(&sla_stations); 01239 ast_cli(a->fd, "=== ---------------------------------------------------------\n===\n"); 01240 } 01241 AST_RWLIST_UNLOCK(&sla_trunks); 01242 ast_cli(a->fd, "=============================================================\n\n"); 01243 01244 return CLI_SUCCESS; 01245 }
| static enum ast_device_state sla_state | ( | const char * | data | ) | [static] |
Definition at line 5340 of file app_meetme.c.
References AST_DEVICE_INVALID, AST_LIST_TRAVERSE, ast_log(), AST_RWLIST_RDLOCK, AST_RWLIST_UNLOCK, ast_strdupa, buf, LOG_ERROR, sla_trunk::name, sla_station::name, sla_state_to_devstate(), sla_trunk_ref::state, strsep(), sla_trunk_ref::trunk, and sla_station::trunks.
Referenced by load_module().
05341 { 05342 char *buf, *station_name, *trunk_name; 05343 struct sla_station *station; 05344 struct sla_trunk_ref *trunk_ref; 05345 enum ast_device_state res = AST_DEVICE_INVALID; 05346 05347 trunk_name = buf = ast_strdupa(data); 05348 station_name = strsep(&trunk_name, "_"); 05349 05350 AST_RWLIST_RDLOCK(&sla_stations); 05351 AST_LIST_TRAVERSE(&sla_stations, station, entry) { 05352 if (strcasecmp(station_name, station->name)) 05353 continue; 05354 AST_RWLIST_RDLOCK(&sla_trunks); 05355 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) { 05356 if (!strcasecmp(trunk_name, trunk_ref->trunk->name)) 05357 break; 05358 } 05359 if (!trunk_ref) { 05360 AST_RWLIST_UNLOCK(&sla_trunks); 05361 break; 05362 } 05363 res = sla_state_to_devstate(trunk_ref->state); 05364 AST_RWLIST_UNLOCK(&sla_trunks); 05365 } 05366 AST_RWLIST_UNLOCK(&sla_stations); 05367 05368 if (res == AST_DEVICE_INVALID) { 05369 ast_log(LOG_ERROR, "Could not determine state for trunk %s on station %s!\n", 05370 trunk_name, station_name); 05371 } 05372 05373 return res; 05374 }
| static enum ast_device_state sla_state_to_devstate | ( | enum sla_trunk_state | state | ) | [static] |
Definition at line 4041 of file app_meetme.c.
References AST_DEVICE_INUSE, AST_DEVICE_NOT_INUSE, AST_DEVICE_ONHOLD, AST_DEVICE_RINGING, AST_DEVICE_UNKNOWN, 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_change_trunk_state(), and sla_state().
04042 { 04043 switch (state) { 04044 case SLA_TRUNK_STATE_IDLE: 04045 return AST_DEVICE_NOT_INUSE; 04046 case SLA_TRUNK_STATE_RINGING: 04047 return AST_DEVICE_RINGING; 04048 case SLA_TRUNK_STATE_UP: 04049 return AST_DEVICE_INUSE; 04050 case SLA_TRUNK_STATE_ONHOLD: 04051 case SLA_TRUNK_STATE_ONHOLD_BYME: 04052 return AST_DEVICE_ONHOLD; 04053 } 04054 04055 return AST_DEVICE_UNKNOWN; 04056 }
| static int sla_station_exec | ( | struct ast_channel * | chan, | |
| void * | data | |||
| ) | [static] |
Definition at line 5018 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_debug, AST_DEVICE_INUSE, ast_devstate_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_detached_background, AST_RWLIST_RDLOCK, AST_RWLIST_UNLOCK, ast_set_flag, ast_strdupa, ast_strlen_zero(), build_conf(), sla_trunk_ref::chan, sla_trunk::chan, conf_run(), CONFFLAG_MARKEDEXIT, CONFFLAG_PASS_DTMF, CONFFLAG_QUIET, CONFFLAG_SLA_STATION, dial_trunk(), dispose_conf(), ast_flags::flags, free, sla_trunk::hold_stations, LOG_NOTICE, LOG_WARNING, MAX_CONFNUM, sla_trunk::name, sla_station::name, sla_trunk::on_hold, pbx_builtin_setvar_helper(), sla_station::ref_count, sla, sla_change_trunk_state(), sla_choose_idle_trunk(), SLA_EVENT_CHECK_RELOAD, 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, strsep(), sla_ringing_trunk::trunk, sla_trunk_ref::trunk, and dial_trunk_args::trunk_ref.
Referenced by load_module().
05019 { 05020 char *station_name, *trunk_name; 05021 struct sla_station *station; 05022 struct sla_trunk_ref *trunk_ref = NULL; 05023 char conf_name[MAX_CONFNUM]; 05024 struct ast_flags conf_flags = { 0 }; 05025 struct ast_conference *conf; 05026 05027 if (ast_strlen_zero(data)) { 05028 ast_log(LOG_WARNING, "Invalid Arguments to SLAStation!\n"); 05029 pbx_builtin_setvar_helper(chan, "SLASTATION_STATUS", "FAILURE"); 05030 return 0; 05031 } 05032 05033 trunk_name = ast_strdupa(data); 05034 station_name = strsep(&trunk_name, "_"); 05035 05036 if (ast_strlen_zero(station_name)) { 05037 ast_log(LOG_WARNING, "Invalid Arguments to SLAStation!\n"); 05038 pbx_builtin_setvar_helper(chan, "SLASTATION_STATUS", "FAILURE"); 05039 return 0; 05040 } 05041 05042 AST_RWLIST_RDLOCK(&sla_stations); 05043 station = sla_find_station(station_name); 05044 if (station) 05045 ast_atomic_fetchadd_int((int *) &station->ref_count, 1); 05046 AST_RWLIST_UNLOCK(&sla_stations); 05047 05048 if (!station) { 05049 ast_log(LOG_WARNING, "Station '%s' not found!\n", station_name); 05050 pbx_builtin_setvar_helper(chan, "SLASTATION_STATUS", "FAILURE"); 05051 sla_queue_event(SLA_EVENT_CHECK_RELOAD); 05052 return 0; 05053 } 05054 05055 AST_RWLIST_RDLOCK(&sla_trunks); 05056 if (!ast_strlen_zero(trunk_name)) { 05057 trunk_ref = sla_find_trunk_ref_byname(station, trunk_name); 05058 } else 05059 trunk_ref = sla_choose_idle_trunk(station); 05060 AST_RWLIST_UNLOCK(&sla_trunks); 05061 05062 if (!trunk_ref) { 05063 if (ast_strlen_zero(trunk_name)) 05064 ast_log(LOG_NOTICE, "No trunks available for call.\n"); 05065 else { 05066 ast_log(LOG_NOTICE, "Can't join existing call on trunk " 05067 "'%s' due to access controls.\n", trunk_name); 05068 } 05069 pbx_builtin_setvar_helper(chan, "SLASTATION_STATUS", "CONGESTION"); 05070 ast_atomic_fetchadd_int((int *) &station->ref_count, -1); 05071 sla_queue_event(SLA_EVENT_CHECK_RELOAD); 05072 return 0; 05073 } 05074 05075 if (trunk_ref->state == SLA_TRUNK_STATE_ONHOLD_BYME) { 05076 if (ast_atomic_dec_and_test((int *) &trunk_ref->trunk->hold_stations) == 1) 05077 sla_change_trunk_state(trunk_ref->trunk, SLA_TRUNK_STATE_UP, ALL_TRUNK_REFS, NULL); 05078 else { 05079 trunk_ref->state = SLA_TRUNK_STATE_UP; 05080 ast_devstate_changed(AST_DEVICE_INUSE, 05081 "SLA:%s_%s", station->name, trunk_ref->trunk->name); 05082 } 05083 } else if (trunk_ref->state == SLA_TRUNK_STATE_RINGING) { 05084 struct sla_ringing_trunk *ringing_trunk; 05085 05086 ast_mutex_lock(&sla.lock); 05087 AST_LIST_TRAVERSE_SAFE_BEGIN(&sla.ringing_trunks, ringing_trunk, entry) { 05088 if (ringing_trunk->trunk == trunk_ref->trunk) { 05089 AST_LIST_REMOVE_CURRENT(entry); 05090 break; 05091 } 05092 } 05093 AST_LIST_TRAVERSE_SAFE_END 05094 ast_mutex_unlock(&sla.lock); 05095 05096 if (ringing_trunk) { 05097 answer_trunk_chan(ringing_trunk->trunk->chan); 05098 sla_change_trunk_state(ringing_trunk->trunk, SLA_TRUNK_STATE_UP, ALL_TRUNK_REFS, NULL); 05099 05100 free(ringing_trunk); 05101 05102 /* Queue up reprocessing ringing trunks, and then ringing stations again */ 05103 sla_queue_event(SLA_EVENT_RINGING_TRUNK); 05104 sla_queue_event(SLA_EVENT_DIAL_STATE); 05105 } 05106 } 05107 05108 trunk_ref->chan = chan; 05109 05110 if (!trunk_ref->trunk->chan) { 05111 ast_mutex_t cond_lock; 05112 ast_cond_t cond; 05113 pthread_t dont_care; 05114 struct dial_trunk_args args = { 05115 .trunk_ref = trunk_ref, 05116 .station = station, 05117 .cond_lock = &cond_lock, 05118 .cond = &cond, 05119 }; 05120 sla_change_trunk_state(trunk_ref->trunk, SLA_TRUNK_STATE_UP, ALL_TRUNK_REFS, NULL); 05121 /* Create a thread to dial the trunk and dump it into the conference. 05122 * However, we want to wait until the trunk has been dialed and the 05123 * conference is created before continuing on here. */ 05124 ast_autoservice_start(chan); 05125 ast_mutex_init(&cond_lock); 05126 ast_cond_init(&cond, NULL); 05127 ast_mutex_lock(&cond_lock); 05128 ast_pthread_create_detached_background(&dont_care, NULL, dial_trunk, &args); 05129 ast_cond_wait(&cond, &cond_lock); 05130 ast_mutex_unlock(&cond_lock); 05131 ast_mutex_destroy(&cond_lock); 05132 ast_cond_destroy(&cond); 05133 ast_autoservice_stop(chan); 05134 if (!trunk_ref->trunk->chan) { 05135 ast_debug(1, "Trunk didn't get created. chan: %lx\n", (long) trunk_ref->trunk->chan); 05136 pbx_builtin_setvar_helper(chan, "SLASTATION_STATUS", "CONGESTION"); 05137 sla_change_trunk_state(trunk_ref->trunk, SLA_TRUNK_STATE_IDLE, ALL_TRUNK_REFS, NULL); 05138 trunk_ref->chan = NULL; 05139 ast_atomic_fetchadd_int((int *) &station->ref_count, -1); 05140 sla_queue_event(SLA_EVENT_CHECK_RELOAD); 05141 return 0; 05142 } 05143 } 05144 05145 if (ast_atomic_fetchadd_int((int *) &trunk_ref->trunk->active_stations, 1) == 0 && 05146 trunk_ref->trunk->on_hold) { 05147 trunk_ref->trunk->on_hold = 0; 05148 ast_indicate(trunk_ref->trunk->chan, AST_CONTROL_UNHOLD); 05149 sla_change_trunk_state(trunk_ref->trunk, SLA_TRUNK_STATE_UP, ALL_TRUNK_REFS, NULL); 05150 } 05151 05152 snprintf(conf_name, sizeof(conf_name), "SLA_%s", trunk_ref->trunk->name); 05153 ast_set_flag(&conf_flags, 05154 CONFFLAG_QUIET | CONFFLAG_MARKEDEXIT | CONFFLAG_PASS_DTMF | CONFFLAG_SLA_STATION); 05155 ast_answer(chan); 05156 conf = build_conf(conf_name, "", "", 0, 0, 1, chan); 05157 if (conf) { 05158 conf_run(chan, conf, conf_flags.flags, NULL); 05159 dispose_conf(conf); 05160 conf = NULL; 05161 } 05162 trunk_ref->chan = NULL; 05163 if (ast_atomic_dec_and_test((int *) &trunk_ref->trunk->active_stations) && 05164 trunk_ref->state != SLA_TRUNK_STATE_ONHOLD_BYME) { 05165 strncat(conf_name, ",K", sizeof(conf_name) - strlen(conf_name) - 1); 05166 admin_exec(NULL, conf_name); 05167 trunk_ref->trunk->hold_stations = 0; 05168 sla_change_trunk_state(trunk_ref->trunk, SLA_TRUNK_STATE_IDLE, ALL_TRUNK_REFS, NULL); 05169 } 05170 05171 pbx_builtin_setvar_helper(chan, "SLASTATION_STATUS", "SUCCESS"); 05172 05173 ast_atomic_fetchadd_int((int *) &station->ref_count, -1); 05174 sla_queue_event(SLA_EVENT_CHECK_RELOAD); 05175 05176 return 0; 05177 }
| static void sla_stop_ringing_station | ( | struct sla_ringing_station * | ringing_station, | |
| enum sla_station_hangup | hangup | |||
| ) | [static] |
Definition at line 4151 of file app_meetme.c.
References ast_dial_destroy(), ast_dial_join(), ast_free, AST_LIST_INSERT_TAIL, AST_LIST_TRAVERSE, sla_station::dial, 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().
04153 { 04154 struct sla_ringing_trunk *ringing_trunk; 04155 struct sla_trunk_ref *trunk_ref; 04156 struct sla_station_ref *station_ref; 04157 04158 ast_dial_join(ringing_station->station->dial); 04159 ast_dial_destroy(ringing_station->station->dial); 04160 ringing_station->station->dial = NULL; 04161 04162 if (hangup == SLA_STATION_HANGUP_NORMAL) 04163 goto done; 04164 04165 /* If the station is being hung up because of a timeout, then add it to the 04166 * list of timed out stations on each of the ringing trunks. This is so 04167 * that when doing further processing to figure out which stations should be 04168 * ringing, which trunk to answer, determining timeouts, etc., we know which 04169 * ringing trunks we should ignore. */ 04170 AST_LIST_TRAVERSE(&sla.ringing_trunks, ringing_trunk, entry) { 04171 AST_LIST_TRAVERSE(&ringing_station->station->trunks, trunk_ref, entry) { 04172 if (ringing_trunk->trunk == trunk_ref->trunk) 04173 break; 04174 } 04175 if (!trunk_ref) 04176 continue; 04177 if (!(station_ref = sla_create_station_ref(ringing_station->station))) 04178 continue; 04179 AST_LIST_INSERT_TAIL(&ringing_trunk->timed_out_stations, station_ref, entry); 04180 } 04181 04182 done: 04183 ast_free(ringing_station); 04184 }
| static void sla_stop_ringing_trunk | ( | struct sla_ringing_trunk * | ringing_trunk | ) | [static] |
Definition at line 4136 of file app_meetme.c.
References admin_exec(), ALL_TRUNK_REFS, ast_free, AST_LIST_REMOVE_HEAD, buf, 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().
04137 { 04138 char buf[80]; 04139 struct sla_station_ref *station_ref; 04140 04141 snprintf(buf, sizeof(buf), "SLA_%s,K", ringing_trunk->trunk->name); 04142 admin_exec(NULL, buf); 04143 sla_change_trunk_state(ringing_trunk->trunk, SLA_TRUNK_STATE_IDLE, ALL_TRUNK_REFS, NULL); 04144 04145 while ((station_ref = AST_LIST_REMOVE_HEAD(&ringing_trunk->timed_out_stations, entry))) 04146 ast_free(station_ref); 04147 04148 ast_free(ringing_trunk); 04149 }
| static void* sla_thread | ( | void * | data | ) | [static] |
Definition at line 4824 of file app_meetme.c.
References ast_cond_timedwait(), ast_cond_wait(), ast_free, AST_LIST_EMPTY, AST_LIST_REMOVE_HEAD, ast_mutex_lock(), ast_mutex_unlock(), sla, sla_check_reload(), SLA_EVENT_CHECK_RELOAD, SLA_EVENT_DIAL_STATE, SLA_EVENT_HOLD, SLA_EVENT_RELOAD, 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().
04825 { 04826 struct sla_failed_station *failed_station; 04827 struct sla_ringing_station *ringing_station; 04828 04829 ast_mutex_lock(&sla.lock); 04830 04831 while (!sla.stop) { 04832 struct sla_event *event; 04833 struct timespec ts = { 0, }; 04834 unsigned int have_timeout = 0; 04835 04836 if (AST_LIST_EMPTY(&sla.event_q)) { 04837 if ((have_timeout = sla_process_timers(&ts))) 04838 ast_cond_timedwait(&sla.cond, &sla.lock, &ts); 04839 else 04840 ast_cond_wait(&sla.cond, &sla.lock); 04841 if (sla.stop) 04842 break; 04843 } 04844 04845 if (have_timeout) 04846 sla_process_timers(NULL); 04847 04848 while ((event = AST_LIST_REMOVE_HEAD(&sla.event_q, entry))) { 04849 ast_mutex_unlock(&sla.lock); 04850 switch (event->type) { 04851 case SLA_EVENT_HOLD: 04852 sla_handle_hold_event(event); 04853 break; 04854 case SLA_EVENT_DIAL_STATE: 04855 sla_handle_dial_state_event(); 04856 break; 04857 case SLA_EVENT_RINGING_TRUNK: 04858 sla_handle_ringing_trunk_event(); 04859 break; 04860 case SLA_EVENT_RELOAD: 04861 sla.reload = 1; 04862 case SLA_EVENT_CHECK_RELOAD: 04863 break; 04864 } 04865 ast_free(event); 04866 ast_mutex_lock(&sla.lock); 04867 } 04868 04869 if (sla.reload) 04870 sla_check_reload(); 04871 } 04872 04873 ast_mutex_unlock(&sla.lock); 04874 04875 while ((ringing_station = AST_LIST_REMOVE_HEAD(&sla.ringing_stations, entry))) 04876 ast_free(ringing_station); 04877 04878 while ((failed_station = AST_LIST_REMOVE_HEAD(&sla.failed_stations, entry))) 04879 ast_free(failed_station); 04880 04881 return NULL; 04882 }
| static int sla_trunk_exec | ( | struct ast_channel * | chan, | |
| void * | data | |||
| ) | [static] |
Definition at line 5225 of file app_meetme.c.
References ALL_TRUNK_REFS, AST_APP_ARG, ast_app_parse_options(), ast_atomic_fetchadd_int(), AST_CONTROL_RINGING, AST_DECLARE_APP_ARGS, ast_free, 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, AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), ast_test_flag, build_conf(), sla_trunk::chan, conf_run(), CONFFLAG_MARKEDEXIT, CONFFLAG_MARKEDUSER, CONFFLAG_MOH, CONFFLAG_NO_AUDIO_UNTIL_UP, CONFFLAG_PASS_DTMF, CONFFLAG_QUIET, dispose_conf(), ast_flags::flags, LOG_ERROR, MAX_CONFNUM, sla_trunk::on_hold, OPT_ARG_ARRAY_SIZE, OPT_ARG_MOH_CLASS, parse(), pbx_builtin_getvar_helper(), pbx_builtin_setvar_helper(), queue_ringing_trunk(), sla_trunk::ref_count, sla, sla_change_trunk_state(), SLA_EVENT_CHECK_RELOAD, SLA_EVENT_RINGING_TRUNK, sla_find_trunk(), sla_queue_event(), SLA_TRUNK_OPT_ARG_ARRAY_SIZE, SLA_TRUNK_OPT_ARG_MOH_CLASS, SLA_TRUNK_OPT_MOH, sla_trunk_opts, SLA_TRUNK_STATE_IDLE, and sla_ringing_trunk::trunk.
Referenced by load_module().
05226 { 05227 char conf_name[MAX_CONFNUM]; 05228 struct ast_conference *conf; 05229 struct ast_flags conf_flags = { 0 }; 05230 struct sla_trunk *trunk; 05231 struct sla_ringing_trunk *ringing_trunk; 05232 AST_DECLARE_APP_ARGS(args, 05233 AST_APP_ARG(trunk_name); 05234 AST_APP_ARG(options); 05235 ); 05236 char *opts[SLA_TRUNK_OPT_ARG_ARRAY_SIZE] = { NULL, }; 05237 char *conf_opt_args[OPT_ARG_ARRAY_SIZE] = { NULL, }; 05238 struct ast_flags opt_flags = { 0 }; 05239 char *parse; 05240 05241 if (ast_strlen_zero(data)) { 05242 ast_log(LOG_ERROR, "The SLATrunk application requires an argument, the trunk name\n"); 05243 return -1; 05244 } 05245 05246 parse = ast_strdupa(data); 05247 AST_STANDARD_APP_ARGS(args, parse); 05248 if (args.argc == 2) { 05249 if (ast_app_parse_options(sla_trunk_opts, &opt_flags, opts, args.options)) { 05250 ast_log(LOG_ERROR, "Error parsing options for SLATrunk\n"); 05251 return -1; 05252 } 05253 } 05254 05255 AST_RWLIST_RDLOCK(&sla_trunks); 05256 trunk = sla_find_trunk(args.trunk_name); 05257 if (trunk) 05258 ast_atomic_fetchadd_int((int *) &trunk->ref_count, 1); 05259 AST_RWLIST_UNLOCK(&sla_trunks); 05260 05261 if (!trunk) { 05262 ast_log(LOG_ERROR, "SLA Trunk '%s' not found!\n", args.trunk_name); 05263 pbx_builtin_setvar_helper(chan, "SLATRUNK_STATUS", "FAILURE"); 05264 ast_atomic_fetchadd_int((int *) &trunk->ref_count, -1); 05265 sla_queue_event(SLA_EVENT_CHECK_RELOAD); 05266 return 0; 05267 } 05268 05269 if (trunk->chan) { 05270 ast_log(LOG_ERROR, "Call came in on %s, but the trunk is already in use!\n", 05271 args.trunk_name); 05272 pbx_builtin_setvar_helper(chan, "SLATRUNK_STATUS", "FAILURE"); 05273 ast_atomic_fetchadd_int((int *) &trunk->ref_count, -1); 05274 sla_queue_event(SLA_EVENT_CHECK_RELOAD); 05275 return 0; 05276 } 05277 05278 trunk->chan = chan; 05279 05280 if (!(ringing_trunk = queue_ringing_trunk(trunk))) { 05281 pbx_builtin_setvar_helper(chan, "SLATRUNK_STATUS", "FAILURE"); 05282 ast_atomic_fetchadd_int((int *) &trunk->ref_count, -1); 05283 sla_queue_event(SLA_EVENT_CHECK_RELOAD); 05284 return 0; 05285 } 05286 05287 snprintf(conf_name, sizeof(conf_name), "SLA_%s", args.trunk_name); 05288 conf = build_conf(conf_name, "", "", 1, 1, 1, chan); 05289 if (!conf) { 05290 pbx_builtin_setvar_helper(chan, "SLATRUNK_STATUS", "FAILURE"); 05291 ast_atomic_fetchadd_int((int *) &trunk->ref_count, -1); 05292 sla_queue_event(SLA_EVENT_CHECK_RELOAD); 05293 return 0; 05294 } 05295 ast_set_flag(&conf_flags, 05296 CONFFLAG_QUIET | CONFFLAG_MARKEDEXIT | CONFFLAG_MARKEDUSER | CONFFLAG_PASS_DTMF | CONFFLAG_NO_AUDIO_UNTIL_UP); 05297 05298 if (ast_test_flag(&opt_flags, SLA_TRUNK_OPT_MOH)) { 05299 ast_indicate(chan, -1); 05300 ast_set_flag(&conf_flags, CONFFLAG_MOH); 05301 conf_opt_args[OPT_ARG_MOH_CLASS] = opts[SLA_TRUNK_OPT_ARG_MOH_CLASS]; 05302 } else 05303 ast_indicate(chan, AST_CONTROL_RINGING); 05304 05305 conf_run(chan, conf, conf_flags.flags, opts); 05306 dispose_conf(conf); 05307 conf = NULL; 05308 trunk->chan = NULL; 05309 trunk->on_hold = 0; 05310 05311 sla_change_trunk_state(trunk, SLA_TRUNK_STATE_IDLE, ALL_TRUNK_REFS, NULL); 05312 05313 if (!pbx_builtin_getvar_helper(chan, "SLATRUNK_STATUS")) 05314 pbx_builtin_setvar_helper(chan, "SLATRUNK_STATUS", "SUCCESS"); 05315 05316 /* Remove the entry from the list of ringing trunks if it is still there. */ 05317 ast_mutex_lock(&sla.lock); 05318 AST_LIST_TRAVERSE_SAFE_BEGIN(&sla.ringing_trunks, ringing_trunk, entry) { 05319 if (ringing_trunk->trunk == trunk) { 05320 AST_LIST_REMOVE_CURRENT(entry); 05321 break; 05322 } 05323 } 05324 AST_LIST_TRAVERSE_SAFE_END; 05325 ast_mutex_unlock(&sla.lock); 05326 if (ringing_trunk) { 05327 ast_free(ringing_trunk); 05328 pbx_builtin_setvar_helper(chan, "SLATRUNK_STATUS", "UNANSWERED"); 05329 /* Queue reprocessing of ringing trunks to make stations stop ringing 05330 * that shouldn't be ringing after this trunk stopped. */ 05331 sla_queue_event(SLA_EVENT_RINGING_TRUNK); 05332 } 05333 05334 ast_atomic_fetchadd_int((int *) &trunk->ref_count, -1); 05335 sla_queue_event(SLA_EVENT_CHECK_RELOAD); 05336 05337 return 0; 05338 }
| static const char* trunkstate2str | ( | enum sla_trunk_state | state | ) | [static] |
Definition at line 1247 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().
01248 { 01249 #define S(e) case e: return # e; 01250 switch (state) { 01251 S(SLA_TRUNK_STATE_IDLE) 01252 S(SLA_TRUNK_STATE_RINGING) 01253 S(SLA_TRUNK_STATE_UP) 01254 S(SLA_TRUNK_STATE_ONHOLD) 01255 S(SLA_TRUNK_STATE_ONHOLD_BYME) 01256 } 01257 return "Uknown State"; 01258 #undef S 01259 }
| static void tweak_listen_volume | ( | struct ast_conf_user * | user, | |
| enum volume_action | action | |||
| ) | [static] |
Definition at line 760 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().
00761 { 00762 tweak_volume(&user->listen, action); 00763 /* attempt to make the adjustment in the channel driver; 00764 if successful, don't adjust in the frame reading routine 00765 */ 00766 if (!set_listen_volume(user, user->listen.desired)) 00767 user->listen.actual = 0; 00768 else 00769 user->listen.actual = user->listen.desired; 00770 }
| static void tweak_talk_volume | ( | struct ast_conf_user * | user, | |
| enum volume_action | action | |||
| ) | [static] |
Definition at line 748 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().
00749 { 00750 tweak_volume(&user->talk, action); 00751 /* attempt to make the adjustment in the channel driver; 00752 if successful, don't adjust in the frame reading routine 00753 */ 00754 if (!set_talk_volume(user, user->talk.desired)) 00755 user->talk.actual = 0; 00756 else 00757 user->talk.actual = user->talk.desired; 00758 }
| static void tweak_volume | ( | struct volume * | vol, | |
| enum volume_action | action | |||
| ) | [static] |
Definition at line 713 of file app_meetme.c.
References volume::desired, VOL_DOWN, and VOL_UP.
Referenced by tweak_listen_volume(), and tweak_talk_volume().
00714 { 00715 switch (action) { 00716 case VOL_UP: 00717 switch (vol->desired) { 00718 case 5: 00719 break; 00720 case 0: 00721 vol->desired = 2; 00722 break; 00723 case -2: 00724 vol->desired = 0; 00725 break; 00726 default: 00727 vol->desired++; 00728 break; 00729 } 00730 break; 00731 case VOL_DOWN: 00732 switch (vol->desired) { 00733 case -5: 00734 break; 00735 case 2: 00736 vol->desired = 0; 00737 break; 00738 case 0: 00739 vol->desired = -2; 00740 break; 00741 default: 00742 vol->desired--; 00743 break; 00744 } 00745 } 00746 }
| static int unload_module | ( | void | ) | [static] |
Definition at line 5846 of file app_meetme.c.
References ARRAY_LEN, ast_cli_unregister_multiple(), ast_custom_function_unregister(), ast_devstate_prov_del(), ast_manager_unregister(), ast_unload_realtime(), ast_unregister_application(), and sla_destroy().
05847 { 05848 int res = 0; 05849 05850 ast_cli_unregister_multiple(cli_meetme, ARRAY_LEN(cli_meetme)); 05851 res = ast_manager_unregister("MeetmeMute"); 05852 res |= ast_manager_unregister("MeetmeUnmute"); 05853 res |= ast_manager_unregister("MeetmeList"); 05854 res |= ast_unregister_application(app4); 05855 res |= ast_unregister_application(app3); 05856 res |= ast_unregister_application(app2); 05857 res |= ast_unregister_application(app); 05858 res |= ast_unregister_application(slastation_app); 05859 res |= ast_unregister_application(slatrunk_app); 05860 05861 ast_devstate_prov_del("Meetme"); 05862 ast_devstate_prov_del("SLA"); 05863 05864 sla_destroy(); 05865 05866 res |= ast_custom_function_unregister(&meetme_info_acf); 05867 ast_unload_realtime("meetme"); 05868 05869 return res; 05870 }
struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .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 = "a9c98e5d177805051735cb5b0b16b0a0" , .load = load_module, .unload = unload_module, .reload = reload, } [static] |
Definition at line 5913 of file app_meetme.c.
const char* app = "MeetMe" [static] |
Definition at line 209 of file app_meetme.c.
const char* app2 = "MeetMeCount" [static] |
Definition at line 210 of file app_meetme.c.
const char* app3 = "MeetMeAdmin" [static] |
Definition at line 211 of file app_meetme.c.
const char* app4 = "MeetMeChannelAdmin" [static] |
Definition at line 212 of file app_meetme.c.
struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 5913 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 617 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 626 of file app_meetme.c.
struct ast_cli_entry cli_meetme[] [static] |
{
AST_CLI_DEFINE(meetme_cmd, "Execute a command on a conference or conferee"),
AST_CLI_DEFINE(sla_show_trunks, "Show SLA Trunks"),
AST_CLI_DEFINE(sla_show_stations, "Show SLA Stations"),
}
Definition at line 1337 of file app_meetme.c.
Definition at line 608 of file app_meetme.c.
unsigned int conf_map[1024] = {0, } [static] |
Definition at line 419 of file app_meetme.c.
Referenced by build_conf(), conf_exec(), and dispose_conf().
const char* descrip [static] |
Definition at line 232 of file app_meetme.c.
const char* descrip2 [static] |
Definition at line 295 of file app_meetme.c.
const char* descrip3 [static] |
Definition at line 303 of file app_meetme.c.
const char* descrip4 [static] |
Definition at line 326 of file app_meetme.c.
int earlyalert [static] |
Definition at line 226 of file app_meetme.c.
int endalert [static] |
Definition at line 227 of file app_meetme.c.
| struct { ... } event_q |
| struct { ... } failed_stations |
Definition at line 610 of file app_meetme.c.
Referenced by ast_print_group(), context_merge(), h261_encap(), h263_encap(), h263p_encap(), h264_encap(), log_jack_status(), misdn_lib_init(), mpeg4_encap(), and schedule().
int fuzzystart [static] |
Definition at line 225 of file app_meetme.c.
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 634 of file app_meetme.c.
Definition at line 610 of file app_meetme.c.
Referenced by __ao2_callback(), __verboser(), aji_handle_presence(), apply_outgoing(), ast_config_engine_deregister(), ast_db_freetree(), ast_db_gettree(), config_odbc(), config_pgsql(), do_monitor(), gtalk_free_candidates(), jingle_free_candidates(), load_password(), node_lookup(), scan_thread(), schedule(), and try_firmware().
Definition at line 609 of file app_meetme.c.
char mandescr_meetmelist[] [static] |
Definition at line 3712 of file app_meetme.c.
struct ast_custom_function meetme_info_acf [static] |
Definition at line 5817 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 }, [ 'C' ] = { .flag = CONFFLAG_KICK_CONTINUE }, [ 'D' ] = { .flag = CONFFLAG_DYNAMICPIN }, [ 'd' ] = { .flag = CONFFLAG_DYNAMIC }, [ 'E' ] = { .flag = CONFFLAG_EMPTYNOPIN }, [ 'e' ] = { .flag = CONFFLAG_EMPTY }, [ 'F' ] = { .flag = CONFFLAG_PASS_DTMF }, [ 'i' ] = { .flag = CONFFLAG_INTROUSER }, [ 'I' ] = { .flag = CONFFLAG_INTROUSERNOREVIEW }, [ 'M' ] = { .flag = CONFFLAG_MOH , .arg_index = OPT_ARG_MOH_CLASS + 1 }, [ 'm' ] = { .flag = CONFFLAG_STARTMUTED }, [ 'o' ] = { .flag = CONFFLAG_OPTIMIZETALKER }, [ 'P' ] = { .flag = CONFFLAG_ALWAYSPROMPT }, [ 'p' ] = { .flag = CONFFLAG_KEYEXIT , .arg_index = OPT_ARG_EXITKEYS + 1 }, [ '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 }, [ 'S' ] = { .flag = CONFFLAG_DURATION_STOP , .arg_index = OPT_ARG_DURATION_STOP + 1 }, [ 'L' ] = { .flag = CONFFLAG_DURATION_LIMIT , .arg_index = OPT_ARG_DURATION_LIMIT + 1 }, } [static] |
Definition at line 207 of file app_meetme.c.
Referenced by conf_exec().
| static int reload |
A reload has been requested
reload: Part of Asterisk module interface ---
Definition at line 619 of file app_meetme.c.
Referenced by handle_cli_moh_reload(), handle_minivm_reload(), reload(), rpt_do_reload(), and show_console().
| struct { ... } ringing_stations |
| struct { ... } ringing_trunks |
int rt_log_members [static] |
Definition at line 230 of file app_meetme.c.
int rt_schedule [static] |
Definition at line 224 of file app_meetme.c.
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_reload(), 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 549 of file app_meetme.c.
Referenced by destroy_station(), destroy_trunk(), sla_build_station(), sla_build_trunk(), and sla_destroy().
struct ast_app_option sla_trunk_opts[128] = { [ 'M' ] = { .flag = SLA_TRUNK_OPT_MOH , .arg_index = SLA_TRUNK_OPT_ARG_MOH_CLASS + 1 }, } [static] |
Definition at line 5223 of file app_meetme.c.
Referenced by sla_trunk_exec().
const char* slastation_app = "SLAStation" [static] |
Definition at line 213 of file app_meetme.c.
const char* slastation_desc [static] |
Definition at line 334 of file app_meetme.c.
const char* slastation_synopsis = "Shared Line Appearance Station" [static] |
Definition at line 220 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 347 of file app_meetme.c.
const char* slatrunk_synopsis = "Shared Line Appearance Trunk" [static] |
Definition at line 221 of file app_meetme.c.
| unsigned int stop |
Definition at line 614 of file app_meetme.c.
Referenced by controlplayback_exec(), 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.
const char* synopsis4 = "MeetMe conference Administration (channel specific)" [static] |
Definition at line 219 of file app_meetme.c.
| pthread_t thread |
The SLA thread ID
Definition at line 607 of file app_meetme.c.
1.6.1