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 | MAX_SETTINGS (MAX_CONFNUM + MAX_PIN + MAX_PIN + 3) |
| #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 | OPTIONS_LEN 100 |
| #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, 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 char * | meetme_show_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 int | rt_extend_conf (char *confno) |
| static void * | run_station (void *data) |
| static void | send_talking_event (struct ast_channel *chan, struct ast_conference *conf, struct ast_conf_user *user, int talking) |
| 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 | set_user_talking (struct ast_channel *chan, struct ast_conference *conf, struct ast_conf_user *user, int talking, int monitor) |
| 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 = "0901e4e500243c855563a2d78b0c03e4" , .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 int | earlyalert |
| static int | endalert |
| static int | extendby |
| 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 * | slatrunk_app = "SLATrunk" |
Meet me conference bridge and Shared Line Appearances.
Definition in file app_meetme.c.
| #define AST_FRAME_BITS 32 |
Definition at line 445 of file app_meetme.c.
Referenced by conf_free(), conf_run(), and recordthread().
| #define CONF_SIZE 320 |
Definition at line 464 of file app_meetme.c.
| #define CONFIG_FILE_NAME "meetme.conf" |
Definition at line 425 of file app_meetme.c.
Referenced by _dsp_init(), conf_exec(), find_conf(), and load_config_meetme().
| #define DATE_FORMAT "%Y-%m-%d %H:%M:%S" |
String format for scheduled conferences
Definition at line 432 of file app_meetme.c.
Referenced by append_date(), build_radius_record(), conf_run(), execute_cb(), find_conf_realtime(), format_date(), get_date(), manager_log(), pgsql_log(), and rt_extend_conf().
| #define DEFAULT_AUDIO_BUFFERS 32 |
each buffer is 20ms, so this is 640ms total
Definition at line 429 of file app_meetme.c.
Referenced by load_config_meetme().
| #define MAX_CONFNUM 80 |
Definition at line 585 of file app_meetme.c.
Referenced by conf_exec(), dial_trunk(), meetme_cmd(), meetme_show_cmd(), sla_station_exec(), and sla_trunk_exec().
| #define MAX_PIN 80 |
Definition at line 586 of file app_meetme.c.
Referenced by conf_exec().
| #define MAX_SETTINGS (MAX_CONFNUM + MAX_PIN + MAX_PIN + 3) |
Definition at line 590 of file app_meetme.c.
Referenced by conf_exec(), and find_conf().
| #define MC_DATA_FORMAT "%-12.12s %4.4d %4.4s %02d:%02d:%02d %-8s %-6s\n" |
Referenced by meetme_show_cmd().
| #define MC_HEADER_FORMAT "%-14s %-14s %-10s %-8s %-8s %-6s\n" |
Referenced by meetme_show_cmd().
| #define MEETME_DELAYDETECTENDTALK 1000 |
Definition at line 443 of file app_meetme.c.
Referenced by conf_run().
| #define MEETME_DELAYDETECTTALK 300 |
Definition at line 442 of file app_meetme.c.
Referenced by conf_run().
| #define OPTIONS_LEN 100 |
Definition at line 587 of file app_meetme.c.
Referenced by find_conf_realtime().
| #define S | ( | e | ) | case e: return # e; |
Referenced by sms_readfile(), and trunkstate2str().
| #define SLA_CONFIG_FILE "sla.conf" |
Definition at line 426 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 434 of file app_meetme.c.
00434 { 00435 ADMINFLAG_MUTED = (1 << 1), /*!< User is muted */ 00436 ADMINFLAG_SELFMUTED = (1 << 2), /*!< User muted self */ 00437 ADMINFLAG_KICKME = (1 << 3), /*!< User has been kicked */ 00438 /*! User has requested to speak */ 00439 ADMINFLAG_T_REQUEST = (1 << 4), 00440 };
| anonymous enum |
Definition at line 466 of file app_meetme.c.
00466 { 00467 /*! user has admin access on the conference */ 00468 CONFFLAG_ADMIN = (1 << 0), 00469 /*! If set the user can only receive audio from the conference */ 00470 CONFFLAG_MONITOR = (1 << 1), 00471 /*! If set asterisk will exit conference when key defined in p() option is pressed */ 00472 CONFFLAG_KEYEXIT = (1 << 2), 00473 /*! If set asterisk will provide a menu to the user when '*' is pressed */ 00474 CONFFLAG_STARMENU = (1 << 3), 00475 /*! If set the use can only send audio to the conference */ 00476 CONFFLAG_TALKER = (1 << 4), 00477 /*! If set there will be no enter or leave sounds */ 00478 CONFFLAG_QUIET = (1 << 5), 00479 /*! If set, when user joins the conference, they will be told the number 00480 * of users that are already in */ 00481 CONFFLAG_ANNOUNCEUSERCOUNT = (1 << 6), 00482 /*! Set to run AGI Script in Background */ 00483 CONFFLAG_AGI = (1 << 7), 00484 /*! Set to have music on hold when user is alone in conference */ 00485 CONFFLAG_MOH = (1 << 8), 00486 /*! If set the MeetMe will return if all marked with this flag left */ 00487 CONFFLAG_MARKEDEXIT = (1 << 9), 00488 /*! If set, the MeetMe will wait until a marked user enters */ 00489 CONFFLAG_WAITMARKED = (1 << 10), 00490 /*! If set, the MeetMe will exit to the specified context */ 00491 CONFFLAG_EXIT_CONTEXT = (1 << 11), 00492 /*! If set, the user will be marked */ 00493 CONFFLAG_MARKEDUSER = (1 << 12), 00494 /*! If set, user will be ask record name on entry of conference */ 00495 CONFFLAG_INTROUSER = (1 << 13), 00496 /*! If set, the MeetMe will be recorded */ 00497 CONFFLAG_RECORDCONF = (1<< 14), 00498 /*! If set, the user will be monitored if the user is talking or not */ 00499 CONFFLAG_MONITORTALKER = (1 << 15), 00500 CONFFLAG_DYNAMIC = (1 << 16), 00501 CONFFLAG_DYNAMICPIN = (1 << 17), 00502 CONFFLAG_EMPTY = (1 << 18), 00503 CONFFLAG_EMPTYNOPIN = (1 << 19), 00504 CONFFLAG_ALWAYSPROMPT = (1 << 20), 00505 /*! If set, treat talking users as muted users */ 00506 CONFFLAG_OPTIMIZETALKER = (1 << 21), 00507 /*! If set, won't speak the extra prompt when the first person 00508 * enters the conference */ 00509 CONFFLAG_NOONLYPERSON = (1 << 22), 00510 /*! If set, user will be asked to record name on entry of conference 00511 * without review */ 00512 CONFFLAG_INTROUSERNOREVIEW = (1 << 23), 00513 /*! If set, the user will be initially self-muted */ 00514 CONFFLAG_STARTMUTED = (1 << 24), 00515 /*! Pass DTMF through the conference */ 00516 CONFFLAG_PASS_DTMF = (1 << 25), 00517 CONFFLAG_SLA_STATION = (1 << 26), 00518 CONFFLAG_SLA_TRUNK = (1 << 27), 00519 /*! If set, the user should continue in the dialplan if kicked out */ 00520 CONFFLAG_KICK_CONTINUE = (1 << 28), 00521 CONFFLAG_DURATION_STOP = (1 << 29), 00522 CONFFLAG_DURATION_LIMIT = (1 << 30), 00523 /*! Do not write any audio to this channel until the state is up. */ 00524 CONFFLAG_NO_AUDIO_UNTIL_UP = (1 << 31), 00525 };
| 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 527 of file app_meetme.c.
00527 { 00528 OPT_ARG_WAITMARKED = 0, 00529 OPT_ARG_EXITKEYS = 1, 00530 OPT_ARG_DURATION_STOP = 2, 00531 OPT_ARG_DURATION_LIMIT = 3, 00532 OPT_ARG_MOH_CLASS = 4, 00533 OPT_ARG_ARRAY_SIZE = 5, 00534 };
| anonymous enum |
Definition at line 5795 of file app_meetme.c.
05795 { 05796 SLA_TRUNK_OPT_MOH = (1 << 0), 05797 };
| anonymous enum |
Definition at line 5799 of file app_meetme.c.
05799 { 05800 SLA_TRUNK_OPT_ARG_MOH_CLASS = 0, 05801 SLA_TRUNK_OPT_ARG_ARRAY_SIZE = 1, 05802 };
| enum announcetypes |
Definition at line 592 of file app_meetme.c.
00592 { 00593 CONF_HASJOIN, 00594 CONF_HASLEFT 00595 };
| enum entrance_sound |
Definition at line 452 of file app_meetme.c.
| enum recording_state |
Definition at line 457 of file app_meetme.c.
00457 { 00458 MEETME_RECORD_OFF, 00459 MEETME_RECORD_STARTED, 00460 MEETME_RECORD_ACTIVE, 00461 MEETME_RECORD_TERMINATE 00462 };
| enum sla_event_type |
Event types that can be queued up for the SLA thread.
Definition at line 785 of file app_meetme.c.
00785 { 00786 /*! A station has put the call on hold */ 00787 SLA_EVENT_HOLD, 00788 /*! The state of a dial has changed */ 00789 SLA_EVENT_DIAL_STATE, 00790 /*! The state of a ringing trunk has changed */ 00791 SLA_EVENT_RINGING_TRUNK, 00792 /*! A reload of configuration has been requested */ 00793 SLA_EVENT_RELOAD, 00794 /*! Poke the SLA thread so it can check if it can perform a reload */ 00795 SLA_EVENT_CHECK_RELOAD, 00796 };
| enum sla_hold_access |
Definition at line 695 of file app_meetme.c.
00695 { 00696 /*! This means that any station can put it on hold, and any station 00697 * can retrieve the call from hold. */ 00698 SLA_HOLD_OPEN, 00699 /*! This means that only the station that put the call on hold may 00700 * retrieve it from hold. */ 00701 SLA_HOLD_PRIVATE, 00702 };
| enum sla_station_hangup |
Definition at line 822 of file app_meetme.c.
00822 { 00823 SLA_STATION_HANGUP_NORMAL, 00824 SLA_STATION_HANGUP_TIMEOUT, 00825 };
| 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 687 of file app_meetme.c.
00687 { 00688 SLA_TRUNK_STATE_IDLE, 00689 SLA_TRUNK_STATE_RINGING, 00690 SLA_TRUNK_STATE_UP, 00691 SLA_TRUNK_STATE_ONHOLD, 00692 SLA_TRUNK_STATE_ONHOLD_BYME, 00693 };
| enum sla_which_trunk_refs |
Definition at line 682 of file app_meetme.c.
00682 { 00683 ALL_TRUNK_REFS, 00684 INACTIVE_TRUNK_REFS, 00685 };
| enum volume_action |
Definition at line 447 of file app_meetme.c.
| static void __reg_module | ( | void | ) | [static] |
Definition at line 6500 of file app_meetme.c.
| static void __unreg_module | ( | void | ) | [static] |
Definition at line 6500 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 6355 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_strlen_zero(), ast_conference::confno, ast_conference::list, LOG_ERROR, LOG_NOTICE, and parse().
06356 { 06357 struct ast_conference *conf; 06358 char *parse; 06359 int result = -2; /* only non-negative numbers valid, -1 is used elsewhere */ 06360 AST_DECLARE_APP_ARGS(args, 06361 AST_APP_ARG(keyword); 06362 AST_APP_ARG(confno); 06363 ); 06364 06365 if (ast_strlen_zero(data)) { 06366 ast_log(LOG_ERROR, "Syntax: MEETME_INFO() requires two arguments\n"); 06367 return -1; 06368 } 06369 06370 parse = ast_strdupa(data); 06371 AST_STANDARD_APP_ARGS(args, parse); 06372 06373 if (ast_strlen_zero(args.keyword)) { 06374 ast_log(LOG_ERROR, "Syntax: MEETME_INFO() requires a keyword\n"); 06375 return -1; 06376 } 06377 06378 if (ast_strlen_zero(args.confno)) { 06379 ast_log(LOG_ERROR, "Syntax: MEETME_INFO() requires a conference number\n"); 06380 return -1; 06381 } 06382 06383 AST_LIST_LOCK(&confs); 06384 AST_LIST_TRAVERSE(&confs, conf, list) { 06385 if (!strcmp(args.confno, conf->confno)) { 06386 result = acf_meetme_info_eval(args.keyword, conf); 06387 break; 06388 } 06389 } 06390 AST_LIST_UNLOCK(&confs); 06391 06392 if (result > -1) { 06393 snprintf(buf, len, "%d", result); 06394 } else if (result == -1) { 06395 ast_log(LOG_NOTICE, "Error: invalid keyword: '%s'\n", args.keyword); 06396 snprintf(buf, len, "0"); 06397 } else if (result == -2) { 06398 ast_log(LOG_NOTICE, "Error: conference (%s) not found\n", args.confno); 06399 snprintf(buf, len, "0"); 06400 } 06401 06402 return 0; 06403 }
| static int acf_meetme_info_eval | ( | char * | keyword, | |
| struct ast_conference * | conf | |||
| ) | [static] |
Definition at line 6337 of file app_meetme.c.
References ast_conference::isdynamic, ast_conference::locked, ast_conference::start, and ast_conference::users.
Referenced by acf_meetme_info().
06338 { 06339 if (!strcasecmp("lock", keyword)) { 06340 return conf->locked; 06341 } else if (!strcasecmp("parties", keyword)) { 06342 return conf->users; 06343 } else if (!strcasecmp("activity", keyword)) { 06344 time_t now; 06345 now = time(NULL); 06346 return (now - conf->start); 06347 } else if (!strcasecmp("dynamic", keyword)) { 06348 return conf->isdynamic; 06349 } else { 06350 return -1; 06351 } 06352 06353 }
| static int action_meetmelist | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 4292 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, ast_channel::name, S_OR, ast_conf_user::talking, total, ast_conf_user::user_no, ast_conf_user::userflags, and ast_conference::userlist.
Referenced by load_module().
04293 { 04294 const char *actionid = astman_get_header(m, "ActionID"); 04295 const char *conference = astman_get_header(m, "Conference"); 04296 char idText[80] = ""; 04297 struct ast_conference *cnf; 04298 struct ast_conf_user *user; 04299 int total = 0; 04300 04301 if (!ast_strlen_zero(actionid)) 04302 snprintf(idText, sizeof(idText), "ActionID: %s\r\n", actionid); 04303 04304 if (AST_LIST_EMPTY(&confs)) { 04305 astman_send_error(s, m, "No active conferences."); 04306 return 0; 04307 } 04308 04309 astman_send_listack(s, m, "Meetme user list will follow", "start"); 04310 04311 /* Find the right conference */ 04312 AST_LIST_LOCK(&confs); 04313 AST_LIST_TRAVERSE(&confs, cnf, list) { 04314 /* If we ask for one particular, and this isn't it, skip it */ 04315 if (!ast_strlen_zero(conference) && strcmp(cnf->confno, conference)) 04316 continue; 04317 04318 /* Show all the users */ 04319 AST_LIST_TRAVERSE(&cnf->userlist, user, list) { 04320 total++; 04321 astman_append(s, 04322 "Event: MeetmeList\r\n" 04323 "%s" 04324 "Conference: %s\r\n" 04325 "UserNumber: %d\r\n" 04326 "CallerIDNum: %s\r\n" 04327 "CallerIDName: %s\r\n" 04328 "Channel: %s\r\n" 04329 "Admin: %s\r\n" 04330 "Role: %s\r\n" 04331 "MarkedUser: %s\r\n" 04332 "Muted: %s\r\n" 04333 "Talking: %s\r\n" 04334 "\r\n", 04335 idText, 04336 cnf->confno, 04337 user->user_no, 04338 S_OR(user->chan->cid.cid_num, "<unknown>"), 04339 S_OR(user->chan->cid.cid_name, "<no name>"), 04340 user->chan->name, 04341 user->userflags & CONFFLAG_ADMIN ? "Yes" : "No", 04342 user->userflags & CONFFLAG_MONITOR ? "Listen only" : user->userflags & CONFFLAG_TALKER ? "Talk only" : "Talk and listen", 04343 user->userflags & CONFFLAG_MARKEDUSER ? "Yes" : "No", 04344 user->adminflags & ADMINFLAG_MUTED ? "By admin" : user->adminflags & ADMINFLAG_SELFMUTED ? "By self" : "No", 04345 user->talking > 0 ? "Yes" : user->talking == 0 ? "No" : "Not monitored"); 04346 } 04347 } 04348 AST_LIST_UNLOCK(&confs); 04349 /* Send final confirmation */ 04350 astman_append(s, 04351 "Event: MeetmeListComplete\r\n" 04352 "EventList: Complete\r\n" 04353 "ListItems: %d\r\n" 04354 "%s" 04355 "\r\n", total, idText); 04356 return 0; 04357 }
| static int action_meetmemute | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 4274 of file app_meetme.c.
References meetmemute().
Referenced by load_module().
04275 { 04276 return meetmemute(s, m, 1); 04277 }
| static int action_meetmeunmute | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 4279 of file app_meetme.c.
References meetmemute().
Referenced by load_module().
04280 { 04281 return meetmemute(s, m, 0); 04282 }
| static int admin_exec | ( | struct ast_channel * | chan, | |
| void * | data | |||
| ) | [static] |
The MeetMeadmin application.
Definition at line 3969 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_strlen_zero(), CONFFLAG_ADMIN, ast_conference::confno, dispose_conf(), find_user(), ast_conf_user::list, ast_conference::locked, LOG_NOTICE, LOG_WARNING, pbx_builtin_setvar_helper(), ast_conference::refcount, reset_volumes(), rt_extend_conf(), tweak_listen_volume(), tweak_talk_volume(), ast_conf_user::userflags, ast_conference::userlist, VOL_DOWN, and VOL_UP.
Referenced by load_module(), meetme_cmd(), meetme_show_cmd(), run_station(), sla_station_exec(), and sla_stop_ringing_trunk().
03969 { 03970 char *params; 03971 struct ast_conference *cnf; 03972 struct ast_conf_user *user = NULL; 03973 AST_DECLARE_APP_ARGS(args, 03974 AST_APP_ARG(confno); 03975 AST_APP_ARG(command); 03976 AST_APP_ARG(user); 03977 ); 03978 int res = 0; 03979 03980 if (ast_strlen_zero(data)) { 03981 ast_log(LOG_WARNING, "MeetMeAdmin requires an argument!\n"); 03982 pbx_builtin_setvar_helper(chan, "MEETMEADMINSTATUS", "NOPARSE"); 03983 return -1; 03984 } 03985 03986 params = ast_strdupa(data); 03987 AST_STANDARD_APP_ARGS(args, params); 03988 03989 if (!args.command) { 03990 ast_log(LOG_WARNING, "MeetmeAdmin requires a command!\n"); 03991 pbx_builtin_setvar_helper(chan, "MEETMEADMINSTATUS", "NOPARSE"); 03992 return -1; 03993 } 03994 03995 AST_LIST_LOCK(&confs); 03996 AST_LIST_TRAVERSE(&confs, cnf, list) { 03997 if (!strcmp(cnf->confno, args.confno)) 03998 break; 03999 } 04000 04001 if (!cnf) { 04002 ast_log(LOG_WARNING, "Conference number '%s' not found!\n", args.confno); 04003 AST_LIST_UNLOCK(&confs); 04004 pbx_builtin_setvar_helper(chan, "MEETMEADMINSTATUS", "NOTFOUND"); 04005 return 0; 04006 } 04007 04008 ast_atomic_fetchadd_int(&cnf->refcount, 1); 04009 04010 if (args.user) 04011 user = find_user(cnf, args.user); 04012 04013 switch (*args.command) { 04014 case 76: /* L: Lock */ 04015 cnf->locked = 1; 04016 break; 04017 case 108: /* l: Unlock */ 04018 cnf->locked = 0; 04019 break; 04020 case 75: /* K: kick all users */ 04021 AST_LIST_TRAVERSE(&cnf->userlist, user, list) 04022 user->adminflags |= ADMINFLAG_KICKME; 04023 break; 04024 case 101: /* e: Eject last user*/ 04025 user = AST_LIST_LAST(&cnf->userlist); 04026 if (!(user->userflags & CONFFLAG_ADMIN)) 04027 user->adminflags |= ADMINFLAG_KICKME; 04028 else { 04029 res = -1; 04030 ast_log(LOG_NOTICE, "Not kicking last user, is an Admin!\n"); 04031 } 04032 break; 04033 case 77: /* M: Mute */ 04034 if (user) { 04035 user->adminflags |= ADMINFLAG_MUTED; 04036 } else { 04037 res = -2; 04038 ast_log(LOG_NOTICE, "Specified User not found!\n"); 04039 } 04040 break; 04041 case 78: /* N: Mute all (non-admin) users */ 04042 AST_LIST_TRAVERSE(&cnf->userlist, user, list) { 04043 if (!(user->userflags & CONFFLAG_ADMIN)) { 04044 user->adminflags |= ADMINFLAG_MUTED; 04045 } 04046 } 04047 break; 04048 case 109: /* m: Unmute */ 04049 if (user) { 04050 user->adminflags &= ~(ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED | ADMINFLAG_T_REQUEST); 04051 } else { 04052 res = -2; 04053 ast_log(LOG_NOTICE, "Specified User not found!\n"); 04054 } 04055 break; 04056 case 110: /* n: Unmute all users */ 04057 AST_LIST_TRAVERSE(&cnf->userlist, user, list) { 04058 user->adminflags &= ~(ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED | ADMINFLAG_T_REQUEST); 04059 } 04060 break; 04061 case 107: /* k: Kick user */ 04062 if (user) { 04063 user->adminflags |= ADMINFLAG_KICKME; 04064 } else { 04065 res = -2; 04066 ast_log(LOG_NOTICE, "Specified User not found!\n"); 04067 } 04068 break; 04069 case 118: /* v: Lower all users listen volume */ 04070 AST_LIST_TRAVERSE(&cnf->userlist, user, list) { 04071 tweak_listen_volume(user, VOL_DOWN); 04072 } 04073 break; 04074 case 86: /* V: Raise all users listen volume */ 04075 AST_LIST_TRAVERSE(&cnf->userlist, user, list) { 04076 tweak_listen_volume(user, VOL_UP); 04077 } 04078 break; 04079 case 115: /* s: Lower all users speaking volume */ 04080 AST_LIST_TRAVERSE(&cnf->userlist, user, list) { 04081 tweak_talk_volume(user, VOL_DOWN); 04082 } 04083 break; 04084 case 83: /* S: Raise all users speaking volume */ 04085 AST_LIST_TRAVERSE(&cnf->userlist, user, list) { 04086 tweak_talk_volume(user, VOL_UP); 04087 } 04088 break; 04089 case 82: /* R: Reset all volume levels */ 04090 AST_LIST_TRAVERSE(&cnf->userlist, user, list) { 04091 reset_volumes(user); 04092 } 04093 break; 04094 case 114: /* r: Reset user's volume level */ 04095 if (user) { 04096 reset_volumes(user); 04097 } else { 04098 res = -2; 04099 ast_log(LOG_NOTICE, "Specified User not found!\n"); 04100 } 04101 break; 04102 case 85: /* U: Raise user's listen volume */ 04103 if (user) { 04104 tweak_listen_volume(user, VOL_UP); 04105 } else { 04106 res = -2; 04107 ast_log(LOG_NOTICE, "Specified User not found!\n"); 04108 } 04109 break; 04110 case 117: /* u: Lower user's listen volume */ 04111 if (user) { 04112 tweak_listen_volume(user, VOL_DOWN); 04113 } else { 04114 res = -2; 04115 ast_log(LOG_NOTICE, "Specified User not found!\n"); 04116 } 04117 break; 04118 case 84: /* T: Raise user's talk volume */ 04119 if (user) { 04120 tweak_talk_volume(user, VOL_UP); 04121 } else { 04122 res = -2; 04123 ast_log(LOG_NOTICE, "Specified User not found!\n"); 04124 } 04125 break; 04126 case 116: /* t: Lower user's talk volume */ 04127 if (user) { 04128 tweak_talk_volume(user, VOL_DOWN); 04129 } else { 04130 res = -2; 04131 ast_log(LOG_NOTICE, "Specified User not found!\n"); 04132 } 04133 break; 04134 case 'E': /* E: Extend conference */ 04135 if (rt_extend_conf(args.confno)) { 04136 res = -1; 04137 } 04138 break; 04139 } 04140 04141 AST_LIST_UNLOCK(&confs); 04142 04143 dispose_conf(cnf); 04144 pbx_builtin_setvar_helper(chan, "MEETMEADMINSTATUS", res == -2 ? "NOTFOUND" : res ? "FAILED" : "OK"); 04145 04146 return 0; 04147 }
| static void* announce_thread | ( | void * | data | ) | [static] |
Definition at line 1907 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().
01908 { 01909 struct announce_listitem *current; 01910 struct ast_conference *conf = data; 01911 int res; 01912 char filename[PATH_MAX] = ""; 01913 AST_LIST_HEAD_NOLOCK(, announce_listitem) local_list; 01914 AST_LIST_HEAD_INIT_NOLOCK(&local_list); 01915 01916 while (!conf->announcethread_stop) { 01917 ast_mutex_lock(&conf->announcelistlock); 01918 if (conf->announcethread_stop) { 01919 ast_mutex_unlock(&conf->announcelistlock); 01920 break; 01921 } 01922 if (AST_LIST_EMPTY(&conf->announcelist)) 01923 ast_cond_wait(&conf->announcelist_addition, &conf->announcelistlock); 01924 01925 AST_LIST_APPEND_LIST(&local_list, &conf->announcelist, entry); 01926 AST_LIST_HEAD_INIT_NOLOCK(&conf->announcelist); 01927 01928 ast_mutex_unlock(&conf->announcelistlock); 01929 if (conf->announcethread_stop) { 01930 break; 01931 } 01932 01933 for (res = 1; !conf->announcethread_stop && (current = AST_LIST_REMOVE_HEAD(&local_list, entry)); ao2_ref(current, -1)) { 01934 ast_log(LOG_DEBUG, "About to play %s\n", current->namerecloc); 01935 if (!ast_fileexists(current->namerecloc, NULL, NULL)) 01936 continue; 01937 if ((current->confchan) && (current->confusers > 1) && !ast_check_hangup(current->confchan)) { 01938 if (!ast_streamfile(current->confchan, current->namerecloc, current->language)) 01939 res = ast_waitstream(current->confchan, ""); 01940 if (!res) { 01941 ast_copy_string(filename, get_announce_filename(current->announcetype), sizeof(filename)); 01942 if (!ast_streamfile(current->confchan, filename, current->language)) 01943 ast_waitstream(current->confchan, ""); 01944 } 01945 } 01946 if (current->announcetype == CONF_HASLEFT) { 01947 ast_filedelete(current->namerecloc, NULL); 01948 } 01949 } 01950 } 01951 01952 /* thread marked to stop, clean up */ 01953 while ((current = AST_LIST_REMOVE_HEAD(&local_list, entry))) { 01954 ast_filedelete(current->namerecloc, NULL); 01955 ao2_ref(current, -1); 01956 } 01957 return NULL; 01958 }
| static void answer_trunk_chan | ( | struct ast_channel * | chan | ) | [static] |
Definition at line 4667 of file app_meetme.c.
References ast_answer(), and ast_indicate().
Referenced by run_station(), sla_handle_dial_state_event(), and sla_station_exec().
04668 { 04669 ast_answer(chan); 04670 ast_indicate(chan, -1); 04671 }
| 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 1061 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, ast_channel::uniqueid, and ast_conference::uniqueid.
Referenced by dial_trunk(), find_conf(), find_conf_realtime(), run_station(), sla_station_exec(), and sla_trunk_exec().
01062 { 01063 struct ast_conference *cnf; 01064 struct dahdi_confinfo dahdic = { 0, }; 01065 int confno_int = 0; 01066 01067 AST_LIST_LOCK(&confs); 01068 01069 AST_LIST_TRAVERSE(&confs, cnf, list) { 01070 if (!strcmp(confno, cnf->confno)) 01071 break; 01072 } 01073 01074 if (cnf || (!make && !dynamic)) 01075 goto cnfout; 01076 01077 /* Make a new one */ 01078 if (!(cnf = ast_calloc(1, sizeof(*cnf)))) 01079 goto cnfout; 01080 01081 ast_mutex_init(&cnf->playlock); 01082 ast_mutex_init(&cnf->listenlock); 01083 cnf->recordthread = AST_PTHREADT_NULL; 01084 ast_mutex_init(&cnf->recordthreadlock); 01085 cnf->announcethread = AST_PTHREADT_NULL; 01086 ast_mutex_init(&cnf->announcethreadlock); 01087 ast_copy_string(cnf->confno, confno, sizeof(cnf->confno)); 01088 ast_copy_string(cnf->pin, pin, sizeof(cnf->pin)); 01089 ast_copy_string(cnf->pinadmin, pinadmin, sizeof(cnf->pinadmin)); 01090 ast_copy_string(cnf->uniqueid, chan->uniqueid, sizeof(cnf->uniqueid)); 01091 01092 /* Setup a new dahdi conference */ 01093 dahdic.confno = -1; 01094 dahdic.confmode = DAHDI_CONF_CONFANN | DAHDI_CONF_CONFANNMON; 01095 cnf->fd = open("/dev/dahdi/pseudo", O_RDWR); 01096 if (cnf->fd < 0 || ioctl(cnf->fd, DAHDI_SETCONF, &dahdic)) { 01097 ast_log(LOG_WARNING, "Unable to open pseudo device\n"); 01098 if (cnf->fd >= 0) 01099 close(cnf->fd); 01100 ast_free(cnf); 01101 cnf = NULL; 01102 goto cnfout; 01103 } 01104 01105 cnf->dahdiconf = dahdic.confno; 01106 01107 /* Setup a new channel for playback of audio files */ 01108 cnf->chan = ast_request("DAHDI", AST_FORMAT_SLINEAR, "pseudo", NULL); 01109 if (cnf->chan) { 01110 ast_set_read_format(cnf->chan, AST_FORMAT_SLINEAR); 01111 ast_set_write_format(cnf->chan, AST_FORMAT_SLINEAR); 01112 dahdic.chan = 0; 01113 dahdic.confno = cnf->dahdiconf; 01114 dahdic.confmode = DAHDI_CONF_CONFANN | DAHDI_CONF_CONFANNMON; 01115 if (ioctl(cnf->chan->fds[0], DAHDI_SETCONF, &dahdic)) { 01116 ast_log(LOG_WARNING, "Error setting conference\n"); 01117 if (cnf->chan) 01118 ast_hangup(cnf->chan); 01119 else 01120 close(cnf->fd); 01121 01122 ast_free(cnf); 01123 cnf = NULL; 01124 goto cnfout; 01125 } 01126 } 01127 01128 /* Fill the conference struct */ 01129 cnf->start = time(NULL); 01130 cnf->maxusers = 0x7fffffff; 01131 cnf->isdynamic = dynamic ? 1 : 0; 01132 ast_verb(3, "Created MeetMe conference %d for conference '%s'\n", cnf->dahdiconf, cnf->confno); 01133 AST_LIST_INSERT_HEAD(&confs, cnf, list); 01134 01135 /* Reserve conference number in map */ 01136 if ((sscanf(cnf->confno, "%30d", &confno_int) == 1) && (confno_int >= 0 && confno_int < 1024)) 01137 conf_map[confno_int] = 1; 01138 01139 cnfout: 01140 if (cnf) 01141 ast_atomic_fetchadd_int(&cnf->refcount, refcount); 01142 01143 AST_LIST_UNLOCK(&confs); 01144 01145 return cnf; 01146 }
| static int can_write | ( | struct ast_channel * | chan, | |
| int | confflags | |||
| ) | [static] |
Definition at line 1960 of file app_meetme.c.
References ast_channel::_state, AST_STATE_UP, and CONFFLAG_NO_AUDIO_UNTIL_UP.
Referenced by conf_run().
01961 { 01962 if (!(confflags & CONFFLAG_NO_AUDIO_UNTIL_UP)) { 01963 return 1; 01964 } 01965 01966 return (chan->_state == AST_STATE_UP); 01967 }
| static int careful_write | ( | int | fd, | |
| unsigned char * | data, | |||
| int | len, | |||
| int | block | |||
| ) | [static] |
Definition at line 895 of file app_meetme.c.
References ast_log(), errno, and LOG_WARNING.
Referenced by conf_play(), and conf_run().
00896 { 00897 int res; 00898 int x; 00899 00900 while (len) { 00901 if (block) { 00902 x = DAHDI_IOMUX_WRITE | DAHDI_IOMUX_SIGEVENT; 00903 res = ioctl(fd, DAHDI_IOMUX, &x); 00904 } else 00905 res = 0; 00906 if (res >= 0) 00907 res = write(fd, data, len); 00908 if (res < 1) { 00909 if (errno != EAGAIN) { 00910 ast_log(LOG_WARNING, "Failed to write audio data to conference: %s\n", strerror(errno)); 00911 return -1; 00912 } else 00913 return 0; 00914 } 00915 len -= res; 00916 data += res; 00917 } 00918 00919 return 0; 00920 }
| static int channel_admin_exec | ( | struct ast_channel * | chan, | |
| void * | data | |||
| ) | [static] |
Definition at line 4151 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_strlen_zero(), ast_conf_user::chan, ast_conf_user::list, LOG_NOTICE, LOG_WARNING, ast_channel::name, and ast_conference::userlist.
Referenced by load_module().
04151 { 04152 char *params; 04153 struct ast_conference *conf = NULL; 04154 struct ast_conf_user *user = NULL; 04155 AST_DECLARE_APP_ARGS(args, 04156 AST_APP_ARG(channel); 04157 AST_APP_ARG(command); 04158 ); 04159 04160 if (ast_strlen_zero(data)) { 04161 ast_log(LOG_WARNING, "MeetMeChannelAdmin requires two arguments!\n"); 04162 return -1; 04163 } 04164 04165 params = ast_strdupa(data); 04166 AST_STANDARD_APP_ARGS(args, params); 04167 04168 if (!args.channel) { 04169 ast_log(LOG_WARNING, "MeetMeChannelAdmin requires a channel name!\n"); 04170 return -1; 04171 } 04172 04173 if (!args.command) { 04174 ast_log(LOG_WARNING, "MeetMeChannelAdmin requires a command!\n"); 04175 return -1; 04176 } 04177 04178 AST_LIST_LOCK(&confs); 04179 AST_LIST_TRAVERSE(&confs, conf, list) { 04180 AST_LIST_TRAVERSE(&conf->userlist, user, list) { 04181 if (!strcmp(user->chan->name, args.channel)) 04182 break; 04183 } 04184 } 04185 04186 if (!user) { 04187 ast_log(LOG_NOTICE, "Specified user (%s) not found\n", args.channel); 04188 AST_LIST_UNLOCK(&confs); 04189 return 0; 04190 } 04191 04192 /* perform the specified action */ 04193 switch (*args.command) { 04194 case 77: /* M: Mute */ 04195 user->adminflags |= ADMINFLAG_MUTED; 04196 break; 04197 case 109: /* m: Unmute */ 04198 user->adminflags &= ~ADMINFLAG_MUTED; 04199 break; 04200 case 107: /* k: Kick user */ 04201 user->adminflags |= ADMINFLAG_KICKME; 04202 break; 04203 default: /* unknown command */ 04204 ast_log(LOG_WARNING, "Unknown MeetMeChannelAdmin command '%s'\n", args.command); 04205 break; 04206 } 04207 04208 AST_LIST_UNLOCK(&confs); 04209 04210 return 0; 04211 }
| static char* complete_meetmecmd | ( | const char * | line, | |
| const char * | word, | |||
| int | pos, | |||
| int | state | |||
| ) | [static] |
Definition at line 1148 of file app_meetme.c.
References ast_cli_complete(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_strdup, ast_conference::confno, len(), ast_conf_user::list, ast_conf_user::user_no, and ast_conference::userlist.
Referenced by meetme_cmd(), and meetme_show_cmd().
01149 { 01150 static char *cmds[] = {"concise", "lock", "unlock", "mute", "unmute", "kick", "list", NULL}; 01151 01152 int len = strlen(word); 01153 int which = 0; 01154 struct ast_conference *cnf = NULL; 01155 struct ast_conf_user *usr = NULL; 01156 char *confno = NULL; 01157 char usrno[50] = ""; 01158 char *myline, *ret = NULL; 01159 01160 if (pos == 1) { /* Command */ 01161 return ast_cli_complete(word, cmds, state); 01162 } else if (pos == 2) { /* Conference Number */ 01163 AST_LIST_LOCK(&confs); 01164 AST_LIST_TRAVERSE(&confs, cnf, list) { 01165 if (!strncasecmp(word, cnf->confno, len) && ++which > state) { 01166 ret = cnf->confno; 01167 break; 01168 } 01169 } 01170 ret = ast_strdup(ret); /* dup before releasing the lock */ 01171 AST_LIST_UNLOCK(&confs); 01172 return ret; 01173 } else if (pos == 3) { 01174 /* User Number || Conf Command option*/ 01175 if (strstr(line, "mute") || strstr(line, "kick")) { 01176 if (state == 0 && (strstr(line, "kick") || strstr(line, "mute")) && !strncasecmp(word, "all", len)) 01177 return ast_strdup("all"); 01178 which++; 01179 AST_LIST_LOCK(&confs); 01180 01181 /* TODO: Find the conf number from the cmdline (ignore spaces) <- test this and make it fail-safe! */ 01182 myline = ast_strdupa(line); 01183 if (strsep(&myline, " ") && strsep(&myline, " ") && !confno) { 01184 while((confno = strsep(&myline, " ")) && (strcmp(confno, " ") == 0)) 01185 ; 01186 } 01187 01188 AST_LIST_TRAVERSE(&confs, cnf, list) { 01189 if (!strcmp(confno, cnf->confno)) 01190 break; 01191 } 01192 01193 if (cnf) { 01194 /* Search for the user */ 01195 AST_LIST_TRAVERSE(&cnf->userlist, usr, list) { 01196 snprintf(usrno, sizeof(usrno), "%d", usr->user_no); 01197 if (!strncasecmp(word, usrno, len) && ++which > state) 01198 break; 01199 } 01200 } 01201 AST_LIST_UNLOCK(&confs); 01202 return usr ? ast_strdup(usrno) : NULL; 01203 } 01204 } 01205 01206 return NULL; 01207 }
| static int conf_exec | ( | struct ast_channel * | chan, | |
| void * | data | |||
| ) | [static] |
The meetme() application.
Definition at line 3696 of file app_meetme.c.
References ast_channel::_state, ast_conference::adminopts, 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_STANDARD_APP_ARGS, AST_STATE_UP, ast_stopstream(), ast_streamfile(), ast_strlen_zero(), ast_test_flag, ast_variable_browse(), ast_verb, 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, CONFIG_STATUS_FILEINVALID, ast_conference::confno, dispose_conf(), find_conf(), find_conf_realtime(), ast_flags::flags, ast_channel::language, LOG_ERROR, LOG_WARNING, MAX_CONFNUM, MAX_PIN, MAX_SETTINGS, meetme_opts, ast_variable::name, ast_variable::next, OPT_ARG_ARRAY_SIZE, parse(), ast_conference::pin, ast_conference::pinadmin, ast_conference::recordingfilename, ast_conference::recordingformat, ast_conference::useropts, ast_variable::value, and var.
Referenced by load_module().
03697 { 03698 int res = -1; 03699 char confno[MAX_CONFNUM] = ""; 03700 int allowretry = 0; 03701 int retrycnt = 0; 03702 struct ast_conference *cnf = NULL; 03703 struct ast_flags confflags = {0}, config_flags = { 0 }; 03704 int dynamic = 0; 03705 int empty = 0, empty_no_pin = 0; 03706 int always_prompt = 0; 03707 char *notdata, *info, the_pin[MAX_PIN] = ""; 03708 AST_DECLARE_APP_ARGS(args, 03709 AST_APP_ARG(confno); 03710 AST_APP_ARG(options); 03711 AST_APP_ARG(pin); 03712 ); 03713 char *optargs[OPT_ARG_ARRAY_SIZE] = { NULL, }; 03714 03715 if (ast_strlen_zero(data)) { 03716 allowretry = 1; 03717 notdata = ""; 03718 } else { 03719 notdata = data; 03720 } 03721 03722 if (chan->_state != AST_STATE_UP) 03723 ast_answer(chan); 03724 03725 info = ast_strdupa(notdata); 03726 03727 AST_STANDARD_APP_ARGS(args, info); 03728 03729 if (args.confno) { 03730 ast_copy_string(confno, args.confno, sizeof(confno)); 03731 if (ast_strlen_zero(confno)) { 03732 allowretry = 1; 03733 } 03734 } 03735 03736 if (args.pin) 03737 ast_copy_string(the_pin, args.pin, sizeof(the_pin)); 03738 03739 if (args.options) { 03740 ast_app_parse_options(meetme_opts, &confflags, optargs, args.options); 03741 dynamic = ast_test_flag(&confflags, CONFFLAG_DYNAMIC | CONFFLAG_DYNAMICPIN); 03742 if (ast_test_flag(&confflags, CONFFLAG_DYNAMICPIN) && ast_strlen_zero(args.pin)) 03743 strcpy(the_pin, "q"); 03744 03745 empty = ast_test_flag(&confflags, CONFFLAG_EMPTY | CONFFLAG_EMPTYNOPIN); 03746 empty_no_pin = ast_test_flag(&confflags, CONFFLAG_EMPTYNOPIN); 03747 always_prompt = ast_test_flag(&confflags, CONFFLAG_ALWAYSPROMPT | CONFFLAG_DYNAMICPIN); 03748 } 03749 03750 do { 03751 if (retrycnt > 3) 03752 allowretry = 0; 03753 if (empty) { 03754 int i; 03755 struct ast_config *cfg; 03756 struct ast_variable *var; 03757 int confno_int; 03758 03759 /* We only need to load the config file for static and empty_no_pin (otherwise we don't care) */ 03760 if ((empty_no_pin) || (!dynamic)) { 03761 cfg = ast_config_load(CONFIG_FILE_NAME, config_flags); 03762 if (cfg && cfg != CONFIG_STATUS_FILEINVALID) { 03763 var = ast_variable_browse(cfg, "rooms"); 03764 while (var) { 03765 char parse[MAX_SETTINGS], *stringp = parse, *confno_tmp; 03766 if (!strcasecmp(var->name, "conf")) { 03767 int found = 0; 03768 ast_copy_string(parse, var->value, sizeof(parse)); 03769 confno_tmp = strsep(&stringp, "|,"); 03770 if (!dynamic) { 03771 /* For static: run through the list and see if this conference is empty */ 03772 AST_LIST_LOCK(&confs); 03773 AST_LIST_TRAVERSE(&confs, cnf, list) { 03774 if (!strcmp(confno_tmp, cnf->confno)) { 03775 /* The conference exists, therefore it's not empty */ 03776 found = 1; 03777 break; 03778 } 03779 } 03780 AST_LIST_UNLOCK(&confs); 03781 if (!found) { 03782 /* At this point, we have a confno_tmp (static conference) that is empty */ 03783 if ((empty_no_pin && ast_strlen_zero(stringp)) || (!empty_no_pin)) { 03784 /* Case 1: empty_no_pin and pin is nonexistent (NULL) 03785 * Case 2: empty_no_pin and pin is blank (but not NULL) 03786 * Case 3: not empty_no_pin 03787 */ 03788 ast_copy_string(confno, confno_tmp, sizeof(confno)); 03789 break; 03790 /* XXX the map is not complete (but we do have a confno) */ 03791 } 03792 } 03793 } 03794 } 03795 var = var->next; 03796 } 03797 ast_config_destroy(cfg); 03798 } 03799 } 03800 03801 /* Select first conference number not in use */ 03802 if (ast_strlen_zero(confno) && dynamic) { 03803 AST_LIST_LOCK(&confs); 03804 for (i = 0; i < ARRAY_LEN(conf_map); i++) { 03805 if (!conf_map[i]) { 03806 snprintf(confno, sizeof(confno), "%d", i); 03807 conf_map[i] = 1; 03808 break; 03809 } 03810 } 03811 AST_LIST_UNLOCK(&confs); 03812 } 03813 03814 /* Not found? */ 03815 if (ast_strlen_zero(confno)) { 03816 res = ast_streamfile(chan, "conf-noempty", chan->language); 03817 if (!res) 03818 ast_waitstream(chan, ""); 03819 } else { 03820 if (sscanf(confno, "%30d", &confno_int) == 1) { 03821 if (!ast_test_flag(&confflags, CONFFLAG_QUIET)) { 03822 res = ast_streamfile(chan, "conf-enteringno", chan->language); 03823 if (!res) { 03824 ast_waitstream(chan, ""); 03825 res = ast_say_digits(chan, confno_int, "", chan->language); 03826 } 03827 } 03828 } else { 03829 ast_log(LOG_ERROR, "Could not scan confno '%s'\n", confno); 03830 } 03831 } 03832 } 03833 03834 while (allowretry && (ast_strlen_zero(confno)) && (++retrycnt < 4)) { 03835 /* Prompt user for conference number */ 03836 res = ast_app_getdata(chan, "conf-getconfno", confno, sizeof(confno) - 1, 0); 03837 if (res < 0) { 03838 /* Don't try to validate when we catch an error */ 03839 confno[0] = '\0'; 03840 allowretry = 0; 03841 break; 03842 } 03843 } 03844 if (!ast_strlen_zero(confno)) { 03845 /* Check the validity of the conference */ 03846 cnf = find_conf(chan, confno, 1, dynamic, the_pin, 03847 sizeof(the_pin), 1, &confflags); 03848 if (!cnf) { 03849 int too_early = 0; 03850 03851 cnf = find_conf_realtime(chan, confno, 1, dynamic, 03852 the_pin, sizeof(the_pin), 1, &confflags,&too_early); 03853 if (rt_schedule && too_early) 03854 allowretry = 0; 03855 } 03856 03857 if (!cnf) { 03858 if (allowretry) { 03859 confno[0] = '\0'; 03860 res = ast_streamfile(chan, "conf-invalid", chan->language); 03861 if (!res) 03862 ast_waitstream(chan, ""); 03863 res = -1; 03864 } 03865 } else { 03866 if ((!ast_strlen_zero(cnf->pin) && 03867 !ast_test_flag(&confflags, CONFFLAG_ADMIN)) || 03868 (!ast_strlen_zero(cnf->pinadmin) && 03869 ast_test_flag(&confflags, CONFFLAG_ADMIN))) { 03870 char pin[MAX_PIN] = ""; 03871 int j; 03872 03873 /* Allow the pin to be retried up to 3 times */ 03874 for (j = 0; j < 3; j++) { 03875 if (*the_pin && (always_prompt == 0)) { 03876 ast_copy_string(pin, the_pin, sizeof(pin)); 03877 res = 0; 03878 } else { 03879 /* Prompt user for pin if pin is required */ 03880 res = ast_app_getdata(chan, "conf-getpin", pin + strlen(pin), sizeof(pin) - 1 - strlen(pin), 0); 03881 } 03882 if (res >= 0) { 03883 if (!strcasecmp(pin, cnf->pin) || 03884 (!ast_strlen_zero(cnf->pinadmin) && 03885 !strcasecmp(pin, cnf->pinadmin))) { 03886 /* Pin correct */ 03887 allowretry = 0; 03888 if (!ast_strlen_zero(cnf->pinadmin) && !strcasecmp(pin, cnf->pinadmin)) { 03889 if (!ast_strlen_zero(cnf->adminopts)) { 03890 char *opts = ast_strdupa(cnf->adminopts); 03891 ast_app_parse_options(meetme_opts, &confflags, optargs, opts); 03892 } 03893 } else { 03894 if (!ast_strlen_zero(cnf->useropts)) { 03895 char *opts = ast_strdupa(cnf->useropts); 03896 ast_app_parse_options(meetme_opts, &confflags, optargs, opts); 03897 } 03898 } 03899 /* Run the conference */ 03900 ast_verb(4, "Starting recording of MeetMe Conference %s into file %s.%s.\n", cnf->confno, cnf->recordingfilename, cnf->recordingformat); 03901 res = conf_run(chan, cnf, confflags.flags, optargs); 03902 break; 03903 } else { 03904 /* Pin invalid */ 03905 if (!ast_streamfile(chan, "conf-invalidpin", chan->language)) { 03906 res = ast_waitstream(chan, AST_DIGIT_ANY); 03907 ast_stopstream(chan); 03908 } else { 03909 ast_log(LOG_WARNING, "Couldn't play invalid pin msg!\n"); 03910 break; 03911 } 03912 if (res < 0) 03913 break; 03914 pin[0] = res; 03915 pin[1] = '\0'; 03916 res = -1; 03917 if (allowretry) 03918 confno[0] = '\0'; 03919 } 03920 } else { 03921 /* failed when getting the pin */ 03922 res = -1; 03923 allowretry = 0; 03924 /* see if we need to get rid of the conference */ 03925 break; 03926 } 03927 03928 /* Don't retry pin with a static pin */ 03929 if (*the_pin && (always_prompt == 0)) { 03930 break; 03931 } 03932 } 03933 } else { 03934 /* No pin required */ 03935 allowretry = 0; 03936 03937 /* Run the conference */ 03938 res = conf_run(chan, cnf, confflags.flags, optargs); 03939 } 03940 dispose_conf(cnf); 03941 cnf = NULL; 03942 } 03943 } 03944 } while (allowretry); 03945 03946 if (cnf) 03947 dispose_conf(cnf); 03948 03949 return res; 03950 }
| static void conf_flush | ( | int | fd, | |
| struct ast_channel * | chan | |||
| ) | [static] |
Definition at line 1617 of file app_meetme.c.
References ast_frfree, ast_log(), ast_read(), ast_waitfor(), f, and LOG_WARNING.
Referenced by conf_run().
01618 { 01619 int x; 01620 01621 /* read any frames that may be waiting on the channel 01622 and throw them away 01623 */ 01624 if (chan) { 01625 struct ast_frame *f; 01626 01627 /* when no frames are available, this will wait 01628 for 1 millisecond maximum 01629 */ 01630 while (ast_waitfor(chan, 1)) { 01631 f = ast_read(chan); 01632 if (f) 01633 ast_frfree(f); 01634 else /* channel was hung up or something else happened */ 01635 break; 01636 } 01637 } 01638 01639 /* flush any data sitting in the pseudo channel */ 01640 x = DAHDI_FLUSH_ALL; 01641 if (ioctl(fd, DAHDI_FLUSH, &x)) 01642 ast_log(LOG_WARNING, "Error flushing channel\n"); 01643 01644 }
| static int conf_free | ( | struct ast_conference * | conf | ) | [static] |
Definition at line 1648 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().
01649 { 01650 int x; 01651 struct announce_listitem *item; 01652 01653 AST_LIST_REMOVE(&confs, conf, list); 01654 manager_event(EVENT_FLAG_CALL, "MeetmeEnd", "Meetme: %s\r\n", conf->confno); 01655 01656 if (conf->recording == MEETME_RECORD_ACTIVE) { 01657 conf->recording = MEETME_RECORD_TERMINATE; 01658 AST_LIST_UNLOCK(&confs); 01659 while (1) { 01660 usleep(1); 01661 AST_LIST_LOCK(&confs); 01662 if (conf->recording == MEETME_RECORD_OFF) 01663 break; 01664 AST_LIST_UNLOCK(&confs); 01665 } 01666 } 01667 01668 for (x = 0; x < AST_FRAME_BITS; x++) { 01669 if (conf->transframe[x]) 01670 ast_frfree(conf->transframe[x]); 01671 if (conf->transpath[x]) 01672 ast_translator_free_path(conf->transpath[x]); 01673 } 01674 if (conf->announcethread != AST_PTHREADT_NULL) { 01675 ast_mutex_lock(&conf->announcelistlock); 01676 conf->announcethread_stop = 1; 01677 ast_softhangup(conf->chan, AST_SOFTHANGUP_EXPLICIT); 01678 ast_cond_signal(&conf->announcelist_addition); 01679 ast_mutex_unlock(&conf->announcelistlock); 01680 pthread_join(conf->announcethread, NULL); 01681 01682 while ((item = AST_LIST_REMOVE_HEAD(&conf->announcelist, entry))) { 01683 ast_filedelete(item->namerecloc, NULL); 01684 ao2_ref(item, -1); 01685 } 01686 ast_mutex_destroy(&conf->announcelistlock); 01687 } 01688 if (conf->origframe) 01689 ast_frfree(conf->origframe); 01690 if (conf->lchan) 01691 ast_hangup(conf->lchan); 01692 if (conf->chan) 01693 ast_hangup(conf->chan); 01694 if (conf->fd >= 0) 01695 close(conf->fd); 01696 if (conf->recordingfilename) { 01697 ast_free(conf->recordingfilename); 01698 } 01699 if (conf->recordingformat) { 01700 ast_free(conf->recordingformat); 01701 } 01702 ast_mutex_destroy(&conf->playlock); 01703 ast_mutex_destroy(&conf->listenlock); 01704 ast_mutex_destroy(&conf->recordthreadlock); 01705 ast_mutex_destroy(&conf->announcethreadlock); 01706 ast_free(conf); 01707 01708 return 0; 01709 }
| static void conf_play | ( | struct ast_channel * | chan, | |
| struct ast_conference * | conf, | |||
| enum entrance_sound | sound | |||
| ) | [static] |
Definition at line 1013 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().
01014 { 01015 unsigned char *data; 01016 int len; 01017 int res = -1; 01018 01019 if (!ast_check_hangup(chan)) 01020 res = ast_autoservice_start(chan); 01021 01022 AST_LIST_LOCK(&confs); 01023 01024 switch(sound) { 01025 case ENTER: 01026 data = enter; 01027 len = sizeof(enter); 01028 break; 01029 case LEAVE: 01030 data = leave; 01031 len = sizeof(leave); 01032 break; 01033 default: 01034 data = NULL; 01035 len = 0; 01036 } 01037 if (data) { 01038 careful_write(conf->fd, data, len, 1); 01039 } 01040 01041 AST_LIST_UNLOCK(&confs); 01042 01043 if (!res) 01044 ast_autoservice_stop(chan); 01045 }
| static void conf_queue_dtmf | ( | const struct ast_conference * | conf, | |
| const struct ast_conf_user * | sender, | |||
| struct ast_frame * | f | |||
| ) | [static] |
Definition at line 1711 of file app_meetme.c.
References AST_LIST_TRAVERSE, ast_log(), ast_write(), ast_conf_user::chan, ast_conf_user::list, LOG_WARNING, ast_channel::name, and ast_conference::userlist.
Referenced by conf_run().
01713 { 01714 struct ast_conf_user *user; 01715 01716 AST_LIST_TRAVERSE(&conf->userlist, user, list) { 01717 if (user == sender) 01718 continue; 01719 if (ast_write(user->chan, f) < 0) 01720 ast_log(LOG_WARNING, "Error writing frame to channel %s\n", user->chan->name); 01721 } 01722 }
| static int conf_run | ( | struct ast_channel * | chan, | |
| struct ast_conference * | conf, | |||
| int | confflags, | |||
| char * | optargs[] | |||
| ) | [static] |
Definition at line 1998 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_load_realtime(), ast_localtime(), ast_log(), AST_MAX_CONTEXT, AST_MAX_EXTENSION, ast_mkdir(), ast_mktime(), ast_moh_start(), ast_moh_stop(), ast_mutex_init(), ast_mutex_lock(), ast_mutex_unlock(), ast_null_frame, AST_OPTION_TONE_VERIFY, ast_play_and_record(), ast_pthread_create_background, ast_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_streamfile(), ast_strftime(), ast_strlen_zero(), ast_strptime(), ast_translate(), ast_translator_build_path(), ast_tvadd(), ast_tvdiff_ms(), ast_tvnow(), ast_tvsub(), ast_tvzero(), ast_update_realtime(), ast_variables_destroy(), ast_verb, ast_verbose, 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, DATE_FORMAT, 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::frame_list, ast_frame::frametype, ast_conf_user::jointime, ast_conf_user::kicktime, announce_listitem::language, ast_channel::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, ast_variable::name, ast_channel::name, announce_listitem::namerecloc, ast_conf_user::namerecloc, ast_variable::next, 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, rt_extend_conf(), S_OR, ast_frame::samples, sec, set_talk_volume(), set_user_talking(), SLA_EVENT_HOLD, sla_queue_event_conf(), ast_conf_user::start_time, 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_channel::uniqueid, ast_conf_user::user_no, ast_conf_user::userflags, ast_conference::userlist, ast_conference::users, ast_variable::value, 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().
01999 { 02000 struct ast_conf_user *user = NULL; 02001 struct ast_conf_user *usr = NULL; 02002 int fd; 02003 struct dahdi_confinfo dahdic, dahdic_empty; 02004 struct ast_frame *f; 02005 struct ast_channel *c; 02006 struct ast_frame fr; 02007 int outfd; 02008 int ms; 02009 int nfds; 02010 int res; 02011 int retrydahdi; 02012 int origfd; 02013 int musiconhold = 0, mohtempstopped = 0; 02014 int firstpass = 0; 02015 int lastmarked = 0; 02016 int currentmarked = 0; 02017 int ret = -1; 02018 int x; 02019 int menu_active = 0; 02020 int talkreq_manager = 0; 02021 int using_pseudo = 0; 02022 int duration = 20; 02023 int hr, min, sec; 02024 int sent_event = 0; 02025 int checked = 0; 02026 int announcement_played = 0; 02027 struct timeval now; 02028 struct ast_dsp *dsp = NULL; 02029 struct ast_app *agi_app; 02030 char *agifile; 02031 const char *agifiledefault = "conf-background.agi", *tmpvar; 02032 char meetmesecs[30] = ""; 02033 char exitcontext[AST_MAX_CONTEXT] = ""; 02034 char recordingtmp[AST_MAX_EXTENSION] = ""; 02035 char members[10] = ""; 02036 int dtmf, opt_waitmarked_timeout = 0; 02037 time_t timeout = 0; 02038 struct dahdi_bufferinfo bi; 02039 char __buf[CONF_SIZE + AST_FRIENDLY_OFFSET]; 02040 char *buf = __buf + AST_FRIENDLY_OFFSET; 02041 char *exitkeys = NULL; 02042 unsigned int calldurationlimit = 0; 02043 long timelimit = 0; 02044 long play_warning = 0; 02045 long warning_freq = 0; 02046 const char *warning_sound = NULL; 02047 const char *end_sound = NULL; 02048 char *parse; 02049 long time_left_ms = 0; 02050 struct timeval nexteventts = { 0, }; 02051 int to; 02052 int setusercount = 0; 02053 int confsilence = 0, totalsilence = 0; 02054 02055 if (!(user = ast_calloc(1, sizeof(*user)))) 02056 return ret; 02057 02058 /* Possible timeout waiting for marked user */ 02059 if ((confflags & CONFFLAG_WAITMARKED) && 02060 !ast_strlen_zero(optargs[OPT_ARG_WAITMARKED]) && 02061 (sscanf(optargs[OPT_ARG_WAITMARKED], "%30d", &opt_waitmarked_timeout) == 1) && 02062 (opt_waitmarked_timeout > 0)) { 02063 timeout = time(NULL) + opt_waitmarked_timeout; 02064 } 02065 02066 if ((confflags & CONFFLAG_DURATION_STOP) && !ast_strlen_zero(optargs[OPT_ARG_DURATION_STOP])) { 02067 calldurationlimit = atoi(optargs[OPT_ARG_DURATION_STOP]); 02068 ast_verb(3, "Setting call duration limit to %d seconds.\n", calldurationlimit); 02069 } 02070 02071 if ((confflags & CONFFLAG_DURATION_LIMIT) && !ast_strlen_zero(optargs[OPT_ARG_DURATION_LIMIT])) { 02072 char *limit_str, *warning_str, *warnfreq_str; 02073 const char *var; 02074 02075 parse = optargs[OPT_ARG_DURATION_LIMIT]; 02076 limit_str = strsep(&parse, ":"); 02077 warning_str = strsep(&parse, ":"); 02078 warnfreq_str = parse; 02079 02080 timelimit = atol(limit_str); 02081 if (warning_str) 02082 play_warning = atol(warning_str); 02083 if (warnfreq_str) 02084 warning_freq = atol(warnfreq_str); 02085 02086 if (!timelimit) { 02087 timelimit = play_warning = warning_freq = 0; 02088 warning_sound = NULL; 02089 } else if (play_warning > timelimit) { 02090 if (!warning_freq) { 02091 play_warning = 0; 02092 } else { 02093 while (play_warning > timelimit) 02094 play_warning -= warning_freq; 02095 if (play_warning < 1) 02096 play_warning = warning_freq = 0; 02097 } 02098 } 02099 02100 ast_channel_lock(chan); 02101 if ((var = pbx_builtin_getvar_helper(chan, "CONF_LIMIT_WARNING_FILE"))) { 02102 var = ast_strdupa(var); 02103 } 02104 ast_channel_unlock(chan); 02105 02106 warning_sound = var ? var : "timeleft"; 02107 02108 ast_channel_lock(chan); 02109 if ((var = pbx_builtin_getvar_helper(chan, "CONF_LIMIT_TIMEOUT_FILE"))) { 02110 var = ast_strdupa(var); 02111 } 02112 ast_channel_unlock(chan); 02113 02114 end_sound = var ? var : NULL; 02115 02116 /* undo effect of S(x) in case they are both used */ 02117 calldurationlimit = 0; 02118 /* more efficient do it like S(x) does since no advanced opts */ 02119 if (!play_warning && !end_sound && timelimit) { 02120 calldurationlimit = timelimit / 1000; 02121 timelimit = play_warning = warning_freq = 0; 02122 } else { 02123 ast_debug(2, "Limit Data for this call:\n"); 02124 ast_debug(2, "- timelimit = %ld\n", timelimit); 02125 ast_debug(2, "- play_warning = %ld\n", play_warning); 02126 ast_debug(2, "- warning_freq = %ld\n", warning_freq); 02127 ast_debug(2, "- warning_sound = %s\n", warning_sound ? warning_sound : "UNDEF"); 02128 ast_debug(2, "- end_sound = %s\n", end_sound ? end_sound : "UNDEF"); 02129 } 02130 } 02131 02132 /* Get exit keys */ 02133 if ((confflags & CONFFLAG_KEYEXIT)) { 02134 if (!ast_strlen_zero(optargs[OPT_ARG_EXITKEYS])) 02135 exitkeys = ast_strdupa(optargs[OPT_ARG_EXITKEYS]); 02136 else 02137 exitkeys = ast_strdupa("#"); /* Default */ 02138 } 02139 02140 if (confflags & CONFFLAG_RECORDCONF) { 02141 if (!conf->recordingfilename) { 02142 const char *var; 02143 ast_channel_lock(chan); 02144 if ((var = pbx_builtin_getvar_helper(chan, "MEETME_RECORDINGFILE"))) { 02145 conf->recordingfilename = ast_strdup(var); 02146 } 02147 if ((var = pbx_builtin_getvar_helper(chan, "MEETME_RECORDINGFORMAT"))) { 02148 conf->recordingformat = ast_strdup(var); 02149 } 02150 ast_channel_unlock(chan); 02151 if (!conf->recordingfilename) { 02152 snprintf(recordingtmp, sizeof(recordingtmp), "meetme-conf-rec-%s-%s", conf->confno, chan->uniqueid); 02153 conf->recordingfilename = ast_strdup(recordingtmp); 02154 } 02155 if (!conf->recordingformat) { 02156 conf->recordingformat = ast_strdup("wav"); 02157 } 02158 ast_verb(4, "Starting recording of MeetMe Conference %s into file %s.%s.\n", 02159 conf->confno, conf->recordingfilename, conf->recordingformat); 02160 } 02161 } 02162 02163 ast_mutex_lock(&conf->recordthreadlock); 02164 if ((conf->recordthread == AST_PTHREADT_NULL) && (confflags & CONFFLAG_RECORDCONF) && ((conf->lchan = ast_request("DAHDI", AST_FORMAT_SLINEAR, "pseudo", NULL)))) { 02165 ast_set_read_format(conf->lchan, AST_FORMAT_SLINEAR); 02166 ast_set_write_format(conf->lchan, AST_FORMAT_SLINEAR); 02167 dahdic.chan = 0; 02168 dahdic.confno = conf->dahdiconf; 02169 dahdic.confmode = DAHDI_CONF_CONFANN | DAHDI_CONF_CONFANNMON; 02170 if (ioctl(conf->lchan->fds[0], DAHDI_SETCONF, &dahdic)) { 02171 ast_log(LOG_WARNING, "Error starting listen channel\n"); 02172 ast_hangup(conf->lchan); 02173 conf->lchan = NULL; 02174 } else { 02175 ast_pthread_create_detached_background(&conf->recordthread, NULL, recordthread, conf); 02176 } 02177 } 02178 ast_mutex_unlock(&conf->recordthreadlock); 02179 02180 ast_mutex_lock(&conf->announcethreadlock); 02181 if ((conf->announcethread == AST_PTHREADT_NULL) && !(confflags & CONFFLAG_QUIET) && ((confflags & CONFFLAG_INTROUSER) || (confflags & CONFFLAG_INTROUSERNOREVIEW))) { 02182 ast_mutex_init(&conf->announcelistlock); 02183 AST_LIST_HEAD_INIT_NOLOCK(&conf->announcelist); 02184 ast_pthread_create_background(&conf->announcethread, NULL, announce_thread, conf); 02185 } 02186 ast_mutex_unlock(&conf->announcethreadlock); 02187 02188 time(&user->jointime); 02189 02190 user->timelimit = timelimit; 02191 user->play_warning = play_warning; 02192 user->warning_freq = warning_freq; 02193 user->warning_sound = warning_sound; 02194 user->end_sound = end_sound; 02195 02196 if (calldurationlimit > 0) { 02197 time(&user->kicktime); 02198 user->kicktime = user->kicktime + calldurationlimit; 02199 } 02200 02201 if (ast_tvzero(user->start_time)) 02202 user->start_time = ast_tvnow(); 02203 time_left_ms = user->timelimit; 02204 02205 if (user->timelimit) { 02206 nexteventts = ast_tvadd(user->start_time, ast_samp2tv(user->timelimit, 1000)); 02207 nexteventts = ast_tvsub(nexteventts, ast_samp2tv(user->play_warning, 1000)); 02208 } 02209 02210 if (conf->locked && (!(confflags & CONFFLAG_ADMIN))) { 02211 /* Sorry, but this conference is locked! */ 02212 if (!ast_streamfile(chan, "conf-locked", chan->language)) 02213 ast_waitstream(chan, ""); 02214 goto outrun; 02215 } 02216 02217 ast_mutex_lock(&conf->playlock); 02218 02219 if (AST_LIST_EMPTY(&conf->userlist)) 02220 user->user_no = 1; 02221 else 02222 user->user_no = AST_LIST_LAST(&conf->userlist)->user_no + 1; 02223 02224 if (rt_schedule && conf->maxusers) 02225 if (conf->users >= conf->maxusers) { 02226 /* Sorry, but this confernce has reached the participant limit! */ 02227 if (!ast_streamfile(chan, "conf-full", chan->language)) 02228 ast_waitstream(chan, ""); 02229 ast_mutex_unlock(&conf->playlock); 02230 user->user_no = 0; 02231 goto outrun; 02232 } 02233 02234 AST_LIST_INSERT_TAIL(&conf->userlist, user, list); 02235 02236 user->chan = chan; 02237 user->userflags = confflags; 02238 user->adminflags = (confflags & CONFFLAG_STARTMUTED) ? ADMINFLAG_SELFMUTED : 0; 02239 user->talking = -1; 02240 02241 ast_mutex_unlock(&conf->playlock); 02242 02243 if (!(confflags & CONFFLAG_QUIET) && ((confflags & CONFFLAG_INTROUSER) || (confflags & CONFFLAG_INTROUSERNOREVIEW))) { 02244 char destdir[PATH_MAX]; 02245 02246 snprintf(destdir, sizeof(destdir), "%s/meetme", ast_config_AST_SPOOL_DIR); 02247 02248 if (ast_mkdir(destdir, 0777) != 0) { 02249 ast_log(LOG_WARNING, "mkdir '%s' failed: %s\n", destdir, strerror(errno)); 02250 goto outrun; 02251 } 02252 02253 snprintf(user->namerecloc, sizeof(user->namerecloc), 02254 "%s/meetme-username-%s-%d", destdir, 02255 conf->confno, user->user_no); 02256 if (confflags & CONFFLAG_INTROUSERNOREVIEW) 02257 res = ast_play_and_record(chan, "vm-rec-name", user->namerecloc, 10, "sln", &duration, ast_dsp_get_threshold_from_settings(THRESHOLD_SILENCE), 0, NULL); 02258 else 02259 res = ast_record_review(chan, "vm-rec-name", user->namerecloc, 10, "sln", &duration, NULL); 02260 if (res == -1) 02261 goto outrun; 02262 } 02263 02264 ast_mutex_lock(&conf->playlock); 02265 02266 if (confflags & CONFFLAG_MARKEDUSER) 02267 conf->markedusers++; 02268 conf->users++; 02269 if (rt_log_members) { 02270 /* Update table */ 02271 snprintf(members, sizeof(members), "%d", conf->users); 02272 ast_realtime_require_field("meetme", 02273 "confno", strlen(conf->confno) > 7 ? RQ_UINTEGER4 : strlen(conf->confno) > 4 ? RQ_UINTEGER3 : RQ_UINTEGER2, strlen(conf->confno), 02274 "members", RQ_UINTEGER1, strlen(members), 02275 NULL); 02276 ast_update_realtime("meetme", "confno", conf->confno, "members", members, NULL); 02277 } 02278 setusercount = 1; 02279 02280 /* This device changed state now - if this is the first user */ 02281 if (conf->users == 1) 02282 ast_devstate_changed(AST_DEVICE_INUSE, "meetme:%s", conf->confno); 02283 02284 ast_mutex_unlock(&conf->playlock); 02285 02286 /* return the unique ID of the conference */ 02287 pbx_builtin_setvar_helper(chan, "MEETMEUNIQUEID", conf->uniqueid); 02288 02289 if (confflags & CONFFLAG_EXIT_CONTEXT) { 02290 ast_channel_lock(chan); 02291 if ((tmpvar = pbx_builtin_getvar_helper(chan, "MEETME_EXIT_CONTEXT"))) { 02292 ast_copy_string(exitcontext, tmpvar, sizeof(exitcontext)); 02293 } else if (!ast_strlen_zero(chan->macrocontext)) { 02294 ast_copy_string(exitcontext, chan->macrocontext, sizeof(exitcontext)); 02295 } else { 02296 ast_copy_string(exitcontext, chan->context, sizeof(exitcontext)); 02297 } 02298 ast_channel_unlock(chan); 02299 } 02300 02301 if (!(confflags & (CONFFLAG_QUIET | CONFFLAG_NOONLYPERSON))) { 02302 if (conf->users == 1 && !(confflags & CONFFLAG_WAITMARKED)) 02303 if (!ast_streamfile(chan, "conf-onlyperson", chan->language)) 02304 ast_waitstream(chan, ""); 02305 if ((confflags & CONFFLAG_WAITMARKED) && conf->markedusers == 0) 02306 if (!ast_streamfile(chan, "conf-waitforleader", chan->language)) 02307 ast_waitstream(chan, ""); 02308 } 02309 02310 if (!(confflags & CONFFLAG_QUIET) && (confflags & CONFFLAG_ANNOUNCEUSERCOUNT) && conf->users > 1) { 02311 int keepplaying = 1; 02312 02313 if (conf->users == 2) { 02314 if (!ast_streamfile(chan, "conf-onlyone", chan->language)) { 02315 res = ast_waitstream(chan, AST_DIGIT_ANY); 02316 ast_stopstream(chan); 02317 if (res > 0) 02318 keepplaying = 0; 02319 else if (res == -1) 02320 goto outrun; 02321 } 02322 } else { 02323 if (!ast_streamfile(chan, "conf-thereare", chan->language)) { 02324 res = ast_waitstream(chan, AST_DIGIT_ANY); 02325 ast_stopstream(chan); 02326 if (res > 0) 02327 keepplaying = 0; 02328 else if (res == -1) 02329 goto outrun; 02330 } 02331 if (keepplaying) { 02332 res = ast_say_number(chan, conf->users - 1, AST_DIGIT_ANY, chan->language, (char *) NULL); 02333 if (res > 0) 02334 keepplaying = 0; 02335 else if (res == -1) 02336 goto outrun; 02337 } 02338 if (keepplaying && !ast_streamfile(chan, "conf-otherinparty", chan->language)) { 02339 res = ast_waitstream(chan, AST_DIGIT_ANY); 02340 ast_stopstream(chan); 02341 if (res > 0) 02342 keepplaying = 0; 02343 else if (res == -1) 02344 goto outrun; 02345 } 02346 } 02347 } 02348 02349 if (!(confflags & CONFFLAG_NO_AUDIO_UNTIL_UP)) { 02350 /* We're leaving this alone until the state gets changed to up */ 02351 ast_indicate(chan, -1); 02352 } 02353 02354 if (ast_set_write_format(chan, AST_FORMAT_SLINEAR) < 0) { 02355 ast_log(LOG_WARNING, "Unable to set '%s' to write linear mode\n", chan->name); 02356 goto outrun; 02357 } 02358 02359 if (ast_set_read_format(chan, AST_FORMAT_SLINEAR) < 0) { 02360 ast_log(LOG_WARNING, "Unable to set '%s' to read linear mode\n", chan->name); 02361 goto outrun; 02362 } 02363 02364 retrydahdi = (strcasecmp(chan->tech->type, "DAHDI") || (chan->audiohooks || chan->monitor) ? 1 : 0); 02365 user->dahdichannel = !retrydahdi; 02366 02367 dahdiretry: 02368 origfd = chan->fds[0]; 02369 if (retrydahdi) { 02370 /* open pseudo in non-blocking mode */ 02371 fd = open("/dev/dahdi/pseudo", O_RDWR | O_NONBLOCK); 02372 if (fd < 0) { 02373 ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno)); 02374 goto outrun; 02375 } 02376 using_pseudo = 1; 02377 /* Setup buffering information */ 02378 memset(&bi, 0, sizeof(bi)); 02379 bi.bufsize = CONF_SIZE / 2; 02380 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE; 02381 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE; 02382 bi.numbufs = audio_buffers; 02383 if (ioctl(fd, DAHDI_SET_BUFINFO, &bi)) { 02384 ast_log(LOG_WARNING, "Unable to set buffering information: %s\n", strerror(errno)); 02385 close(fd); 02386 goto outrun; 02387 } 02388 x = 1; 02389 if (ioctl(fd, DAHDI_SETLINEAR, &x)) { 02390 ast_log(LOG_WARNING, "Unable to set linear mode: %s\n", strerror(errno)); 02391 close(fd); 02392 goto outrun; 02393 } 02394 nfds = 1; 02395 } else { 02396 /* XXX Make sure we're not running on a pseudo channel XXX */ 02397 fd = chan->fds[0]; 02398 nfds = 0; 02399 } 02400 memset(&dahdic, 0, sizeof(dahdic)); 02401 memset(&dahdic_empty, 0, sizeof(dahdic_empty)); 02402 /* Check to see if we're in a conference... */ 02403 dahdic.chan = 0; 02404 if (ioctl(fd, DAHDI_GETCONF, &dahdic)) { 02405 ast_log(LOG_WARNING, "Error getting conference\n"); 02406 close(fd); 02407 goto outrun; 02408 } 02409 if (dahdic.confmode) { 02410 /* Whoa, already in a conference... Retry... */ 02411 if (!retrydahdi) { 02412 ast_debug(1, "DAHDI channel is in a conference already, retrying with pseudo\n"); 02413 retrydahdi = 1; 02414 goto dahdiretry; 02415 } 02416 } 02417 memset(&dahdic, 0, sizeof(dahdic)); 02418 /* Add us to the conference */ 02419 dahdic.chan = 0; 02420 dahdic.confno = conf->dahdiconf; 02421 02422 if (!(confflags & CONFFLAG_QUIET) && ((confflags & CONFFLAG_INTROUSER) || (confflags & CONFFLAG_INTROUSERNOREVIEW)) && conf->users > 1) { 02423 struct announce_listitem *item; 02424 if (!(item = ao2_alloc(sizeof(*item), NULL))) 02425 return -1; 02426 ast_copy_string(item->namerecloc, user->namerecloc, sizeof(item->namerecloc)); 02427 ast_copy_string(item->language, chan->language, sizeof(item->language)); 02428 item->confchan = conf->chan; 02429 item->confusers = conf->users; 02430 item->announcetype = CONF_HASJOIN; 02431 ast_mutex_lock(&conf->announcelistlock); 02432 ao2_ref(item, +1); /* add one more so we can determine when announce_thread is done playing it */ 02433 AST_LIST_INSERT_TAIL(&conf->announcelist, item, entry); 02434 ast_cond_signal(&conf->announcelist_addition); 02435 ast_mutex_unlock(&conf->announcelistlock); 02436 02437 while (!ast_check_hangup(conf->chan) && ao2_ref(item, 0) == 2 && !ast_safe_sleep(chan, 1000)) { 02438 ; 02439 } 02440 ao2_ref(item, -1); 02441 } 02442 02443 if (confflags & CONFFLAG_WAITMARKED && !conf->markedusers) 02444 dahdic.confmode = DAHDI_CONF_CONF; 02445 else if (confflags & CONFFLAG_MONITOR) 02446 dahdic.confmode = DAHDI_CONF_CONFMON | DAHDI_CONF_LISTENER; 02447 else if (confflags & CONFFLAG_TALKER) 02448 dahdic.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER; 02449 else 02450 dahdic.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER; 02451 02452 if (ioctl(fd, DAHDI_SETCONF, &dahdic)) { 02453 ast_log(LOG_WARNING, "Error setting conference\n"); 02454 close(fd); 02455 goto outrun; 02456 } 02457 ast_debug(1, "Placed channel %s in DAHDI conf %d\n", chan->name, conf->dahdiconf); 02458 02459 if (!sent_event) { 02460 manager_event(EVENT_FLAG_CALL, "MeetmeJoin", 02461 "Channel: %s\r\n" 02462 "Uniqueid: %s\r\n" 02463 "Meetme: %s\r\n" 02464 "Usernum: %d\r\n" 02465 "CallerIDnum: %s\r\n" 02466 "CallerIDname: %s\r\n", 02467 chan->name, chan->uniqueid, conf->confno, 02468 user->user_no, 02469 S_OR(user->chan->cid.cid_num, "<unknown>"), 02470 S_OR(user->chan->cid.cid_name, "<unknown>") 02471 ); 02472 sent_event = 1; 02473 } 02474 02475 if (!firstpass && !(confflags & CONFFLAG_MONITOR) && !(confflags & CONFFLAG_ADMIN)) { 02476 firstpass = 1; 02477 if (!(confflags & CONFFLAG_QUIET)) 02478 if (!(confflags & CONFFLAG_WAITMARKED) || ((confflags & CONFFLAG_MARKEDUSER) && (conf->markedusers >= 1))) 02479 conf_play(chan, conf, ENTER); 02480 } 02481 02482 conf_flush(fd, chan); 02483 02484 if (!(dsp = ast_dsp_new())) { 02485 ast_log(LOG_WARNING, "Unable to allocate DSP!\n"); 02486 res = -1; 02487 } 02488 02489 if (confflags & CONFFLAG_AGI) { 02490 /* Get name of AGI file to run from $(MEETME_AGI_BACKGROUND) 02491 or use default filename of conf-background.agi */ 02492 02493 ast_channel_lock(chan); 02494 if ((tmpvar = pbx_builtin_getvar_helper(chan, "MEETME_AGI_BACKGROUND"))) { 02495 agifile = ast_strdupa(tmpvar); 02496 } else { 02497 agifile = ast_strdupa(agifiledefault); 02498 } 02499 ast_channel_unlock(chan); 02500 02501 if (user->dahdichannel) { 02502 /* Set CONFMUTE mode on DAHDI channel to mute DTMF tones */ 02503 x = 1; 02504 ast_channel_setoption(chan, AST_OPTION_TONE_VERIFY, &x, sizeof(char), 0); 02505 } 02506 /* Find a pointer to the agi app and execute the script */ 02507 agi_app = pbx_findapp("agi"); 02508 if (agi_app) { 02509 ret = pbx_exec(chan, agi_app, agifile); 02510 } else { 02511 ast_log(LOG_WARNING, "Could not find application (agi)\n"); 02512 ret = -2; 02513 } 02514 if (user->dahdichannel) { 02515 /* Remove CONFMUTE mode on DAHDI channel */ 02516 x = 0; 02517 ast_channel_setoption(chan, AST_OPTION_TONE_VERIFY, &x, sizeof(char), 0); 02518 } 02519 } else { 02520 if (user->dahdichannel && (confflags & CONFFLAG_STARMENU)) { 02521 /* Set CONFMUTE mode on DAHDI channel to mute DTMF tones when the menu is enabled */ 02522 x = 1; 02523 ast_channel_setoption(chan, AST_OPTION_TONE_VERIFY, &x, sizeof(char), 0); 02524 } 02525 for (;;) { 02526 int menu_was_active = 0; 02527 02528 outfd = -1; 02529 ms = -1; 02530 now = ast_tvnow(); 02531 02532 if (rt_schedule && conf->endtime) { 02533 char currenttime[32]; 02534 long localendtime = 0; 02535 int extended = 0; 02536 struct ast_tm tm; 02537 struct ast_variable *var, *origvar; 02538 struct timeval tmp; 02539 02540 if (now.tv_sec % 60 == 0) { 02541 if (!checked) { 02542 ast_localtime(&now, &tm, NULL); 02543 ast_strftime(currenttime, sizeof(currenttime), DATE_FORMAT, &tm); 02544 var = origvar = ast_load_realtime("meetme", "confno", 02545 conf->confno, "starttime <=", currenttime, 02546 "endtime >=", currenttime, NULL); 02547 02548 for ( ; var; var = var->next) { 02549 if (!strcasecmp(var->name, "endtime")) { 02550 struct ast_tm endtime_tm; 02551 ast_strptime(var->value, "%Y-%m-%d %H:%M:%S", &endtime_tm); 02552 tmp = ast_mktime(&endtime_tm, NULL); 02553 localendtime = tmp.tv_sec; 02554 } 02555 } 02556 ast_variables_destroy(origvar); 02557 02558 /* A conference can be extended from the 02559 Admin/User menu or by an external source */ 02560 if (localendtime > conf->endtime){ 02561 conf->endtime = localendtime; 02562 extended = 1; 02563 } 02564 02565 if (conf->endtime && (now.tv_sec >= conf->endtime)) { 02566 ast_verbose("Quitting time...\n"); 02567 goto outrun; 02568 } 02569 02570 if (!announcement_played && conf->endalert) { 02571 if (now.tv_sec + conf->endalert >= conf->endtime) { 02572 if (!ast_streamfile(chan, "conf-will-end-in", chan->language)) 02573 ast_waitstream(chan, ""); 02574 ast_say_digits(chan, (conf->endtime - now.tv_sec) / 60, "", chan->language); 02575 if (!ast_streamfile(chan, "minutes", chan->language)) 02576 ast_waitstream(chan, ""); 02577 announcement_played = 1; 02578 } 02579 } 02580 02581 if (extended) { 02582 announcement_played = 0; 02583 } 02584 02585 checked = 1; 02586 } 02587 } else { 02588 checked = 0; 02589 } 02590 } 02591 02592 if (user->kicktime && (user->kicktime <= now.tv_sec)) { 02593 break; 02594 } 02595 02596 to = -1; 02597 if (user->timelimit) { 02598 int minutes = 0, seconds = 0, remain = 0; 02599 02600 to = ast_tvdiff_ms(nexteventts, now); 02601 if (to < 0) { 02602 to = 0; 02603 } 02604 time_left_ms = user->timelimit - ast_tvdiff_ms(now, user->start_time); 02605 if (time_left_ms < to) { 02606 to = time_left_ms; 02607 } 02608 02609 if (time_left_ms <= 0) { 02610 if (user->end_sound) { 02611 res = ast_streamfile(chan, user->end_sound, chan->language); 02612 res = ast_waitstream(chan, ""); 02613 } 02614 break; 02615 } 02616 02617 if (!to) { 02618 if (time_left_ms >= 5000) { 02619 02620 remain = (time_left_ms + 500) / 1000; 02621 if (remain / 60 >= 1) { 02622 minutes = remain / 60; 02623 seconds = remain % 60; 02624 } else { 02625 seconds = remain; 02626 } 02627 02628 /* force the time left to round up if appropriate */ 02629 if (user->warning_sound && user->play_warning) { 02630 if (!strcmp(user->warning_sound, "timeleft")) { 02631 02632 res = ast_streamfile(chan, "vm-youhave", chan->language); 02633 res = ast_waitstream(chan, ""); 02634 if (minutes) { 02635 res = ast_say_number(chan, minutes, AST_DIGIT_ANY, chan->language, (char *) NULL); 02636 res = ast_streamfile(chan, "queue-minutes", chan->language); 02637 res = ast_waitstream(chan, ""); 02638 } 02639 if (seconds) { 02640 res = ast_say_number(chan, seconds, AST_DIGIT_ANY, chan->language, (char *) NULL); 02641 res = ast_streamfile(chan, "queue-seconds", chan->language); 02642 res = ast_waitstream(chan, ""); 02643 } 02644 } else { 02645 res = ast_streamfile(chan, user->warning_sound, chan->language); 02646 res = ast_waitstream(chan, ""); 02647 } 02648 } 02649 } 02650 if (user->warning_freq) { 02651 nexteventts = ast_tvadd(nexteventts, ast_samp2tv(user->warning_freq, 1000)); 02652 } else { 02653 nexteventts = ast_tvadd(user->start_time, ast_samp2tv(user->timelimit, 1000)); 02654 } 02655 } 02656 } 02657 02658 now = ast_tvnow(); 02659 if (timeout && now.tv_sec >= timeout) { 02660 break; 02661 } 02662 02663 /* if we have just exited from the menu, and the user had a channel-driver 02664 volume adjustment, restore it 02665 */ 02666 if (!menu_active && menu_was_active && user->listen.desired && !user->listen.actual) { 02667 set_talk_volume(user, user->listen.desired); 02668 } 02669 02670 menu_was_active = menu_active; 02671 02672 currentmarked = conf->markedusers; 02673 if (!(confflags & CONFFLAG_QUIET) && 02674 (confflags & CONFFLAG_MARKEDUSER) && 02675 (confflags & CONFFLAG_WAITMARKED) && 02676 lastmarked == 0) { 02677 if (currentmarked == 1 && conf->users > 1) { 02678 ast_say_number(chan, conf->users - 1, AST_DIGIT_ANY, chan->language, (char *) NULL); 02679 if (conf->users - 1 == 1) { 02680 if (!ast_streamfile(chan, "conf-userwilljoin", chan->language)) { 02681 ast_waitstream(chan, ""); 02682 } 02683 } else { 02684 if (!ast_streamfile(chan, "conf-userswilljoin", chan->language)) { 02685 ast_waitstream(chan, ""); 02686 } 02687 } 02688 } 02689 if (conf->users == 1 && ! (confflags & CONFFLAG_MARKEDUSER)) { 02690 if (!ast_streamfile(chan, "conf-onlyperson", chan->language)) { 02691 ast_waitstream(chan, ""); 02692 } 02693 } 02694 } 02695 02696 /* Update the struct with the actual confflags */ 02697 user->userflags = confflags; 02698 02699 if (confflags & CONFFLAG_WAITMARKED) { 02700 if (currentmarked == 0) { 02701 if (lastmarked != 0) { 02702 if (!(confflags & CONFFLAG_QUIET)) { 02703 if (!ast_streamfile(chan, "conf-leaderhasleft", chan->language)) { 02704 ast_waitstream(chan, ""); 02705 } 02706 } 02707 if (confflags & CONFFLAG_MARKEDEXIT) { 02708 if (confflags & CONFFLAG_KICK_CONTINUE) { 02709 ret = 0; 02710 } 02711 break; 02712 } else { 02713 dahdic.confmode = DAHDI_CONF_CONF; 02714 if (ioctl(fd, DAHDI_SETCONF, &dahdic)) { 02715 ast_log(LOG_WARNING, "Error setting conference\n"); 02716 close(fd); 02717 goto outrun; 02718 } 02719 } 02720 } 02721 if (!musiconhold && (confflags & CONFFLAG_MOH)) { 02722 conf_start_moh(chan, optargs[OPT_ARG_MOH_CLASS]); 02723 musiconhold = 1; 02724 } 02725 } else if (currentmarked >= 1 && lastmarked == 0) { 02726 /* Marked user entered, so cancel timeout */ 02727 timeout = 0; 02728 if (confflags & CONFFLAG_MONITOR) { 02729 dahdic.confmode = DAHDI_CONF_CONFMON | DAHDI_CONF_LISTENER; 02730 } else if (confflags & CONFFLAG_TALKER) { 02731 dahdic.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER; 02732 } else { 02733 dahdic.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER; 02734 } 02735 if (ioctl(fd, DAHDI_SETCONF, &dahdic)) { 02736 ast_log(LOG_WARNING, "Error setting conference\n"); 02737 close(fd); 02738 goto outrun; 02739 } 02740 if (musiconhold && (confflags & CONFFLAG_MOH)) { 02741 ast_moh_stop(chan); 02742 musiconhold = 0; 02743 } 02744 if (!(confflags & CONFFLAG_QUIET) && !(confflags & CONFFLAG_MARKEDUSER)) { 02745 if (!ast_streamfile(chan, "conf-placeintoconf", chan->language)) { 02746 ast_waitstream(chan, ""); 02747 } 02748 conf_play(chan, conf, ENTER); 02749 } 02750 } 02751 } 02752 02753 /* trying to add moh for single person conf */ 02754 if ((confflags & CONFFLAG_MOH) && !(confflags & CONFFLAG_WAITMARKED)) { 02755 if (conf->users == 1) { 02756 if (!musiconhold) { 02757 conf_start_moh(chan, optargs[OPT_ARG_MOH_CLASS]); 02758 musiconhold = 1; 02759 } 02760 } else { 02761 if (musiconhold) { 02762 ast_moh_stop(chan); 02763 musiconhold = 0; 02764 } 02765 } 02766 } 02767 02768 /* Leave if the last marked user left */ 02769 if (currentmarked == 0 && lastmarked != 0 && (confflags & CONFFLAG_MARKEDEXIT)) { 02770 if (confflags & CONFFLAG_KICK_CONTINUE) { 02771 ret = 0; 02772 } else { 02773 ret = -1; 02774 } 02775 break; 02776 } 02777 02778 /* Check if my modes have changed */ 02779 02780 /* If I should be muted but am still talker, mute me */ 02781 if ((user->adminflags & (ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED)) && (dahdic.confmode & DAHDI_CONF_TALKER)) { 02782 dahdic.confmode ^= DAHDI_CONF_TALKER; 02783 if (ioctl(fd, DAHDI_SETCONF, &dahdic)) { 02784 ast_log(LOG_WARNING, "Error setting conference - Un/Mute \n"); 02785 ret = -1; 02786 break; 02787 } 02788 02789 /* Indicate user is not talking anymore - change him to unmonitored state */ 02790 if ((confflags & (CONFFLAG_MONITORTALKER | CONFFLAG_OPTIMIZETALKER))) { 02791 set_user_talking(chan, conf, user, -1, confflags & CONFFLAG_MONITORTALKER); 02792 } 02793 02794 manager_event(EVENT_FLAG_CALL, "MeetmeMute", 02795 "Channel: %s\r\n" 02796 "Uniqueid: %s\r\n" 02797 "Meetme: %s\r\n" 02798 "Usernum: %i\r\n" 02799 "Status: on\r\n", 02800 chan->name, chan->uniqueid, conf->confno, user->user_no); 02801 } 02802 02803 /* If I should be un-muted but am not talker, un-mute me */ 02804 if (!(user->adminflags & (ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED)) && !(confflags & CONFFLAG_MONITOR) && !(dahdic.confmode & DAHDI_CONF_TALKER)) { 02805 dahdic.confmode |= DAHDI_CONF_TALKER; 02806 if (ioctl(fd, DAHDI_SETCONF, &dahdic)) { 02807 ast_log(LOG_WARNING, "Error setting conference - Un/Mute \n"); 02808 ret = -1; 02809 break; 02810 } 02811 02812 manager_event(EVENT_FLAG_CALL, "MeetmeMute", 02813 "Channel: %s\r\n" 02814 "Uniqueid: %s\r\n" 02815 "Meetme: %s\r\n" 02816 "Usernum: %i\r\n" 02817 "Status: off\r\n", 02818 chan->name, chan->uniqueid, conf->confno, user->user_no); 02819 } 02820 02821 if ((user->adminflags & (ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED)) && 02822 (user->adminflags & ADMINFLAG_T_REQUEST) && !(talkreq_manager)) { 02823 talkreq_manager = 1; 02824 02825 manager_event(EVENT_FLAG_CALL, "MeetmeTalkRequest", 02826 "Channel: %s\r\n" 02827 "Uniqueid: %s\r\n" 02828 "Meetme: %s\r\n" 02829 "Usernum: %i\r\n" 02830 "Status: on\r\n", 02831 chan->name, chan->uniqueid, conf->confno, user->user_no); 02832 } 02833 02834 02835 if (!(user->adminflags & (ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED)) && 02836 !(user->adminflags & ADMINFLAG_T_REQUEST) && (talkreq_manager)) { 02837 talkreq_manager = 0; 02838 manager_event(EVENT_FLAG_CALL, "MeetmeTalkRequest", 02839 "Channel: %s\r\n" 02840 "Uniqueid: %s\r\n" 02841 "Meetme: %s\r\n" 02842 "Usernum: %i\r\n" 02843 "Status: off\r\n", 02844 chan->name, chan->uniqueid, conf->confno, user->user_no); 02845 } 02846 02847 /* If I have been kicked, exit the conference */ 02848 if (user->adminflags & ADMINFLAG_KICKME) { 02849 /* You have been kicked. */ 02850 if (!(confflags & CONFFLAG_QUIET) && 02851 !ast_streamfile(chan, "conf-kicked", chan->language)) { 02852 ast_waitstream(chan, ""); 02853 } 02854 ret = 0; 02855 break; 02856 } 02857 02858 /* Perform an extra hangup check just in case */ 02859 if (ast_check_hangup(chan)) { 02860 break; 02861 } 02862 02863 c = ast_waitfor_nandfds(&chan, 1, &fd, nfds, NULL, &outfd, &ms); 02864 02865 if (c) { 02866 char dtmfstr[2] = ""; 02867 02868 if (c->fds[0] != origfd || (user->dahdichannel && (c->audiohooks || c->monitor))) { 02869 if (using_pseudo) { 02870 /* Kill old pseudo */ 02871 close(fd); 02872 using_pseudo = 0; 02873 } 02874 ast_debug(1, "Ooh, something swapped out under us, starting over\n"); 02875 retrydahdi = (strcasecmp(c->tech->type, "DAHDI") || (c->audiohooks || c->monitor) ? 1 : 0); 02876 user->dahdichannel = !retrydahdi; 02877 goto dahdiretry; 02878 } 02879 if ((confflags & CONFFLAG_MONITOR) || (user->adminflags & (ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED))) { 02880 f = ast_read_noaudio(c); 02881 } else { 02882 f = ast_read(c); 02883 } 02884 if (!f) { 02885 break; 02886 } 02887 if (f->frametype == AST_FRAME_DTMF) { 02888 dtmfstr[0] = f->subclass; 02889 dtmfstr[1] = '\0'; 02890 } 02891 02892 if ((f->frametype == AST_FRAME_VOICE) && (f->subclass == AST_FORMAT_SLINEAR)) { 02893 if (user->talk.actual) { 02894 ast_frame_adjust_volume(f, user->talk.actual); 02895 } 02896 02897 if (confflags & (CONFFLAG_OPTIMIZETALKER | CONFFLAG_MONITORTALKER)) { 02898 if (user->talking == -1) { 02899 user->talking = 0; 02900 } 02901 02902 res = ast_dsp_silence(dsp, f, &totalsilence); 02903 if (totalsilence < MEETME_DELAYDETECTTALK) { 02904 set_user_talking(chan, conf, user, 1, confflags & CONFFLAG_MONITORTALKER); 02905 } 02906 if (totalsilence > MEETME_DELAYDETECTENDTALK) { 02907 set_user_talking(chan, conf, user, 0, confflags & CONFFLAG_MONITORTALKER); 02908 } 02909 } 02910 if (using_pseudo) { 02911 /* Absolutely do _not_ use careful_write here... 02912 it is important that we read data from the channel 02913 as fast as it arrives, and feed it into the conference. 02914 The buffering in the pseudo channel will take care of any 02915 timing differences, unless they are so drastic as to lose 02916 audio frames (in which case carefully writing would only 02917 have delayed the audio even further). 02918 */ 02919 /* As it turns out, we do want to use careful write. We just 02920 don't want to block, but we do want to at least *try* 02921 to write out all the samples. 02922 */ 02923 if (user->talking || !(confflags & CONFFLAG_OPTIMIZETALKER)) { 02924 careful_write(fd, f->data.ptr, f->datalen, 0); 02925 } 02926 } 02927 } else if (((f->frametype == AST_FRAME_DTMF) && (f->subclass == '*') && (confflags & CONFFLAG_STARMENU)) || ((f->frametype == AST_FRAME_DTMF) && menu_active)) { 02928 if (confflags & CONFFLAG_PASS_DTMF) { 02929 conf_queue_dtmf(conf, user, f); 02930 } 02931 if (ioctl(fd, DAHDI_SETCONF, &dahdic_empty)) { 02932 ast_log(LOG_WARNING, "Error setting conference\n"); 02933 close(fd); 02934 ast_frfree(f); 02935 goto outrun; 02936 } 02937 02938 /* if we are entering the menu, and the user has a channel-driver 02939 volume adjustment, clear it 02940 */ 02941 if (!menu_active && user->talk.desired && !user->talk.actual) { 02942 set_talk_volume(user, 0); 02943 } 02944 02945 if (musiconhold) { 02946 ast_moh_stop(chan); 02947 } 02948 if ((confflags & CONFFLAG_ADMIN)) { 02949 /* Admin menu */ 02950 if (!menu_active) { 02951 menu_active = 1; 02952 /* Record this sound! */ 02953 if (!ast_streamfile(chan, "conf-adminmenu-162", chan->language)) { 02954 dtmf = ast_waitstream(chan, AST_DIGIT_ANY); 02955 ast_stopstream(chan); 02956 } else { 02957 dtmf = 0; 02958 } 02959 } else { 02960 dtmf = f->subclass; 02961 } 02962 if (dtmf) { 02963 switch(dtmf) { 02964 case '1': /* Un/Mute */ 02965 menu_active = 0; 02966 02967 /* for admin, change both admin and use flags */ 02968 if (user->adminflags & (ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED)) { 02969 user->adminflags &= ~(ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED); 02970 } else { 02971 user->adminflags |= (ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED); 02972 } 02973 02974 if ((confflags & CONFFLAG_MONITOR) || (user->adminflags & (ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED))) { 02975 if (!ast_streamfile(chan, "conf-muted", chan->language)) { 02976 ast_waitstream(chan, ""); 02977 } 02978 } else { 02979 if (!ast_streamfile(chan, "conf-unmuted", chan->language)) { 02980 ast_waitstream(chan, ""); 02981 } 02982 } 02983 break; 02984 case '2': /* Un/Lock the Conference */ 02985 menu_active = 0; 02986 if (conf->locked) { 02987 conf->locked = 0; 02988 if (!ast_streamfile(chan, "conf-unlockednow", chan->language)) { 02989 ast_waitstream(chan, ""); 02990 } 02991 } else { 02992 conf->locked = 1; 02993 if (!ast_streamfile(chan, "conf-lockednow", chan->language)) { 02994 ast_waitstream(chan, ""); 02995 } 02996 } 02997 break; 02998 case '3': /* Eject last user */ 02999 menu_active = 0; 03000 usr = AST_LIST_LAST(&conf->userlist); 03001 if ((usr->chan->name == chan->name) || (usr->userflags & CONFFLAG_ADMIN)) { 03002 if (!ast_streamfile(chan, "conf-errormenu", chan->language)) { 03003 ast_waitstream(chan, ""); 03004 } 03005 } else { 03006 usr->adminflags |= ADMINFLAG_KICKME; 03007 } 03008 ast_stopstream(chan); 03009 break; 03010 case '4': 03011 tweak_listen_volume(user, VOL_DOWN); 03012 break; 03013 case '5': 03014 /* Extend RT conference */ 03015 if (rt_schedule) { 03016 if (!rt_extend_conf(conf->confno)) { 03017 if (!ast_streamfile(chan, "conf-extended", chan->language)) { 03018 ast_waitstream(chan, ""); 03019 } 03020 } else { 03021 if (!ast_streamfile(chan, "conf-nonextended", chan->language)) { 03022 ast_waitstream(chan, ""); 03023 } 03024 } 03025 ast_stopstream(chan); 03026 } 03027 menu_active = 0; 03028 break; 03029 case '6': 03030 tweak_listen_volume(user, VOL_UP); 03031 break; 03032 case '7': 03033 tweak_talk_volume(user, VOL_DOWN); 03034 break; 03035 case '8': 03036 menu_active = 0; 03037 break; 03038 case '9': 03039 tweak_talk_volume(user, VOL_UP); 03040 break; 03041 default: 03042 menu_active = 0; 03043 /* Play an error message! */ 03044 if (!ast_streamfile(chan, "conf-errormenu", chan->language)) { 03045 ast_waitstream(chan, ""); 03046 } 03047 break; 03048 } 03049 } 03050 } else { 03051 /* User menu */ 03052 if (!menu_active) { 03053 menu_active = 1; 03054 if (!ast_streamfile(chan, "conf-usermenu-162", chan->language)) { 03055 dtmf = ast_waitstream(chan, AST_DIGIT_ANY); 03056 ast_stopstream(chan); 03057 } else { 03058 dtmf = 0; 03059 } 03060 } else { 03061 dtmf = f->subclass; 03062 } 03063 if (dtmf) { 03064 switch (dtmf) { 03065 case '1': /* Un/Mute */ 03066 menu_active = 0; 03067 03068 /* user can only toggle the self-muted state */ 03069 user->adminflags ^= ADMINFLAG_SELFMUTED; 03070 03071 /* they can't override the admin mute state */ 03072 if ((confflags & CONFFLAG_MONITOR) || (user->adminflags & (ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED))) { 03073 if (!ast_streamfile(chan, "conf-muted", chan->language)) { 03074 ast_waitstream(chan, ""); 03075 } 03076 } else { 03077 if (!ast_streamfile(chan, "conf-unmuted", chan->language)) { 03078 ast_waitstream(chan, ""); 03079 } 03080 } 03081 break; 03082 case '2': 03083 menu_active = 0; 03084 if (user->adminflags & (ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED)) { 03085 user->adminflags |= ADMINFLAG_T_REQUEST; 03086 } 03087 03088 if (user->adminflags & ADMINFLAG_T_REQUEST) { 03089 if (!ast_streamfile(chan, "beep", chan->language)) { 03090 ast_waitstream(chan, ""); 03091 } 03092 } 03093 break; 03094 case '4': 03095 tweak_listen_volume(user, VOL_DOWN); 03096 break; 03097 case '5': 03098 /* Extend RT conference */ 03099 if (rt_schedule) { 03100 rt_extend_conf(conf->confno); 03101 } 03102 menu_active = 0; 03103 break; 03104 case '6': 03105 tweak_listen_volume(user, VOL_UP); 03106 break; 03107 case '7': 03108 tweak_talk_volume(user, VOL_DOWN); 03109 break; 03110 case '8': 03111 menu_active = 0; 03112 break; 03113 case '9': 03114 tweak_talk_volume(user, VOL_UP); 03115 break; 03116 default: 03117 menu_active = 0; 03118 if (!ast_streamfile(chan, "conf-errormenu", chan->language)) { 03119 ast_waitstream(chan, ""); 03120 } 03121 break; 03122 } 03123 } 03124 } 03125 if (musiconhold) { 03126 conf_start_moh(chan, optargs[OPT_ARG_MOH_CLASS]); 03127 } 03128 03129 if (ioctl(fd, DAHDI_SETCONF, &dahdic)) { 03130 ast_log(LOG_WARNING, "Error setting conference\n"); 03131 close(fd); 03132 ast_frfree(f); 03133 goto outrun; 03134 } 03135 03136 conf_flush(fd, chan); 03137 /* Since this option could absorb DTMF meant for the previous (menu), we have to check this one last */ 03138 } else if ((f->frametype == AST_FRAME_DTMF) && (confflags & CONFFLAG_EXIT_CONTEXT) && ast_exists_extension(chan, exitcontext, dtmfstr, 1, "")) { 03139 if (confflags & CONFFLAG_PASS_DTMF) { 03140 conf_queue_dtmf(conf, user, f); 03141 } 03142 03143 if (!ast_goto_if_exists(chan, exitcontext, dtmfstr, 1)) { 03144 ast_debug(1, "Got DTMF %c, goto context %s\n", dtmfstr[0], exitcontext); 03145 ret = 0; 03146 ast_frfree(f); 03147 break; 03148 } else { 03149 ast_debug(2, "Exit by single digit did not work in meetme. Extension %s does not exist in context %s\n", dtmfstr, exitcontext); 03150 } 03151 } else if ((f->frametype == AST_FRAME_DTMF) && (confflags & CONFFLAG_KEYEXIT) && (strchr(exitkeys, f->subclass))) { 03152 pbx_builtin_setvar_helper(chan, "MEETME_EXIT_KEY", dtmfstr); 03153 03154 if (confflags & CONFFLAG_PASS_DTMF) { 03155 conf_queue_dtmf(conf, user, f); 03156 } 03157 ret = 0; 03158 ast_frfree(f); 03159 break; 03160 } else if ((f->frametype == AST_FRAME_DTMF_BEGIN || f->frametype == AST_FRAME_DTMF_END) 03161 && confflags & CONFFLAG_PASS_DTMF) { 03162 conf_queue_dtmf(conf, user, f); 03163 } else if ((confflags & CONFFLAG_SLA_STATION) && f->frametype == AST_FRAME_CONTROL) { 03164 switch (f->subclass) { 03165 case AST_CONTROL_HOLD: 03166 sla_queue_event_conf(SLA_EVENT_HOLD, chan, conf); 03167 break; 03168 default: 03169 break; 03170 } 03171 } else if (f->frametype == AST_FRAME_NULL) { 03172 /* Ignore NULL frames. It is perfectly normal to get these if the person is muted. */ 03173 } else { 03174 ast_debug(1, 03175 "Got unrecognized frame on channel %s, f->frametype=%d,f->subclass=%d\n", 03176 chan->name, f->frametype, f->subclass); 03177 } 03178 ast_frfree(f); 03179 } else if (outfd > -1) { 03180 res = read(outfd, buf, CONF_SIZE); 03181 if (res > 0) { 03182 memset(&fr, 0, sizeof(fr)); 03183 fr.frametype = AST_FRAME_VOICE; 03184 fr.subclass = AST_FORMAT_SLINEAR; 03185 fr.datalen = res; 03186 fr.samples = res / 2; 03187 fr.data.ptr = buf; 03188 fr.offset = AST_FRIENDLY_OFFSET; 03189 if (!user->listen.actual && 03190 ((confflags & CONFFLAG_MONITOR) || 03191 (user->adminflags & (ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED)) || 03192 (!user->talking && (confflags & CONFFLAG_OPTIMIZETALKER)) 03193 )) { 03194 int idx; 03195 for (idx = 0; idx < AST_FRAME_BITS; idx++) { 03196 if (chan->rawwriteformat & (1 << idx)) { 03197 break; 03198 } 03199 } 03200 if (idx >= AST_FRAME_BITS) { 03201 goto bailoutandtrynormal; 03202 } 03203 ast_mutex_lock(&conf->listenlock); 03204 if (!conf->transframe[idx]) { 03205 if (conf->origframe) { 03206 if (!conf->transpath[idx]) { 03207 conf->transpath[idx] = ast_translator_build_path((1 << idx), AST_FORMAT_SLINEAR); 03208 } 03209 if (conf->transpath[idx]) { 03210 conf->transframe[idx] = ast_translate(conf->transpath[idx], conf->origframe, 0); 03211 if (!conf->transframe[idx]) { 03212 conf->transframe[idx] = &ast_null_frame; 03213 } 03214 } 03215 } 03216 } 03217 if (conf->transframe[idx]) { 03218 if ((conf->transframe[idx]->frametype != AST_FRAME_NULL) && 03219 can_write(chan, confflags)) { 03220 struct ast_frame *cur; 03221 if (musiconhold && !ast_dsp_silence(dsp, conf->transframe[idx], &confsilence) && confsilence < MEETME_DELAYDETECTTALK) { 03222 ast_moh_stop(chan); 03223 mohtempstopped = 1; 03224 } 03225 03226 /* the translator may have returned a list of frames, so 03227 write each one onto the channel 03228 */ 03229 for (cur = conf->transframe[idx]; cur; cur = AST_LIST_NEXT(cur, frame_list)) { 03230 if (ast_write(chan, cur)) { 03231 ast_log(LOG_WARNING, "Unable to write frame to channel %s\n", chan->name); 03232 break; 03233 } 03234 } 03235 if (musiconhold && mohtempstopped && confsilence > MEETME_DELAYDETECTENDTALK) { 03236 mohtempstopped = 0; 03237 ast_moh_start(chan, NULL, NULL); 03238 } 03239 } 03240 } else { 03241 ast_mutex_unlock(&conf->listenlock); 03242 goto bailoutandtrynormal; 03243 } 03244 ast_mutex_unlock(&conf->listenlock); 03245 } else { 03246 bailoutandtrynormal: 03247 if (musiconhold && !ast_dsp_silence(dsp, &fr, &confsilence) && confsilence < MEETME_DELAYDETECTTALK) { 03248 ast_moh_stop(chan); 03249 mohtempstopped = 1; 03250 } 03251 if (user->listen.actual) { 03252 ast_frame_adjust_volume(&fr, user->listen.actual); 03253 } 03254 if (can_write(chan, confflags) && ast_write(chan, &fr) < 0) { 03255 ast_log(LOG_WARNING, "Unable to write frame to channel %s\n", chan->name); 03256 } 03257 if (musiconhold && mohtempstopped && confsilence > MEETME_DELAYDETECTENDTALK) { 03258 mohtempstopped = 0; 03259 ast_moh_start(chan, NULL, NULL); 03260 } 03261 } 03262 } else { 03263 ast_log(LOG_WARNING, "Failed to read frame: %s\n", strerror(errno)); 03264 } 03265 } 03266 lastmarked = currentmarked; 03267 } 03268 } 03269 03270 if (musiconhold) { 03271 ast_moh_stop(chan); 03272 } 03273 03274 if (using_pseudo) { 03275 close(fd); 03276 } else { 03277 /* Take out of conference */ 03278 dahdic.chan = 0; 03279 dahdic.confno = 0; 03280 dahdic.confmode = 0; 03281 if (ioctl(fd, DAHDI_SETCONF, &dahdic)) { 03282 ast_log(LOG_WARNING, "Error setting conference\n"); 03283 } 03284 } 03285 03286 reset_volumes(user); 03287 03288 if (!(confflags & CONFFLAG_QUIET) && !(confflags & CONFFLAG_MONITOR) && !(confflags & CONFFLAG_ADMIN)) { 03289 conf_play(chan, conf, LEAVE); 03290 } 03291 03292 if (!(confflags & CONFFLAG_QUIET) && ((confflags & CONFFLAG_INTROUSER) || (confflags & CONFFLAG_INTROUSERNOREVIEW)) && conf->users > 1) { 03293 struct announce_listitem *item; 03294 if (!(item = ao2_alloc(sizeof(*item), NULL))) 03295 return -1; 03296 ast_copy_string(item->namerecloc, user->namerecloc, sizeof(item->namerecloc)); 03297 ast_copy_string(item->language, chan->language, sizeof(item->language)); 03298 item->confchan = conf->chan; 03299 item->confusers = conf->users; 03300 item->announcetype = CONF_HASLEFT; 03301 ast_mutex_lock(&conf->announcelistlock); 03302 AST_LIST_INSERT_TAIL(&conf->announcelist, item, entry); 03303 ast_cond_signal(&conf->announcelist_addition); 03304 ast_mutex_unlock(&conf->announcelistlock); 03305 } else if (!(confflags & CONFFLAG_QUIET) && ((confflags & CONFFLAG_INTROUSER) || (confflags & CONFFLAG_INTROUSERNOREVIEW)) && conf->users == 1) { 03306 /* Last person is leaving, so no reason to try and announce, but should delete the name recording */ 03307 ast_filedelete(user->namerecloc, NULL); 03308 } 03309 03310 outrun: 03311 AST_LIST_LOCK(&confs); 03312 03313 if (dsp) { 03314 ast_dsp_free(dsp); 03315 } 03316 03317 if (user->user_no) { /* Only cleanup users who really joined! */ 03318 now = ast_tvnow(); 03319 hr = (now.tv_sec - user->jointime) / 3600; 03320 min = ((now.tv_sec - user->jointime) % 3600) / 60; 03321 sec = (now.tv_sec - user->jointime) % 60; 03322 03323 if (sent_event) { 03324 manager_event(EVENT_FLAG_CALL, "MeetmeLeave", 03325 "Channel: %s\r\n" 03326 "Uniqueid: %s\r\n" 03327 "Meetme: %s\r\n" 03328 "Usernum: %d\r\n" 03329 "CallerIDNum: %s\r\n" 03330 "CallerIDName: %s\r\n" 03331 "Duration: %ld\r\n", 03332 chan->name, chan->uniqueid, conf->confno, 03333 user->user_no, 03334 S_OR(user->chan->cid.cid_num, "<unknown>"), 03335 S_OR(user->chan->cid.cid_name, "<unknown>"), 03336 (long)(now.tv_sec - user->jointime)); 03337 } 03338 03339 if (setusercount) { 03340 conf->users--; 03341 if (rt_log_members) { 03342 /* Update table */ 03343 snprintf(members, sizeof(members), "%d", conf->users); 03344 ast_realtime_require_field("meetme", 03345 "confno", strlen(conf->confno) > 7 ? RQ_UINTEGER4 : strlen(conf->confno) > 4 ? RQ_UINTEGER3 : RQ_UINTEGER2, strlen(conf->confno), 03346 "members", RQ_UINTEGER1, strlen(members), 03347 NULL); 03348 ast_update_realtime("meetme", "confno", conf->confno, "members", members, NULL); 03349 } 03350 if (confflags & CONFFLAG_MARKEDUSER) { 03351 conf->markedusers--; 03352 } 03353 } 03354 /* Remove ourselves from the list */ 03355 AST_LIST_REMOVE(&conf->userlist, user, list); 03356 03357 /* Change any states */ 03358 if (!conf->users) { 03359 ast_devstate_changed(AST_DEVICE_NOT_INUSE, "meetme:%s", conf->confno); 03360 } 03361 03362 /* Return the number of seconds the user was in the conf */ 03363 snprintf(meetmesecs, sizeof(meetmesecs), "%d", (int) (time(NULL) - user->jointime)); 03364 pbx_builtin_setvar_helper(chan, "MEETMESECS", meetmesecs); 03365 } 03366 ast_free(user); 03367 AST_LIST_UNLOCK(&confs); 03368 03369 return ret; 03370 }
| static void conf_start_moh | ( | struct ast_channel * | chan, | |
| const char * | musicclass | |||
| ) | [static] |
Definition at line 1877 of file app_meetme.c.
References ast_channel_lock, ast_channel_unlock, ast_moh_start(), ast_string_field_set, and ast_channel::musicclass.
Referenced by conf_run().
01878 { 01879 char *original_moh; 01880 01881 ast_channel_lock(chan); 01882 original_moh = ast_strdupa(chan->musicclass); 01883 ast_string_field_set(chan, musicclass, musicclass); 01884 ast_channel_unlock(chan); 01885 01886 ast_moh_start(chan, original_moh, NULL); 01887 01888 ast_channel_lock(chan); 01889 ast_string_field_set(chan, musicclass, original_moh); 01890 ast_channel_unlock(chan); 01891 }
| static int count_exec | ( | struct ast_channel * | chan, | |
| void * | data | |||
| ) | [static] |
The MeetmeCount application.
Definition at line 3650 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_strlen_zero(), dispose_conf(), find_conf(), ast_channel::language, LOG_WARNING, pbx_builtin_setvar_helper(), and ast_conference::users.
Referenced by load_module().
03651 { 03652 int res = 0; 03653 struct ast_conference *conf; 03654 int count; 03655 char *localdata; 03656 char val[80] = "0"; 03657 AST_DECLARE_APP_ARGS(args, 03658 AST_APP_ARG(confno); 03659 AST_APP_ARG(varname); 03660 ); 03661 03662 if (ast_strlen_zero(data)) { 03663 ast_log(LOG_WARNING, "MeetMeCount requires an argument (conference number)\n"); 03664 return -1; 03665 } 03666 03667 if (!(localdata = ast_strdupa(data))) 03668 return -1; 03669 03670 AST_STANDARD_APP_ARGS(args, localdata); 03671 03672 conf = find_conf(chan, args.confno, 0, 0, NULL, 0, 1, NULL); 03673 03674 if (conf) { 03675 count = conf->users; 03676 dispose_conf(conf); 03677 conf = NULL; 03678 } else 03679 count = 0; 03680 03681 if (!ast_strlen_zero(args.varname)) { 03682 /* have var so load it and exit */ 03683 snprintf(val, sizeof(val), "%d", count); 03684 pbx_builtin_setvar_helper(chan, args.varname, val); 03685 } else { 03686 if (chan->_state != AST_STATE_UP) { 03687 ast_answer(chan); 03688 } 03689 res = ast_say_number(chan, count, "", chan->language, (char *) NULL); /* Needs gender */ 03690 } 03691 03692 return res; 03693 }
| static struct sla_trunk_ref* create_trunk_ref | ( | struct sla_trunk * | trunk | ) | [static, read] |
Definition at line 5762 of file app_meetme.c.
References ast_calloc, and sla_trunk_ref::trunk.
Referenced by sla_add_trunk_to_station().
05763 { 05764 struct sla_trunk_ref *trunk_ref; 05765 05766 if (!(trunk_ref = ast_calloc(1, sizeof(*trunk_ref)))) 05767 return NULL; 05768 05769 trunk_ref->trunk = trunk; 05770 05771 return trunk_ref; 05772 }
| static void destroy_station | ( | struct sla_station * | station | ) | [static] |
Definition at line 5973 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().
05974 { 05975 struct sla_trunk_ref *trunk_ref; 05976 05977 if (!ast_strlen_zero(station->autocontext)) { 05978 AST_RWLIST_RDLOCK(&sla_trunks); 05979 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) { 05980 char exten[AST_MAX_EXTENSION]; 05981 char hint[AST_MAX_APP]; 05982 snprintf(exten, sizeof(exten), "%s_%s", station->name, trunk_ref->trunk->name); 05983 snprintf(hint, sizeof(hint), "SLA:%s", exten); 05984 ast_context_remove_extension(station->autocontext, exten, 05985 1, sla_registrar); 05986 ast_context_remove_extension(station->autocontext, hint, 05987 PRIORITY_HINT, sla_registrar); 05988 } 05989 AST_RWLIST_UNLOCK(&sla_trunks); 05990 } 05991 05992 while ((trunk_ref = AST_LIST_REMOVE_HEAD(&station->trunks, entry))) 05993 ast_free(trunk_ref); 05994 05995 ast_string_field_free_memory(station); 05996 ast_free(station); 05997 }
| static void destroy_trunk | ( | struct sla_trunk * | trunk | ) | [static] |
Definition at line 5959 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().
05960 { 05961 struct sla_station_ref *station_ref; 05962 05963 if (!ast_strlen_zero(trunk->autocontext)) 05964 ast_context_remove_extension(trunk->autocontext, "s", 1, sla_registrar); 05965 05966 while ((station_ref = AST_LIST_REMOVE_HEAD(&trunk->stations, entry))) 05967 ast_free(station_ref); 05968 05969 ast_string_field_free_memory(trunk); 05970 ast_free(trunk); 05971 }
| static void* dial_trunk | ( | void * | data | ) | [static] |
Definition at line 5474 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_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, sla_trunk_ref::trunk, and dial_trunk_args::trunk_ref.
Referenced by sla_station_exec().
05475 { 05476 struct dial_trunk_args *args = data; 05477 struct ast_dial *dial; 05478 char *tech, *tech_data; 05479 enum ast_dial_result dial_res; 05480 char conf_name[MAX_CONFNUM]; 05481 struct ast_conference *conf; 05482 struct ast_flags conf_flags = { 0 }; 05483 struct sla_trunk_ref *trunk_ref = args->trunk_ref; 05484 const char *cid_name = NULL, *cid_num = NULL; 05485 05486 if (!(dial = ast_dial_create())) { 05487 ast_mutex_lock(args->cond_lock); 05488 ast_cond_signal(args->cond); 05489 ast_mutex_unlock(args->cond_lock); 05490 return NULL; 05491 } 05492 05493 tech_data = ast_strdupa(trunk_ref->trunk->device); 05494 tech = strsep(&tech_data, "/"); 05495 if (ast_dial_append(dial, tech, tech_data) == -1) { 05496 ast_mutex_lock(args->cond_lock); 05497 ast_cond_signal(args->cond); 05498 ast_mutex_unlock(args->cond_lock); 05499 ast_dial_destroy(dial); 05500 return NULL; 05501 } 05502 05503 if (!sla.attempt_callerid && !ast_strlen_zero(trunk_ref->chan->cid.cid_name)) { 05504 cid_name = ast_strdupa(trunk_ref->chan->cid.cid_name); 05505 ast_free(trunk_ref->chan->cid.cid_name); 05506 trunk_ref->chan->cid.cid_name = NULL; 05507 } 05508 if (!sla.attempt_callerid && !ast_strlen_zero(trunk_ref->chan->cid.cid_num)) { 05509 cid_num = ast_strdupa(trunk_ref->chan->cid.cid_num); 05510 ast_free(trunk_ref->chan->cid.cid_num); 05511 trunk_ref->chan->cid.cid_num = NULL; 05512 } 05513 05514 dial_res = ast_dial_run(dial, trunk_ref->chan, 1); 05515 05516 if (cid_name) 05517 trunk_ref->chan->cid.cid_name = ast_strdup(cid_name); 05518 if (cid_num) 05519 trunk_ref->chan->cid.cid_num = ast_strdup(cid_num); 05520 05521 if (dial_res != AST_DIAL_RESULT_TRYING) { 05522 ast_mutex_lock(args->cond_lock); 05523 ast_cond_signal(args->cond); 05524 ast_mutex_unlock(args->cond_lock); 05525 ast_dial_destroy(dial); 05526 return NULL; 05527 } 05528 05529 for (;;) { 05530 unsigned int done = 0; 05531 switch ((dial_res = ast_dial_state(dial))) { 05532 case AST_DIAL_RESULT_ANSWERED: 05533 trunk_ref->trunk->chan = ast_dial_answered(dial); 05534 case AST_DIAL_RESULT_HANGUP: 05535 case AST_DIAL_RESULT_INVALID: 05536 case AST_DIAL_RESULT_FAILED: 05537 case AST_DIAL_RESULT_TIMEOUT: 05538 case AST_DIAL_RESULT_UNANSWERED: 05539 done = 1; 05540 case AST_DIAL_RESULT_TRYING: 05541 case AST_DIAL_RESULT_RINGING: 05542 case AST_DIAL_RESULT_PROGRESS: 05543 case AST_DIAL_RESULT_PROCEEDING: 05544 break; 05545 } 05546 if (done) 05547 break; 05548 } 05549 05550 if (!trunk_ref->trunk->chan) { 05551 ast_mutex_lock(args->cond_lock); 05552 ast_cond_signal(args->cond); 05553 ast_mutex_unlock(args->cond_lock); 05554 ast_dial_join(dial); 05555 ast_dial_destroy(dial); 05556 return NULL; 05557 } 05558 05559 snprintf(conf_name, sizeof(conf_name), "SLA_%s", trunk_ref->trunk->name); 05560 ast_set_flag(&conf_flags, 05561 CONFFLAG_QUIET | CONFFLAG_MARKEDEXIT | CONFFLAG_MARKEDUSER | 05562 CONFFLAG_PASS_DTMF | CONFFLAG_SLA_TRUNK); 05563 conf = build_conf(conf_name, "", "", 1, 1, 1, trunk_ref->trunk->chan); 05564 05565 ast_mutex_lock(args->cond_lock); 05566 ast_cond_signal(args->cond); 05567 ast_mutex_unlock(args->cond_lock); 05568 05569 if (conf) { 05570 conf_run(trunk_ref->trunk->chan, conf, conf_flags.flags, NULL); 05571 dispose_conf(conf); 05572 conf = NULL; 05573 } 05574 05575 /* If the trunk is going away, it is definitely now IDLE. */ 05576 sla_change_trunk_state(trunk_ref->trunk, SLA_TRUNK_STATE_IDLE, ALL_TRUNK_REFS, NULL); 05577 05578 trunk_ref->trunk->chan = NULL; 05579 trunk_ref->trunk->on_hold = 0; 05580 05581 ast_dial_join(dial); 05582 ast_dial_destroy(dial); 05583 05584 return NULL; 05585 }
| static int dispose_conf | ( | struct ast_conference * | conf | ) | [static] |
Definition at line 1796 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().
01797 { 01798 int res = 0; 01799 int confno_int = 0; 01800 01801 AST_LIST_LOCK(&confs); 01802 if (ast_atomic_dec_and_test(&conf->refcount)) { 01803 /* Take the conference room number out of an inuse state */ 01804 if ((sscanf(conf->confno, "%4d", &confno_int) == 1) && (confno_int >= 0 && confno_int < 1024)) { 01805 conf_map[confno_int] = 0; 01806 } 01807 conf_free(conf); 01808 res = 1; 01809 } 01810 AST_LIST_UNLOCK(&confs); 01811 01812 return res; 01813 }
| 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 3546 of file app_meetme.c.
References AST_APP_ARG, ast_app_getdata(), ast_clear_flag, ast_config_destroy(), ast_config_load, ast_copy_string(), ast_debug, AST_DECLARE_APP_ARGS, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), AST_STANDARD_APP_ARGS, ast_test_flag, ast_variable_browse(), build_conf(), ast_conference::chan, CONFFLAG_INTROUSER, CONFFLAG_INTROUSERNOREVIEW, CONFFLAG_QUIET, CONFFLAG_RECORDCONF, CONFIG_FILE_NAME, CONFIG_STATUS_FILEINVALID, ast_conference::confno, ast_conference::list, LOG_ERROR, LOG_WARNING, MAX_SETTINGS, ast_variable::name, ast_variable::next, parse(), ast_conference::refcount, S_OR, ast_variable::value, and var.
Referenced by conf_exec(), and count_exec().
03548 { 03549 struct ast_config *cfg; 03550 struct ast_variable *var; 03551 struct ast_flags config_flags = { 0 }; 03552 struct ast_conference *cnf; 03553 03554 AST_DECLARE_APP_ARGS(args, 03555 AST_APP_ARG(confno); 03556 AST_APP_ARG(pin); 03557 AST_APP_ARG(pinadmin); 03558 ); 03559 03560 /* Check first in the conference list */ 03561 ast_debug(1, "The requested confno is '%s'?\n", confno); 03562 AST_LIST_LOCK(&confs); 03563 AST_LIST_TRAVERSE(&confs, cnf, list) { 03564 ast_debug(3, "Does conf %s match %s?\n", confno, cnf->confno); 03565 if (!strcmp(confno, cnf->confno)) 03566 break; 03567 } 03568 if (cnf) { 03569 cnf->refcount += refcount; 03570 } 03571 AST_LIST_UNLOCK(&confs); 03572 03573 if (!cnf) { 03574 if (dynamic) { 03575 /* No need to parse meetme.conf */ 03576 ast_debug(1, "Building dynamic conference '%s'\n", confno); 03577 if (dynamic_pin) { 03578 if (dynamic_pin[0] == 'q') { 03579 /* Query the user to enter a PIN */ 03580 if (ast_app_getdata(chan, "conf-getpin", dynamic_pin, pin_buf_len - 1, 0) < 0) 03581 return NULL; 03582 } 03583 cnf = build_conf(confno, dynamic_pin, "", make, dynamic, refcount, chan); 03584 } else { 03585 cnf = build_conf(confno, "", "", make, dynamic, refcount, chan); 03586 } 03587 } else { 03588 /* Check the config */ 03589 cfg = ast_config_load(CONFIG_FILE_NAME, config_flags); 03590 if (!cfg) { 03591 ast_log(LOG_WARNING, "No %s file :(\n", CONFIG_FILE_NAME); 03592 return NULL; 03593 } else if (cfg == CONFIG_STATUS_FILEINVALID) { 03594 ast_log(LOG_ERROR, "Config file " CONFIG_FILE_NAME " is in an invalid format. Aborting.\n"); 03595 return NULL; 03596 } 03597 03598 for (var = ast_variable_browse(cfg, "rooms"); var; var = var->next) { 03599 char parse[MAX_SETTINGS]; 03600 03601 if (strcasecmp(var->name, "conf")) 03602 continue; 03603 03604 ast_copy_string(parse, var->value, sizeof(parse)); 03605 03606 AST_STANDARD_APP_ARGS(args, parse); 03607 ast_debug(3, "Will conf %s match %s?\n", confno, args.confno); 03608 if (!strcasecmp(args.confno, confno)) { 03609 /* Bingo it's a valid conference */ 03610 cnf = build_conf(args.confno, 03611 S_OR(args.pin, ""), 03612 S_OR(args.pinadmin, ""), 03613 make, dynamic, refcount, chan); 03614 break; 03615 } 03616 } 03617 if (!var) { 03618 ast_debug(1, "%s isn't a valid conference\n", confno); 03619 } 03620 ast_config_destroy(cfg); 03621 } 03622 } else if (dynamic_pin) { 03623 /* Correct for the user selecting 'D' instead of 'd' to have 03624 someone join into a conference that has already been created 03625 with a pin. */ 03626 if (dynamic_pin[0] == 'q') { 03627 dynamic_pin[0] = '\0'; 03628 } 03629 } 03630 03631 if (cnf) { 03632 if (confflags && !cnf->chan && 03633 !ast_test_flag(confflags, CONFFLAG_QUIET) && 03634 ast_test_flag(confflags, CONFFLAG_INTROUSER | CONFFLAG_INTROUSERNOREVIEW)) { 03635 ast_log(LOG_WARNING, "No DAHDI channel available for conference, user introduction disabled (is chan_dahdi loaded?)\n"); 03636 ast_clear_flag(confflags, CONFFLAG_INTROUSER | CONFFLAG_INTROUSERNOREVIEW); 03637 } 03638 03639 if (confflags && !cnf->chan && 03640 ast_test_flag(confflags, CONFFLAG_RECORDCONF)) { 03641 ast_log(LOG_WARNING, "No DAHDI channel available for conference, conference recording disabled (is chan_dahdi loaded?)\n"); 03642 ast_clear_flag(confflags, CONFFLAG_RECORDCONF); 03643 } 03644 } 03645 03646 return cnf; 03647 }
| 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, | |||
| int * | too_early | |||
| ) | [static, read] |
Definition at line 3372 of file app_meetme.c.
References ast_conference::adminopts, ast_channel_lock, ast_channel_unlock, ast_clear_flag, ast_copy_string(), ast_debug, ast_free, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_load_realtime(), ast_localtime(), ast_log(), AST_MAX_EXTENSION, ast_mktime(), ast_strdup, ast_streamfile(), ast_strftime(), ast_strlen_zero(), ast_strptime(), ast_test_flag, ast_tvnow(), ast_variables_destroy(), ast_verb, ast_waitstream(), ast_conference::bookid, 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_channel::language, ast_conference::list, LOG_WARNING, ast_conference::maxusers, ast_variable::name, ast_variable::next, OPTIONS_LEN, pbx_builtin_getvar_helper(), ast_conference::recordingfilename, ast_conference::recordingformat, ast_conference::refcount, ast_channel::uniqueid, ast_conference::useropts, ast_variable::value, and var.
Referenced by conf_exec().
03374 { 03375 struct ast_variable *var, *origvar; 03376 struct ast_conference *cnf; 03377 03378 *too_early = 0; 03379 03380 /* Check first in the conference list */ 03381 AST_LIST_LOCK(&confs); 03382 AST_LIST_TRAVERSE(&confs, cnf, list) { 03383 if (!strcmp(confno, cnf->confno)) 03384 break; 03385 } 03386 if (cnf) { 03387 cnf->refcount += refcount; 03388 } 03389 AST_LIST_UNLOCK(&confs); 03390 03391 if (!cnf) { 03392 char *pin = NULL, *pinadmin = NULL; /* For temp use */ 03393 int maxusers = 0; 03394 struct timeval now; 03395 char recordingfilename[256] = ""; 03396 char recordingformat[11] = ""; 03397 char currenttime[19] = ""; 03398 char eatime[19] = ""; 03399 char bookid[51] = ""; 03400 char recordingtmp[AST_MAX_EXTENSION] = ""; 03401 char useropts[OPTIONS_LEN + 1]; /* Used for RealTime conferences */ 03402 char adminopts[OPTIONS_LEN + 1]; 03403 struct ast_tm tm, etm; 03404 struct timeval endtime = { .tv_sec = 0 }; 03405 const char *var2; 03406 03407 if (rt_schedule) { 03408 now = ast_tvnow(); 03409 03410 ast_localtime(&now, &tm, NULL); 03411 ast_strftime(currenttime, sizeof(currenttime), DATE_FORMAT, &tm); 03412 03413 ast_debug(1, "Looking for conference %s that starts after %s\n", confno, eatime); 03414 03415 var = ast_load_realtime("meetme", "confno", 03416 confno, "starttime <= ", currenttime, "endtime >= ", 03417 currenttime, NULL); 03418 03419 if (!var && fuzzystart) { 03420 now = ast_tvnow(); 03421 now.tv_sec += fuzzystart; 03422 03423 ast_localtime(&now, &tm, NULL); 03424 ast_strftime(currenttime, sizeof(currenttime), DATE_FORMAT, &tm); 03425 var = ast_load_realtime("meetme", "confno", 03426 confno, "starttime <= ", currenttime, "endtime >= ", 03427 currenttime, NULL); 03428 } 03429 03430 if (!var && earlyalert) { 03431 now = ast_tvnow(); 03432 now.tv_sec += earlyalert; 03433 ast_localtime(&now, &etm, NULL); 03434 ast_strftime(eatime, sizeof(eatime), DATE_FORMAT, &etm); 03435 var = ast_load_realtime("meetme", "confno", 03436 confno, "starttime <= ", eatime, "endtime >= ", 03437 currenttime, NULL); 03438 if (var) { 03439 *too_early = 1; 03440 } 03441 } 03442 03443 } else { 03444 var = ast_load_realtime("meetme", "confno", confno, NULL); 03445 } 03446 03447 if (!var) 03448 return NULL; 03449 03450 if (rt_schedule && *too_early) { 03451 /* Announce that the caller is early and exit */ 03452 if (!ast_streamfile(chan, "conf-has-not-started", chan->language)) 03453 ast_waitstream(chan, ""); 03454 ast_variables_destroy(var); 03455 return NULL; 03456 } 03457 03458 for (origvar = var; var; var = var->next) { 03459 if (!strcasecmp(var->name, "pin")) { 03460 pin = ast_strdupa(var->value); 03461 } else if (!strcasecmp(var->name, "adminpin")) { 03462 pinadmin = ast_strdupa(var->value); 03463 } else if (!strcasecmp(var->name, "bookId")) { 03464 ast_copy_string(bookid, var->value, sizeof(bookid)); 03465 } else if (!strcasecmp(var->name, "opts")) { 03466 ast_copy_string(useropts, var->value, sizeof(char[OPTIONS_LEN + 1])); 03467 } else if (!strcasecmp(var->name, "maxusers")) { 03468 maxusers = atoi(var->value); 03469 } else if (!strcasecmp(var->name, "adminopts")) { 03470 ast_copy_string(adminopts, var->value, sizeof(char[OPTIONS_LEN + 1])); 03471 } else if (!strcasecmp(var->name, "recordingfilename")) { 03472 ast_copy_string(recordingfilename, var->value, sizeof(recordingfilename)); 03473 } else if (!strcasecmp(var->name, "recordingformat")) { 03474 ast_copy_string(recordingformat, var->value, sizeof(recordingformat)); 03475 } else if (!strcasecmp(var->name, "endtime")) { 03476 struct ast_tm endtime_tm; 03477 ast_strptime(var->value, "%Y-%m-%d %H:%M:%S", &endtime_tm); 03478 endtime = ast_mktime(&endtime_tm, NULL); 03479 } 03480 } 03481 03482 ast_variables_destroy(origvar); 03483 03484 cnf = build_conf(confno, pin ? pin : "", pinadmin ? pinadmin : "", make, dynamic, refcount, chan); 03485 03486 if (cnf) { 03487 cnf->maxusers = maxusers; 03488 cnf->endalert = endalert; 03489 cnf->endtime = endtime.tv_sec; 03490 cnf->useropts = ast_strdup(useropts); 03491 cnf->adminopts = ast_strdup(adminopts); 03492 cnf->bookid = ast_strdup(bookid); 03493 cnf->recordingfilename = ast_strdup(recordingfilename); 03494 cnf->recordingformat = ast_strdup(recordingformat); 03495 03496 if (strchr(cnf->useropts, 'r')) { 03497 if (ast_strlen_zero(recordingfilename)) { /* If the recordingfilename in the database is empty, use the channel definition or use the default. */ 03498 ast_channel_lock(chan); 03499 if ((var2 = pbx_builtin_getvar_helper(chan, "MEETME_RECORDINGFILE"))) { 03500 ast_free(cnf->recordingfilename); 03501 cnf->recordingfilename = ast_strdup(var2); 03502 } 03503 ast_channel_unlock(chan); 03504 if (ast_strlen_zero(cnf->recordingfilename)) { 03505 snprintf(recordingtmp, sizeof(recordingtmp), "meetme-conf-rec-%s-%s", cnf->confno, chan->uniqueid); 03506 ast_free(cnf->recordingfilename); 03507 cnf->recordingfilename = ast_strdup(recordingtmp); 03508 } 03509 } 03510 if (ast_strlen_zero(cnf->recordingformat)) {/* If the recording format is empty, use the wav as default */ 03511 ast_channel_lock(chan); 03512 if ((var2 = pbx_builtin_getvar_helper(chan, "MEETME_RECORDINGFORMAT"))) { 03513 ast_free(cnf->recordingformat); 03514 cnf->recordingformat = ast_strdup(var2); 03515 } 03516 ast_channel_unlock(chan); 03517 if (ast_strlen_zero(cnf->recordingformat)) { 03518 ast_free(cnf->recordingformat); 03519 cnf->recordingformat = ast_strdup("wav"); 03520 } 03521 } 03522 ast_verb(4, "Starting recording of MeetMe Conference %s into file %s.%s.\n", cnf->confno, cnf->recordingfilename, cnf->recordingformat); 03523 } 03524 } 03525 } 03526 03527 if (cnf) { 03528 if (confflags && !cnf->chan && 03529 !ast_test_flag(confflags, CONFFLAG_QUIET) && 03530 ast_test_flag(confflags, CONFFLAG_INTROUSER | CONFFLAG_INTROUSERNOREVIEW)) { 03531 ast_log(LOG_WARNING, "No DAHDI channel available for conference, user introduction disabled (is chan_dahdi loaded?)\n"); 03532 ast_clear_flag(confflags, CONFFLAG_INTROUSER | CONFFLAG_INTROUSERNOREVIEW); 03533 } 03534 03535 if (confflags && !cnf->chan && 03536 ast_test_flag(confflags, CONFFLAG_RECORDCONF)) { 03537 ast_log(LOG_WARNING, "No DAHDI channel available for conference, conference recording disabled (is chan_dahdi loaded?)\n"); 03538 ast_clear_flag(confflags, CONFFLAG_RECORDCONF); 03539 } 03540 } 03541 03542 return cnf; 03543 }
| static struct ast_conf_user* find_user | ( | struct ast_conference * | conf, | |
| char * | callerident | |||
| ) | [static, read] |
Definition at line 3952 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().
03953 { 03954 struct ast_conf_user *user = NULL; 03955 int cid; 03956 03957 sscanf(callerident, "%30i", &cid); 03958 if (conf && callerident) { 03959 AST_LIST_TRAVERSE(&conf->userlist, user, list) { 03960 if (cid == user->user_no) 03961 return user; 03962 } 03963 } 03964 return NULL; 03965 }
| static const char* get_announce_filename | ( | enum announcetypes | type | ) | [static] |
Definition at line 1893 of file app_meetme.c.
References CONF_HASJOIN, and CONF_HASLEFT.
Referenced by announce_thread().
01894 { 01895 switch (type) { 01896 case CONF_HASLEFT: 01897 return "conf-hasleft"; 01898 break; 01899 case CONF_HASJOIN: 01900 return "conf-hasjoin"; 01901 break; 01902 default: 01903 return ""; 01904 } 01905 }
| static char* istalking | ( | int | x | ) | [static] |
Definition at line 885 of file app_meetme.c.
Referenced by meetme_show_cmd().
| static int load_config | ( | int | reload | ) | [static] |
Definition at line 6421 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().
06422 { 06423 load_config_meetme(); 06424 06425 if (reload) { 06426 sla_queue_event(SLA_EVENT_RELOAD); 06427 ast_log(LOG_NOTICE, "A reload of the SLA configuration has been requested " 06428 "and will be completed when the system is idle.\n"); 06429 return 0; 06430 } 06431 06432 return sla_load_config(0); 06433 }
| static void load_config_meetme | ( | void | ) | [static] |
Definition at line 4446 of file app_meetme.c.
References ast_config_destroy(), ast_config_load, ast_log(), ast_true(), ast_variable_retrieve(), CONFIG_FILE_NAME, CONFIG_STATUS_FILEINVALID, DEFAULT_AUDIO_BUFFERS, LOG_ERROR, LOG_NOTICE, and LOG_WARNING.
Referenced by load_config().
04447 { 04448 struct ast_config *cfg; 04449 struct ast_flags config_flags = { 0 }; 04450 const char *val; 04451 04452 if (!(cfg = ast_config_load(CONFIG_FILE_NAME, config_flags))) { 04453 return; 04454 } else if (cfg == CONFIG_STATUS_FILEINVALID) { 04455 ast_log(LOG_ERROR, "Config file " CONFIG_FILE_NAME " is in an invalid format. Aborting.\n"); 04456 return; 04457 } 04458 04459 audio_buffers = DEFAULT_AUDIO_BUFFERS; 04460 04461 /* Scheduling support is off by default */ 04462 rt_schedule = 0; 04463 fuzzystart = 0; 04464 earlyalert = 0; 04465 endalert = 0; 04466 extendby = 0; 04467 04468 /* Logging of participants defaults to ON for compatibility reasons */ 04469 rt_log_members = 1; 04470 04471 if ((val = ast_variable_retrieve(cfg, "general", "audiobuffers"))) { 04472 if ((sscanf(val, "%30d", &audio_buffers) != 1)) { 04473 ast_log(LOG_WARNING, "audiobuffers setting must be a number, not '%s'\n", val); 04474 audio_buffers = DEFAULT_AUDIO_BUFFERS; 04475 } else if ((audio_buffers < DAHDI_DEFAULT_NUM_BUFS) || (audio_buffers > DAHDI_MAX_NUM_BUFS)) { 04476 ast_log(LOG_WARNING, "audiobuffers setting must be between %d and %d\n", 04477 DAHDI_DEFAULT_NUM_BUFS, DAHDI_MAX_NUM_BUFS); 04478 audio_buffers = DEFAULT_AUDIO_BUFFERS; 04479 } 04480 if (audio_buffers != DEFAULT_AUDIO_BUFFERS) 04481 ast_log(LOG_NOTICE, "Audio buffers per channel set to %d\n", audio_buffers); 04482 } 04483 04484 if ((val = ast_variable_retrieve(cfg, "general", "schedule"))) 04485 rt_schedule = ast_true(val); 04486 if ((val = ast_variable_retrieve(cfg, "general", "logmembercount"))) 04487 rt_log_members = ast_true(val); 04488 if ((val = ast_variable_retrieve(cfg, "general", "fuzzystart"))) { 04489 if ((sscanf(val, "%30d", &fuzzystart) != 1)) { 04490 ast_log(LOG_WARNING, "fuzzystart must be a number, not '%s'\n", val); 04491 fuzzystart = 0; 04492 } 04493 } 04494 if ((val = ast_variable_retrieve(cfg, "general", "earlyalert"))) { 04495 if ((sscanf(val, "%30d", &earlyalert) != 1)) { 04496 ast_log(LOG_WARNING, "earlyalert must be a number, not '%s'\n", val); 04497 earlyalert = 0; 04498 } 04499 } 04500 if ((val = ast_variable_retrieve(cfg, "general", "endalert"))) { 04501 if ((sscanf(val, "%30d", &endalert) != 1)) { 04502 ast_log(LOG_WARNING, "endalert must be a number, not '%s'\n", val); 04503 endalert = 0; 04504 } 04505 } 04506 if ((val = ast_variable_retrieve(cfg, "general", "extendby"))) { 04507 if ((sscanf(val, "%30d", &extendby) != 1)) { 04508 ast_log(LOG_WARNING, "extendby must be a number, not '%s'\n", val); 04509 extendby = 0; 04510 } 04511 } 04512 04513 ast_config_destroy(cfg); 04514 }
| static int load_module | ( | void | ) | [static] |
Definition at line 6461 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_xml, 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().
06462 { 06463 int res = 0; 06464 06465 res |= load_config(0); 06466 06467 ast_cli_register_multiple(cli_meetme, ARRAY_LEN(cli_meetme)); 06468 res |= ast_manager_register("MeetmeMute", EVENT_FLAG_CALL, 06469 action_meetmemute, "Mute a Meetme user"); 06470 res |= ast_manager_register("MeetmeUnmute", EVENT_FLAG_CALL, 06471 action_meetmeunmute, "Unmute a Meetme user"); 06472 res |= ast_manager_register2("MeetmeList", EVENT_FLAG_REPORTING, 06473 action_meetmelist, "List participants in a conference", mandescr_meetmelist); 06474 res |= ast_register_application_xml(app4, channel_admin_exec); 06475 res |= ast_register_application_xml(app3, admin_exec); 06476 res |= ast_register_application_xml(app2, count_exec); 06477 res |= ast_register_application_xml(app, conf_exec); 06478 res |= ast_register_application_xml(slastation_app, sla_station_exec); 06479 res |= ast_register_application_xml(slatrunk_app, sla_trunk_exec); 06480 06481 res |= ast_devstate_prov_add("Meetme", meetmestate); 06482 res |= ast_devstate_prov_add("SLA", sla_state); 06483 06484 res |= ast_custom_function_register(&meetme_info_acf); 06485 ast_realtime_require_field("meetme", "confno", RQ_UINTEGER2, 3, "members", RQ_UINTEGER1, 3, NULL); 06486 06487 return res; 06488 }
| static char* meetme_cmd | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 1363 of file app_meetme.c.
References admin_exec(), ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_debug, ast_free, ast_str_append(), ast_str_buffer(), ast_str_create(), ast_str_set(), CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_meetmecmd(), ast_cli_args::fd, ast_cli_args::line, MAX_CONFNUM, ast_cli_args::n, ast_cli_args::pos, ast_cli_entry::usage, and ast_cli_args::word.
01364 { 01365 /* Process the command */ 01366 struct ast_str *cmdline = NULL; 01367 int i = 0; 01368 01369 switch (cmd) { 01370 case CLI_INIT: 01371 e->command = "meetme {lock|unlock|mute|unmute|kick}"; 01372 e->usage = 01373 "Usage: meetme (un)lock|(un)mute|kick <confno> <usernumber>\n" 01374 " Executes a command for the conference or on a conferee\n"; 01375 return NULL; 01376 case CLI_GENERATE: 01377 return complete_meetmecmd(a->line, a->word, a->pos, a->n); 01378 } 01379 01380 if (a->argc > 8) 01381 ast_cli(a->fd, "Invalid Arguments.\n"); 01382 /* Check for length so no buffer will overflow... */ 01383 for (i = 0; i < a->argc; i++) { 01384 if (strlen(a->argv[i]) > 100) 01385 ast_cli(a->fd, "Invalid Arguments.\n"); 01386 } 01387 01388 /* Max confno length */ 01389 if (!(cmdline = ast_str_create(MAX_CONFNUM))) { 01390 return CLI_FAILURE; 01391 } 01392 01393 if (a->argc < 1) { 01394 ast_free(cmdline); 01395 return CLI_SHOWUSAGE; 01396 } 01397 01398 ast_str_set(&cmdline, 0, "%s", a->argv[2]); /* Argv 2: conference number */ 01399 if (strstr(a->argv[1], "lock")) { 01400 if (strcmp(a->argv[1], "lock") == 0) { 01401 /* Lock */ 01402 ast_str_append(&cmdline, 0, ",L"); 01403 } else { 01404 /* Unlock */ 01405 ast_str_append(&cmdline, 0, ",l"); 01406 } 01407 } else if (strstr(a->argv[1], "mute")) { 01408 if (a->argc < 4) { 01409 ast_free(cmdline); 01410 return CLI_SHOWUSAGE; 01411 } 01412 if (strcmp(a->argv[1], "mute") == 0) { 01413 /* Mute */ 01414 if (strcmp(a->argv[3], "all") == 0) { 01415 ast_str_append(&cmdline, 0, ",N"); 01416 } else { 01417 ast_str_append(&cmdline, 0, ",M,%s", a->argv[3]); 01418 } 01419 } else { 01420 /* Unmute */ 01421 if (strcmp(a->argv[3], "all") == 0) { 01422 ast_str_append(&cmdline, 0, ",n"); 01423 } else { 01424 ast_str_append(&cmdline, 0, ",m,%s", a->argv[3]); 01425 } 01426 } 01427 } else if (strcmp(a->argv[1], "kick") == 0) { 01428 if (a->argc < 4) { 01429 ast_free(cmdline); 01430 return CLI_SHOWUSAGE; 01431 } 01432 if (strcmp(a->argv[3], "all") == 0) { 01433 /* Kick all */ 01434 ast_str_append(&cmdline, 0, ",K"); 01435 } else { 01436 /* Kick a single user */ 01437 ast_str_append(&cmdline, 0, ",k,%s", a->argv[3]); 01438 } 01439 } else { 01440 ast_free(cmdline); 01441 return CLI_SHOWUSAGE; 01442 } 01443 01444 ast_debug(1, "Cmdline: %s\n", ast_str_buffer(cmdline)); 01445 01446 admin_exec(NULL, ast_str_buffer(cmdline)); 01447 ast_free(cmdline); 01448 01449 return CLI_SUCCESS; 01450 }
| static char* meetme_show_cmd | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 1209 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_buffer(), 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_channel::name, ast_cli_args::pos, S_OR, sec, ast_conference::start, 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.
01210 { 01211 /* Process the command */ 01212 struct ast_conf_user *user; 01213 struct ast_conference *cnf; 01214 int hr, min, sec; 01215 int i = 0, total = 0; 01216 time_t now; 01217 struct ast_str *cmdline = NULL; 01218 #define MC_HEADER_FORMAT "%-14s %-14s %-10s %-8s %-8s %-6s\n" 01219 #define MC_DATA_FORMAT "%-12.12s %4.4d %4.4s %02d:%02d:%02d %-8s %-6s\n" 01220 01221 switch (cmd) { 01222 case CLI_INIT: 01223 e->command = "meetme list [concise]"; 01224 e->usage = 01225 "Usage: meetme list [concise] <confno> \n" 01226 " List all or a specific conference.\n"; 01227 return NULL; 01228 case CLI_GENERATE: 01229 return complete_meetmecmd(a->line, a->word, a->pos, a->n); 01230 } 01231 01232 /* Check for length so no buffer will overflow... */ 01233 for (i = 0; i < a->argc; i++) { 01234 if (strlen(a->argv[i]) > 100) 01235 ast_cli(a->fd, "Invalid Arguments.\n"); 01236 } 01237 01238 /* Max confno length */ 01239 if (!(cmdline = ast_str_create(MAX_CONFNUM))) { 01240 return CLI_FAILURE; 01241 } 01242 01243 if (a->argc == 2 || (a->argc == 3 && !strcasecmp(a->argv[2], "concise"))) { 01244 /* List all the conferences */ 01245 int concise = (a->argc == 3 && !strcasecmp(a->argv[2], "concise")); 01246 now = time(NULL); 01247 AST_LIST_LOCK(&confs); 01248 if (AST_LIST_EMPTY(&confs)) { 01249 if (!concise) { 01250 ast_cli(a->fd, "No active MeetMe conferences.\n"); 01251 } 01252 AST_LIST_UNLOCK(&confs); 01253 ast_free(cmdline); 01254 return CLI_SUCCESS; 01255 } 01256 if (!concise) { 01257 ast_cli(a->fd, MC_HEADER_FORMAT, "Conf Num", "Parties", "Marked", "Activity", "Creation", "Locked"); 01258 } 01259 AST_LIST_TRAVERSE(&confs, cnf, list) { 01260 if (cnf->markedusers == 0) { 01261 ast_str_set(&cmdline, 0, "N/A "); 01262 } else { 01263 ast_str_set(&cmdline, 0, "%4.4d", cnf->markedusers); 01264 } 01265 hr = (now - cnf->start) / 3600; 01266 min = ((now - cnf->start) % 3600) / 60; 01267 sec = (now - cnf->start) % 60; 01268 if (!concise) { 01269 ast_cli(a->fd, MC_DATA_FORMAT, cnf->confno, cnf->users, ast_str_buffer(cmdline), hr, min, sec, cnf->isdynamic ? "Dynamic" : "Static", cnf->locked ? "Yes" : "No"); 01270 } else { 01271 ast_cli(a->fd, "%s!%d!%d!%02d:%02d:%02d!%d!%d\n", 01272 cnf->confno, 01273 cnf->users, 01274 cnf->markedusers, 01275 hr, min, sec, 01276 cnf->isdynamic, 01277 cnf->locked); 01278 } 01279 01280 total += cnf->users; 01281 } 01282 AST_LIST_UNLOCK(&confs); 01283 if (!concise) { 01284 ast_cli(a->fd, "* Total number of MeetMe users: %d\n", total); 01285 } 01286 ast_free(cmdline); 01287 return CLI_SUCCESS; 01288 } else if (strcmp(a->argv[1], "list") == 0) { 01289 int concise = (a->argc == 4 && (!strcasecmp(a->argv[3], "concise"))); 01290 /* List all the users in a conference */ 01291 if (AST_LIST_EMPTY(&confs)) { 01292 if (!concise) { 01293 ast_cli(a->fd, "No active MeetMe conferences.\n"); 01294 } 01295 ast_free(cmdline); 01296 return CLI_SUCCESS; 01297 } 01298 /* Find the right conference */ 01299 AST_LIST_LOCK(&confs); 01300 AST_LIST_TRAVERSE(&confs, cnf, list) { 01301 if (strcmp(cnf->confno, a->argv[2]) == 0) { 01302 break; 01303 } 01304 } 01305 if (!cnf) { 01306 if (!concise) 01307 ast_cli(a->fd, "No such conference: %s.\n", a->argv[2]); 01308 AST_LIST_UNLOCK(&confs); 01309 ast_free(cmdline); 01310 return CLI_SUCCESS; 01311 } 01312 /* Show all the users */ 01313 time(&now); 01314 AST_LIST_TRAVERSE(&cnf->userlist, user, list) { 01315 hr = (now - user->jointime) / 3600; 01316 min = ((now - user->jointime) % 3600) / 60; 01317 sec = (now - user->jointime) % 60; 01318 if (!concise) { 01319 ast_cli(a->fd, "User #: %-2.2d %12.12s %-20.20s Channel: %s %s %s %s %s %s %02d:%02d:%02d\n", 01320 user->user_no, 01321 S_OR(user->chan->cid.cid_num, "<unknown>"), 01322 S_OR(user->chan->cid.cid_name, "<no name>"), 01323 user->chan->name, 01324 user->userflags & CONFFLAG_ADMIN ? "(Admin)" : "", 01325 user->userflags & CONFFLAG_MONITOR ? "(Listen only)" : "", 01326 user->adminflags & ADMINFLAG_MUTED ? "(Admin Muted)" : user->adminflags & ADMINFLAG_SELFMUTED ? "(Muted)" : "", 01327 user->adminflags & ADMINFLAG_T_REQUEST ? "(Request to Talk)" : "", 01328 istalking(user->talking), hr, min, sec); 01329 } else { 01330 ast_cli(a->fd, "%d!%s!%s!%s!%s!%s!%s!%s!%d!%02d:%02d:%02d\n", 01331 user->user_no, 01332 S_OR(user->chan->cid.cid_num, ""), 01333 S_OR(user->chan->cid.cid_name, ""), 01334 user->chan->name, 01335 user->userflags & CONFFLAG_ADMIN ? "1" : "", 01336 user->userflags & CONFFLAG_MONITOR ? "1" : "", 01337 user->adminflags & (ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED) ? "1" : "", 01338 user->adminflags & ADMINFLAG_T_REQUEST ? "1" : "", 01339 user->talking, hr, min, sec); 01340 } 01341 } 01342 if (!concise) { 01343 ast_cli(a->fd, "%d users in that conference.\n", cnf->users); 01344 } 01345 AST_LIST_UNLOCK(&confs); 01346 ast_free(cmdline); 01347 return CLI_SUCCESS; 01348 } 01349 if (a->argc < 2) { 01350 ast_free(cmdline); 01351 return CLI_SHOWUSAGE; 01352 } 01353 01354 ast_debug(1, "Cmdline: %s\n", ast_str_buffer(cmdline)); 01355 01356 admin_exec(NULL, ast_str_buffer(cmdline)); 01357 ast_free(cmdline); 01358 01359 return CLI_SUCCESS; 01360 }
| static int meetmemute | ( | struct mansession * | s, | |
| const struct message * | m, | |||
| int | mute | |||
| ) | [static] |
Definition at line 4213 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_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), ast_conf_user::chan, ast_conference::confno, ast_conf_user::list, LOG_NOTICE, ast_channel::name, ast_channel::uniqueid, ast_conf_user::user_no, and ast_conference::userlist.
Referenced by action_meetmemute(), and action_meetmeunmute().
04214 { 04215 struct ast_conference *conf; 04216 struct ast_conf_user *user; 04217 const char *confid = astman_get_header(m, "Meetme"); 04218 char *userid = ast_strdupa(astman_get_header(m, "Usernum")); 04219 int userno; 04220 04221 if (ast_strlen_zero(confid)) { 04222 astman_send_error(s, m, "Meetme conference not specified"); 04223 return 0; 04224 } 04225 04226 if (ast_strlen_zero(userid)) { 04227 astman_send_error(s, m, "Meetme user number not specified"); 04228 return 0; 04229 } 04230 04231 userno = strtoul(userid, &userid, 10); 04232 04233 if (*userid) { 04234 astman_send_error(s, m, "Invalid user number"); 04235 return 0; 04236 } 04237 04238 /* Look in the conference list */ 04239 AST_LIST_LOCK(&confs); 04240 AST_LIST_TRAVERSE(&confs, conf, list) { 04241 if (!strcmp(confid, conf->confno)) 04242 break; 04243 } 04244 04245 if (!conf) { 04246 AST_LIST_UNLOCK(&confs); 04247 astman_send_error(s, m, "Meetme conference does not exist"); 04248 return 0; 04249 } 04250 04251 AST_LIST_TRAVERSE(&conf->userlist, user, list) 04252 if (user->user_no == userno) 04253 break; 04254 04255 if (!user) { 04256 AST_LIST_UNLOCK(&confs); 04257 astman_send_error(s, m, "User number not found"); 04258 return 0; 04259 } 04260 04261 if (mute) 04262 user->adminflags |= ADMINFLAG_MUTED; /* request user muting */ 04263 else 04264 user->adminflags &= ~(ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED | ADMINFLAG_T_REQUEST); /* request user unmuting */ 04265 04266 AST_LIST_UNLOCK(&confs); 04267 04268 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); 04269 04270 astman_send_ack(s, m, mute ? "User muted" : "User unmuted"); 04271 return 0; 04272 }
| static enum ast_device_state meetmestate | ( | const char * | data | ) | [static] |
Callback for devicestate providers.
Definition at line 4424 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().
04425 { 04426 struct ast_conference *conf; 04427 04428 /* Find conference */ 04429 AST_LIST_LOCK(&confs); 04430 AST_LIST_TRAVERSE(&confs, conf, list) { 04431 if (!strcmp(data, conf->confno)) 04432 break; 04433 } 04434 AST_LIST_UNLOCK(&confs); 04435 if (!conf) 04436 return AST_DEVICE_INVALID; 04437 04438 04439 /* SKREP to fill */ 04440 if (!conf->users) 04441 return AST_DEVICE_NOT_INUSE; 04442 04443 return AST_DEVICE_INUSE; 04444 }
| static struct sla_ringing_trunk* queue_ringing_trunk | ( | struct sla_trunk * | trunk | ) | [static, read] |
Definition at line 5774 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().
05775 { 05776 struct sla_ringing_trunk *ringing_trunk; 05777 05778 if (!(ringing_trunk = ast_calloc(1, sizeof(*ringing_trunk)))) 05779 return NULL; 05780 05781 ringing_trunk->trunk = trunk; 05782 ringing_trunk->ring_begin = ast_tvnow(); 05783 05784 sla_change_trunk_state(trunk, SLA_TRUNK_STATE_RINGING, ALL_TRUNK_REFS, NULL); 05785 05786 ast_mutex_lock(&sla.lock); 05787 AST_LIST_INSERT_HEAD(&sla.ringing_trunks, ringing_trunk, entry); 05788 ast_mutex_unlock(&sla.lock); 05789 05790 sla_queue_event(SLA_EVENT_RINGING_TRUNK); 05791 05792 return ringing_trunk; 05793 }
| static void * recordthread | ( | void * | args | ) | [static] |
Definition at line 4359 of file app_meetme.c.
References ast_closestream(), 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.
04360 { 04361 struct ast_conference *cnf = args; 04362 struct ast_frame *f = NULL; 04363 int flags; 04364 struct ast_filestream *s = NULL; 04365 int res = 0; 04366 int x; 04367 const char *oldrecordingfilename = NULL; 04368 04369 if (!cnf || !cnf->lchan) { 04370 pthread_exit(0); 04371 } 04372 04373 ast_stopstream(cnf->lchan); 04374 flags = O_CREAT | O_TRUNC | O_WRONLY; 04375 04376 04377 cnf->recording = MEETME_RECORD_ACTIVE; 04378 while (ast_waitfor(cnf->lchan, -1) > -1) { 04379 if (cnf->recording == MEETME_RECORD_TERMINATE) { 04380 AST_LIST_LOCK(&confs); 04381 AST_LIST_UNLOCK(&confs); 04382 break; 04383 } 04384 if (!s && cnf->recordingfilename && (cnf->recordingfilename != oldrecordingfilename)) { 04385 s = ast_writefile(cnf->recordingfilename, cnf->recordingformat, NULL, flags, 0, AST_FILE_MODE); 04386 oldrecordingfilename = cnf->recordingfilename; 04387 } 04388 04389 f = ast_read(cnf->lchan); 04390 if (!f) { 04391 res = -1; 04392 break; 04393 } 04394 if (f->frametype == AST_FRAME_VOICE) { 04395 ast_mutex_lock(&cnf->listenlock); 04396 for (x = 0; x < AST_FRAME_BITS; x++) { 04397 /* Free any translations that have occured */ 04398 if (cnf->transframe[x]) { 04399 ast_frfree(cnf->transframe[x]); 04400 cnf->transframe[x] = NULL; 04401 } 04402 } 04403 if (cnf->origframe) 04404 ast_frfree(cnf->origframe); 04405 cnf->origframe = ast_frdup(f); 04406 ast_mutex_unlock(&cnf->listenlock); 04407 if (s) 04408 res = ast_writestream(s, f); 04409 if (res) { 04410 ast_frfree(f); 04411 break; 04412 } 04413 } 04414 ast_frfree(f); 04415 } 04416 cnf->recording = MEETME_RECORD_OFF; 04417 if (s) 04418 ast_closestream(s); 04419 04420 pthread_exit(0); 04421 }
| static int reload | ( | void | ) | [static] |
Definition at line 6490 of file app_meetme.c.
References ast_unload_realtime(), and load_config().
06491 { 06492 ast_unload_realtime("meetme"); 06493 return load_config(1); 06494 }
| static void reset_volumes | ( | struct ast_conf_user * | user | ) | [static] |
Definition at line 1005 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().
01006 { 01007 signed char zero_volume = 0; 01008 01009 ast_channel_setoption(user->chan, AST_OPTION_TXGAIN, &zero_volume, sizeof(zero_volume), 0); 01010 ast_channel_setoption(user->chan, AST_OPTION_RXGAIN, &zero_volume, sizeof(zero_volume), 0); 01011 }
| static int rt_extend_conf | ( | char * | confno | ) | [static] |
Definition at line 1815 of file app_meetme.c.
References ast_copy_string(), ast_debug, ast_load_realtime(), ast_localtime(), ast_mktime(), ast_strftime(), ast_strptime(), ast_tvnow(), ast_update_realtime(), ast_variables_destroy(), DATE_FORMAT, ast_variable::name, ast_variable::next, ast_variable::value, and var.
Referenced by admin_exec(), and conf_run().
01816 { 01817 char currenttime[32]; 01818 char endtime[32]; 01819 struct timeval now; 01820 struct ast_tm tm; 01821 struct ast_variable *var, *orig_var; 01822 char bookid[51]; 01823 01824 if (!extendby) { 01825 return 0; 01826 } 01827 01828 now = ast_tvnow(); 01829 01830 ast_localtime(&now, &tm, NULL); 01831 ast_strftime(currenttime, sizeof(currenttime), DATE_FORMAT, &tm); 01832 01833 var = ast_load_realtime("meetme", "confno", 01834 confno, "startTime<= ", currenttime, 01835 "endtime>= ", currenttime, NULL); 01836 01837 orig_var = var; 01838 01839 /* Identify the specific RealTime conference */ 01840 while (var) { 01841 if (!strcasecmp(var->name, "bookid")) { 01842 ast_copy_string(bookid, var->value, sizeof(bookid)); 01843 } 01844 if (!strcasecmp(var->name, "endtime")) { 01845 ast_copy_string(endtime, var->value, sizeof(endtime)); 01846 } 01847 01848 var = var->next; 01849 } 01850 ast_variables_destroy(orig_var); 01851 01852 ast_strptime(endtime, DATE_FORMAT, &tm); 01853 now = ast_mktime(&tm, NULL); 01854 01855 now.tv_sec += extendby; 01856 01857 ast_localtime(&now, &tm, NULL); 01858 ast_strftime(currenttime, sizeof(currenttime), DATE_FORMAT, &tm); 01859 strcat(currenttime, "0"); /* Seconds needs to be 00 */ 01860 01861 var = ast_load_realtime("meetme", "confno", 01862 confno, "startTime<= ", currenttime, 01863 "endtime>= ", currenttime, NULL); 01864 01865 /* If there is no conflict with extending the conference, update the DB */ 01866 if (!var) { 01867 ast_debug(3, "Trying to update the endtime of Conference %s to %s\n", confno, currenttime); 01868 ast_update_realtime("meetme", "bookid", bookid, "endtime", currenttime, NULL); 01869 return 0; 01870 01871 } 01872 01873 ast_variables_destroy(var); 01874 return -1; 01875 }
| static void* run_station | ( | void * | data | ) | [static] |
Definition at line 4673 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_buffer(), 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, sla_trunk_ref::trunk, and run_station_args::trunk_ref.
Referenced by sla_handle_dial_state_event().
04674 { 04675 struct sla_station *station; 04676 struct sla_trunk_ref *trunk_ref; 04677 struct ast_str *conf_name = ast_str_create(16); 04678 struct ast_flags conf_flags = { 0 }; 04679 struct ast_conference *conf; 04680 04681 { 04682 struct run_station_args *args = data; 04683 station = args->station; 04684 trunk_ref = args->trunk_ref; 04685 ast_mutex_lock(args->cond_lock); 04686 ast_cond_signal(args->cond); 04687 ast_mutex_unlock(args->cond_lock); 04688 /* args is no longer valid here. */ 04689 } 04690 04691 ast_atomic_fetchadd_int((int *) &trunk_ref->trunk->active_stations, 1); 04692 ast_str_set(&conf_name, 0, "SLA_%s", trunk_ref->trunk->name); 04693 ast_set_flag(&conf_flags, 04694 CONFFLAG_QUIET | CONFFLAG_MARKEDEXIT | CONFFLAG_PASS_DTMF | CONFFLAG_SLA_STATION); 04695 answer_trunk_chan(trunk_ref->chan); 04696 conf = build_conf(ast_str_buffer(conf_name), "", "", 0, 0, 1, trunk_ref->chan); 04697 if (conf) { 04698 conf_run(trunk_ref->chan, conf, conf_flags.flags, NULL); 04699 dispose_conf(conf); 04700 conf = NULL; 04701 } 04702 trunk_ref->chan = NULL; 04703 if (ast_atomic_dec_and_test((int *) &trunk_ref->trunk->active_stations) && 04704 trunk_ref->state != SLA_TRUNK_STATE_ONHOLD_BYME) { 04705 ast_str_append(&conf_name, 0, ",K"); 04706 admin_exec(NULL, ast_str_buffer(conf_name)); 04707 trunk_ref->trunk->hold_stations = 0; 04708 sla_change_trunk_state(trunk_ref->trunk, SLA_TRUNK_STATE_IDLE, ALL_TRUNK_REFS, NULL); 04709 } 04710 04711 ast_dial_join(station->dial); 04712 ast_dial_destroy(station->dial); 04713 station->dial = NULL; 04714 ast_free(conf_name); 04715 04716 return NULL; 04717 }
| static void send_talking_event | ( | struct ast_channel * | chan, | |
| struct ast_conference * | conf, | |||
| struct ast_conf_user * | user, | |||
| int | talking | |||
| ) | [static] |
Definition at line 1969 of file app_meetme.c.
References ast_conference::confno, EVENT_FLAG_CALL, manager_event, ast_channel::name, ast_channel::uniqueid, and ast_conf_user::user_no.
Referenced by set_user_talking().
01970 { 01971 manager_event(EVENT_FLAG_CALL, "MeetmeTalking", 01972 "Channel: %s\r\n" 01973 "Uniqueid: %s\r\n" 01974 "Meetme: %s\r\n" 01975 "Usernum: %d\r\n" 01976 "Status: %s\r\n", 01977 chan->name, chan->uniqueid, conf->confno, user->user_no, talking ? "on" : "off"); 01978 }
| static int set_listen_volume | ( | struct ast_conf_user * | user, | |
| int | volume | |||
| ) | [static] |
Definition at line 934 of file app_meetme.c.
References ast_channel_setoption(), AST_OPTION_TXGAIN, and ast_conf_user::chan.
Referenced by tweak_listen_volume().
00935 { 00936 char gain_adjust; 00937 00938 /* attempt to make the adjustment in the channel driver; 00939 if successful, don't adjust in the frame reading routine 00940 */ 00941 gain_adjust = gain_map[volume + 5]; 00942 00943 return ast_channel_setoption(user->chan, AST_OPTION_TXGAIN, &gain_adjust, sizeof(gain_adjust), 0); 00944 }
| static int set_talk_volume | ( | struct ast_conf_user * | user, | |
| int | volume | |||
| ) | [static] |
Definition at line 922 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().
00923 { 00924 char gain_adjust; 00925 00926 /* attempt to make the adjustment in the channel driver; 00927 if successful, don't adjust in the frame reading routine 00928 */ 00929 gain_adjust = gain_map[volume + 5]; 00930 00931 return ast_channel_setoption(user->chan, AST_OPTION_RXGAIN, &gain_adjust, sizeof(gain_adjust), 0); 00932 }
| static void set_user_talking | ( | struct ast_channel * | chan, | |
| struct ast_conference * | conf, | |||
| struct ast_conf_user * | user, | |||
| int | talking, | |||
| int | monitor | |||
| ) | [static] |
Definition at line 1980 of file app_meetme.c.
References send_talking_event(), and ast_conf_user::talking.
Referenced by conf_run().
01981 { 01982 int last_talking = user->talking; 01983 if (last_talking == talking) 01984 return; 01985 01986 user->talking = talking; 01987 01988 if (monitor) { 01989 /* Check if talking state changed. Take care of -1 which means unmonitored */ 01990 int was_talking = (last_talking > 0); 01991 int now_talking = (talking > 0); 01992 if (was_talking != now_talking) { 01993 send_talking_event(chan, conf, user, now_talking); 01994 } 01995 } 01996 }
| static void sla_add_trunk_to_station | ( | struct sla_station * | station, | |
| struct ast_variable * | var | |||
| ) | [static] |
Definition at line 6120 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, 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, sla_station::trunks, and ast_variable::value.
Referenced by sla_build_station().
06121 { 06122 struct sla_trunk *trunk; 06123 struct sla_trunk_ref *trunk_ref; 06124 struct sla_station_ref *station_ref; 06125 char *trunk_name, *options, *cur; 06126 06127 options = ast_strdupa(var->value); 06128 trunk_name = strsep(&options, ","); 06129 06130 AST_RWLIST_RDLOCK(&sla_trunks); 06131 AST_RWLIST_TRAVERSE(&sla_trunks, trunk, entry) { 06132 if (!strcasecmp(trunk->name, trunk_name)) 06133 break; 06134 } 06135 06136 AST_RWLIST_UNLOCK(&sla_trunks); 06137 if (!trunk) { 06138 ast_log(LOG_ERROR, "Trunk '%s' not found!\n", var->value); 06139 return; 06140 } 06141 if (!(trunk_ref = create_trunk_ref(trunk))) 06142 return; 06143 trunk_ref->state = SLA_TRUNK_STATE_IDLE; 06144 06145 while ((cur = strsep(&options, ","))) { 06146 char *name, *value = cur; 06147 name = strsep(&value, "="); 06148 if (!strcasecmp(name, "ringtimeout")) { 06149 if (sscanf(value, "%30u", &trunk_ref->ring_timeout) != 1) { 06150 ast_log(LOG_WARNING, "Invalid ringtimeout value '%s' for " 06151 "trunk '%s' on station '%s'\n", value, trunk->name, station->name); 06152 trunk_ref->ring_timeout = 0; 06153 } 06154 } else if (!strcasecmp(name, "ringdelay")) { 06155 if (sscanf(value, "%30u", &trunk_ref->ring_delay) != 1) { 06156 ast_log(LOG_WARNING, "Invalid ringdelay value '%s' for " 06157 "trunk '%s' on station '%s'\n", value, trunk->name, station->name); 06158 trunk_ref->ring_delay = 0; 06159 } 06160 } else { 06161 ast_log(LOG_WARNING, "Invalid option '%s' for " 06162 "trunk '%s' on station '%s'\n", name, trunk->name, station->name); 06163 } 06164 } 06165 06166 if (!(station_ref = sla_create_station_ref(station))) { 06167 ast_free(trunk_ref); 06168 return; 06169 } 06170 ast_atomic_fetchadd_int((int *) &trunk->num_stations, 1); 06171 AST_RWLIST_WRLOCK(&sla_trunks); 06172 AST_LIST_INSERT_TAIL(&trunk->stations, station_ref, entry); 06173 AST_RWLIST_UNLOCK(&sla_trunks); 06174 AST_LIST_INSERT_TAIL(&station->trunks, trunk_ref, entry); 06175 }
| static int sla_build_station | ( | struct ast_config * | cfg, | |
| const char * | cat | |||
| ) | [static] |
Definition at line 6177 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().
06178 { 06179 struct sla_station *station; 06180 struct ast_variable *var; 06181 const char *dev; 06182 06183 if (!(dev = ast_variable_retrieve(cfg, cat, "device"))) { 06184 ast_log(LOG_ERROR, "SLA Station '%s' defined with no device!\n", cat); 06185 return -1; 06186 } 06187 06188 if (!(station = ast_calloc(1, sizeof(*station)))) 06189 return -1; 06190 if (ast_string_field_init(station, 32)) { 06191 ast_free(station); 06192 return -1; 06193 } 06194 06195 ast_string_field_set(station, name, cat); 06196 ast_string_field_set(station, device, dev); 06197 06198 for (var = ast_variable_browse(cfg, cat); var; var = var->next) { 06199 if (!strcasecmp(var->name, "trunk")) 06200 sla_add_trunk_to_station(station, var); 06201 else if (!strcasecmp(var->name, "autocontext")) 06202 ast_string_field_set(station, autocontext, var->value); 06203 else if (!strcasecmp(var->name, "ringtimeout")) { 06204 if (sscanf(var->value, "%30u", &station->ring_timeout) != 1) { 06205 ast_log(LOG_WARNING, "Invalid ringtimeout '%s' specified for station '%s'\n", 06206 var->value, station->name); 06207 station->ring_timeout = 0; 06208 } 06209 } else if (!strcasecmp(var->name, "ringdelay")) { 06210 if (sscanf(var->value, "%30u", &station->ring_delay) != 1) { 06211 ast_log(LOG_WARNING, "Invalid ringdelay '%s' specified for station '%s'\n", 06212 var->value, station->name); 06213 station->ring_delay = 0; 06214 } 06215 } else if (!strcasecmp(var->name, "hold")) { 06216 if (!strcasecmp(var->value, "private")) 06217 station->hold_access = SLA_HOLD_PRIVATE; 06218 else if (!strcasecmp(var->value, "open")) 06219 station->hold_access = SLA_HOLD_OPEN; 06220 else { 06221 ast_log(LOG_WARNING, "Invalid value '%s' for hold on station %s\n", 06222 var->value, station->name); 06223 } 06224 06225 } else if (strcasecmp(var->name, "type") && strcasecmp(var->name, "device")) { 06226 ast_log(LOG_ERROR, "Invalid option '%s' specified at line %d of %s!\n", 06227 var->name, var->lineno, SLA_CONFIG_FILE); 06228 } 06229 } 06230 06231 if (!ast_strlen_zero(station->autocontext)) { 06232 struct ast_context *context; 06233 struct sla_trunk_ref *trunk_ref; 06234 context = ast_context_find_or_create(NULL, NULL, station->autocontext, sla_registrar); 06235 if (!context) { 06236 ast_log(LOG_ERROR, "Failed to automatically find or create " 06237 "context '%s' for SLA!\n", station->autocontext); 06238 destroy_station(station); 06239 return -1; 06240 } 06241 /* The extension for when the handset goes off-hook. 06242 * exten => station1,1,SLAStation(station1) */ 06243 if (ast_add_extension2(context, 0 /* don't replace */, station->name, 1, 06244 NULL, NULL, slastation_app, ast_strdup(station->name), ast_free_ptr, sla_registrar)) { 06245 ast_log(LOG_ERROR, "Failed to automatically create extension " 06246 "for trunk '%s'!\n", station->name); 06247 destroy_station(station); 06248 return -1; 06249 } 06250 AST_RWLIST_RDLOCK(&sla_trunks); 06251 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) { 06252 char exten[AST_MAX_EXTENSION]; 06253 char hint[AST_MAX_APP]; 06254 snprintf(exten, sizeof(exten), "%s_%s", station->name, trunk_ref->trunk->name); 06255 snprintf(hint, sizeof(hint), "SLA:%s", exten); 06256 /* Extension for this line button 06257 * exten => station1_line1,1,SLAStation(station1_line1) */ 06258 if (ast_add_extension2(context, 0 /* don't replace */, exten, 1, 06259 NULL, NULL, slastation_app, ast_strdup(exten), ast_free_ptr, sla_registrar)) { 06260 ast_log(LOG_ERROR, "Failed to automatically create extension " 06261 "for trunk '%s'!\n", station->name); 06262 destroy_station(station); 06263 return -1; 06264 } 06265 /* Hint for this line button 06266 * exten => station1_line1,hint,SLA:station1_line1 */ 06267 if (ast_add_extension2(context, 0 /* don't replace */, exten, PRIORITY_HINT, 06268 NULL, NULL, hint, NULL, NULL, sla_registrar)) { 06269 ast_log(LOG_ERROR, "Failed to automatically create hint " 06270 "for trunk '%s'!\n", station->name); 06271 destroy_station(station); 06272 return -1; 06273 } 06274 } 06275 AST_RWLIST_UNLOCK(&sla_trunks); 06276 } 06277 06278 AST_RWLIST_WRLOCK(&sla_stations); 06279 AST_RWLIST_INSERT_TAIL(&sla_stations, station, entry); 06280 AST_RWLIST_UNLOCK(&sla_stations); 06281 06282 return 0; 06283 }
| static int sla_build_trunk | ( | struct ast_config * | cfg, | |
| const char * | cat | |||
| ) | [static] |
Definition at line 6042 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().
06043 { 06044 struct sla_trunk *trunk; 06045 struct ast_variable *var; 06046 const char *dev; 06047 06048 if (!(dev = ast_variable_retrieve(cfg, cat, "device"))) { 06049 ast_log(LOG_ERROR, "SLA Trunk '%s' defined with no device!\n", cat); 06050 return -1; 06051 } 06052 06053 if (sla_check_device(dev)) { 06054 ast_log(LOG_ERROR, "SLA Trunk '%s' define with invalid device '%s'!\n", 06055 cat, dev); 06056 return -1; 06057 } 06058 06059 if (!(trunk = ast_calloc(1, sizeof(*trunk)))) 06060 return -1; 06061 if (ast_string_field_init(trunk, 32)) { 06062 ast_free(trunk); 06063 return -1; 06064 } 06065 06066 ast_string_field_set(trunk, name, cat); 06067 ast_string_field_set(trunk, device, dev); 06068 06069 for (var = ast_variable_browse(cfg, cat); var; var = var->next) { 06070 if (!strcasecmp(var->name, "autocontext")) 06071 ast_string_field_set(trunk, autocontext, var->value); 06072 else if (!strcasecmp(var->name, "ringtimeout")) { 06073 if (sscanf(var->value, "%30u", &trunk->ring_timeout) != 1) { 06074 ast_log(LOG_WARNING, "Invalid ringtimeout '%s' specified for trunk '%s'\n", 06075 var->value, trunk->name); 06076 trunk->ring_timeout = 0; 06077 } 06078 } else if (!strcasecmp(var->name, "barge")) 06079 trunk->barge_disabled = ast_false(var->value); 06080 else if (!strcasecmp(var->name, "hold")) { 06081 if (!strcasecmp(var->value, "private")) 06082 trunk->hold_access = SLA_HOLD_PRIVATE; 06083 else if (!strcasecmp(var->value, "open")) 06084 trunk->hold_access = SLA_HOLD_OPEN; 06085 else { 06086 ast_log(LOG_WARNING, "Invalid value '%s' for hold on trunk %s\n", 06087 var->value, trunk->name); 06088 } 06089 } else if (strcasecmp(var->name, "type") && strcasecmp(var->name, "device")) { 06090 ast_log(LOG_ERROR, "Invalid option '%s' specified at line %d of %s!\n", 06091 var->name, var->lineno, SLA_CONFIG_FILE); 06092 } 06093 } 06094 06095 if (!ast_strlen_zero(trunk->autocontext)) { 06096 struct ast_context *context; 06097 context = ast_context_find_or_create(NULL, NULL, trunk->autocontext, sla_registrar); 06098 if (!context) { 06099 ast_log(LOG_ERROR, "Failed to automatically find or create " 06100 "context '%s' for SLA!\n", trunk->autocontext); 06101 destroy_trunk(trunk); 06102 return -1; 06103 } 06104 if (ast_add_extension2(context, 0 /* don't replace */, "s", 1, 06105 NULL, NULL, slatrunk_app, ast_strdup(trunk->name), ast_free_ptr, sla_registrar)) { 06106 ast_log(LOG_ERROR, "Failed to automatically create extension " 06107 "for trunk '%s'!\n", trunk->name); 06108 destroy_trunk(trunk); 06109 return -1; 06110 } 06111 } 06112 06113 AST_RWLIST_WRLOCK(&sla_trunks); 06114 AST_RWLIST_INSERT_TAIL(&sla_trunks, trunk, entry); 06115 AST_RWLIST_UNLOCK(&sla_trunks); 06116 06117 return 0; 06118 }
| static int sla_calc_station_delays | ( | unsigned int * | timeout | ) | [static] |
Calculate the ring delay for a station.
Definition at line 5286 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().
05287 { 05288 struct sla_station *station; 05289 int res = 0; 05290 05291 AST_LIST_TRAVERSE(&sla_stations, station, entry) { 05292 struct sla_ringing_trunk *ringing_trunk; 05293 int time_left; 05294 05295 /* Ignore stations already ringing */ 05296 if (sla_check_ringing_station(station)) 05297 continue; 05298 05299 /* Ignore stations already on a call */ 05300 if (sla_check_inuse_station(station)) 05301 continue; 05302 05303 /* Ignore stations that don't have one of their trunks ringing */ 05304 if (!(ringing_trunk = sla_choose_ringing_trunk(station, NULL, 0))) 05305 continue; 05306 05307 if ((time_left = sla_check_station_delay(station, ringing_trunk)) == INT_MAX) 05308 continue; 05309 05310 /* If there is no time left, then the station needs to start ringing. 05311 * Return non-zero so that an event will be queued up an event to 05312 * make that happen. */ 05313 if (time_left <= 0) { 05314 res = 1; 05315 continue; 05316 } 05317 05318 if (time_left < *timeout) 05319 *timeout = time_left; 05320 } 05321 05322 return res; 05323 }
| static int sla_calc_station_timeouts | ( | unsigned int * | timeout | ) | [static] |
Process station ring timeouts.
Definition at line 5203 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().
05204 { 05205 struct sla_ringing_trunk *ringing_trunk; 05206 struct sla_ringing_station *ringing_station; 05207 int res = 0; 05208 05209 AST_LIST_TRAVERSE_SAFE_BEGIN(&sla.ringing_stations, ringing_station, entry) { 05210 unsigned int ring_timeout = 0; 05211 int time_elapsed, time_left = INT_MAX, final_trunk_time_left = INT_MIN; 05212 struct sla_trunk_ref *trunk_ref; 05213 05214 /* If there are any ring timeouts specified for a specific trunk 05215 * on the station, then use the highest per-trunk ring timeout. 05216 * Otherwise, use the ring timeout set for the entire station. */ 05217 AST_LIST_TRAVERSE(&ringing_station->station->trunks, trunk_ref, entry) { 05218 struct sla_station_ref *station_ref; 05219 int trunk_time_elapsed, trunk_time_left; 05220 05221 AST_LIST_TRAVERSE(&sla.ringing_trunks, ringing_trunk, entry) { 05222 if (ringing_trunk->trunk == trunk_ref->trunk) 05223 break; 05224 } 05225 if (!ringing_trunk) 05226 continue; 05227 05228 /* If there is a trunk that is ringing without a timeout, then the 05229 * only timeout that could matter is a global station ring timeout. */ 05230 if (!trunk_ref->ring_timeout) 05231 break; 05232 05233 /* This trunk on this station is ringing and has a timeout. 05234 * However, make sure this trunk isn't still ringing from a 05235 * previous timeout. If so, don't consider it. */ 05236 AST_LIST_TRAVERSE(&ringing_trunk->timed_out_stations, station_ref, entry) { 05237 if (station_ref->station == ringing_station->station) 05238 break; 05239 } 05240 if (station_ref) 05241 continue; 05242 05243 trunk_time_elapsed = ast_tvdiff_ms(ast_tvnow(), ringing_trunk->ring_begin); 05244 trunk_time_left = (trunk_ref->ring_timeout * 1000) - trunk_time_elapsed; 05245 if (trunk_time_left > final_trunk_time_left) 05246 final_trunk_time_left = trunk_time_left; 05247 } 05248 05249 /* No timeout was found for ringing trunks, and no timeout for the entire station */ 05250 if (final_trunk_time_left == INT_MIN && !ringing_station->station->ring_timeout) 05251 continue; 05252 05253 /* Compute how much time is left for a global station timeout */ 05254 if (ringing_station->station->ring_timeout) { 05255 ring_timeout = ringing_station->station->ring_timeout; 05256 time_elapsed = ast_tvdiff_ms(ast_tvnow(), ringing_station->ring_begin); 05257 time_left = (ring_timeout * 1000) - time_elapsed; 05258 } 05259 05260 /* If the time left based on the per-trunk timeouts is smaller than the 05261 * global station ring timeout, use that. */ 05262 if (final_trunk_time_left > INT_MIN && final_trunk_time_left < time_left) 05263 time_left = final_trunk_time_left; 05264 05265 /* If there is no time left, the station needs to stop ringing */ 05266 if (time_left <= 0) { 05267 AST_LIST_REMOVE_CURRENT(entry); 05268 sla_stop_ringing_station(ringing_station, SLA_STATION_HANGUP_TIMEOUT); 05269 res = 1; 05270 continue; 05271 } 05272 05273 /* There is still some time left for this station to ring, so save that 05274 * timeout if it is the first event scheduled to occur */ 05275 if (time_left < *timeout) 05276 *timeout = time_left; 05277 } 05278 AST_LIST_TRAVERSE_SAFE_END; 05279 05280 return res; 05281 }
| static int sla_calc_trunk_timeouts | ( | unsigned int * | timeout | ) | [static] |
Process trunk ring timeouts.
Definition at line 5173 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().
05174 { 05175 struct sla_ringing_trunk *ringing_trunk; 05176 int res = 0; 05177 05178 AST_LIST_TRAVERSE_SAFE_BEGIN(&sla.ringing_trunks, ringing_trunk, entry) { 05179 int time_left, time_elapsed; 05180 if (!ringing_trunk->trunk->ring_timeout) 05181 continue; 05182 time_elapsed = ast_tvdiff_ms(ast_tvnow(), ringing_trunk->ring_begin); 05183 time_left = (ringing_trunk->trunk->ring_timeout * 1000) - time_elapsed; 05184 if (time_left <= 0) { 05185 pbx_builtin_setvar_helper(ringing_trunk->trunk->chan, "SLATRUNK_STATUS", "RINGTIMEOUT"); 05186 AST_LIST_REMOVE_CURRENT(entry); 05187 sla_stop_ringing_trunk(ringing_trunk); 05188 res = 1; 05189 continue; 05190 } 05191 if (time_left < *timeout) 05192 *timeout = time_left; 05193 } 05194 AST_LIST_TRAVERSE_SAFE_END; 05195 05196 return res; 05197 }
| 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 4641 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().
04643 { 04644 struct sla_station *station; 04645 struct sla_trunk_ref *trunk_ref; 04646 04647 AST_LIST_TRAVERSE(&sla_stations, station, entry) { 04648 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) { 04649 if (trunk_ref->trunk != trunk || (inactive_only ? trunk_ref->chan : 0) 04650 || trunk_ref == exclude) 04651 continue; 04652 trunk_ref->state = state; 04653 ast_devstate_changed(sla_state_to_devstate(state), 04654 "SLA:%s_%s", station->name, trunk->name); 04655 break; 04656 } 04657 } 04658 }
| static int sla_check_device | ( | const char * | device | ) | [static] |
Definition at line 6029 of file app_meetme.c.
References ast_strlen_zero().
Referenced by sla_build_trunk().
06030 { 06031 char *tech, *tech_data; 06032 06033 tech_data = ast_strdupa(device); 06034 tech = strsep(&tech_data, "/"); 06035 06036 if (ast_strlen_zero(tech) || ast_strlen_zero(tech_data)) 06037 return -1; 06038 06039 return 0; 06040 }
| 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 4921 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().
04922 { 04923 struct sla_failed_station *failed_station; 04924 int res = 0; 04925 04926 AST_LIST_TRAVERSE_SAFE_BEGIN(&sla.failed_stations, failed_station, entry) { 04927 if (station != failed_station->station) 04928 continue; 04929 if (ast_tvdiff_ms(ast_tvnow(), failed_station->last_try) > 1000) { 04930 AST_LIST_REMOVE_CURRENT(entry); 04931 ast_free(failed_station); 04932 break; 04933 } 04934 res = 1; 04935 } 04936 AST_LIST_TRAVERSE_SAFE_END 04937 04938 return res; 04939 }
| static int sla_check_inuse_station | ( | const struct sla_station * | station | ) | [static] |
Check to see if a station is in use.
Definition at line 5007 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().
05008 { 05009 struct sla_trunk_ref *trunk_ref; 05010 05011 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) { 05012 if (trunk_ref->chan) 05013 return 1; 05014 } 05015 05016 return 0; 05017 }
| 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 5365 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().
05366 { 05367 struct sla_station *station; 05368 struct sla_trunk *trunk; 05369 05370 ast_mutex_lock(&sla.lock); 05371 05372 if (!AST_LIST_EMPTY(&sla.event_q) || !AST_LIST_EMPTY(&sla.ringing_trunks) 05373 || !AST_LIST_EMPTY(&sla.ringing_stations)) { 05374 ast_mutex_unlock(&sla.lock); 05375 return; 05376 } 05377 05378 AST_RWLIST_RDLOCK(&sla_stations); 05379 AST_RWLIST_TRAVERSE(&sla_stations, station, entry) { 05380 if (station->ref_count) 05381 break; 05382 } 05383 AST_RWLIST_UNLOCK(&sla_stations); 05384 if (station) { 05385 ast_mutex_unlock(&sla.lock); 05386 return; 05387 } 05388 05389 AST_RWLIST_RDLOCK(&sla_trunks); 05390 AST_RWLIST_TRAVERSE(&sla_trunks, trunk, entry) { 05391 if (trunk->ref_count) 05392 break; 05393 } 05394 AST_RWLIST_UNLOCK(&sla_trunks); 05395 if (trunk) { 05396 ast_mutex_unlock(&sla.lock); 05397 return; 05398 } 05399 05400 /* yay */ 05401 sla_load_config(1); 05402 sla.reload = 0; 05403 05404 ast_mutex_unlock(&sla.lock); 05405 }
| static int sla_check_ringing_station | ( | const struct sla_station * | station | ) | [static] |
Check to see if this station is already ringing.
Definition at line 4906 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().
04907 { 04908 struct sla_ringing_station *ringing_station; 04909 04910 AST_LIST_TRAVERSE(&sla.ringing_stations, ringing_station, entry) { 04911 if (station == ringing_station->station) 04912 return 1; 04913 } 04914 04915 return 0; 04916 }
| 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 5037 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().
05039 { 05040 struct sla_trunk_ref *trunk_ref; 05041 unsigned int delay = UINT_MAX; 05042 int time_left, time_elapsed; 05043 05044 if (!ringing_trunk) 05045 ringing_trunk = sla_choose_ringing_trunk(station, &trunk_ref, 0); 05046 else 05047 trunk_ref = sla_find_trunk_ref(station, ringing_trunk->trunk); 05048 05049 if (!ringing_trunk || !trunk_ref) 05050 return delay; 05051 05052 /* If this station has a ring delay specific to the highest priority 05053 * ringing trunk, use that. Otherwise, use the ring delay specified 05054 * globally for the station. */ 05055 delay = trunk_ref->ring_delay; 05056 if (!delay) 05057 delay = station->ring_delay; 05058 if (!delay) 05059 return INT_MAX; 05060 05061 time_elapsed = ast_tvdiff_ms(ast_tvnow(), ringing_trunk->ring_begin); 05062 time_left = (delay * 1000) - time_elapsed; 05063 05064 return time_left; 05065 }
| static int sla_check_station_hold_access | ( | const struct sla_trunk * | trunk, | |
| const struct sla_station * | station | |||
| ) | [static] |
Definition at line 4546 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().
04548 { 04549 struct sla_station_ref *station_ref; 04550 struct sla_trunk_ref *trunk_ref; 04551 04552 /* For each station that has this call on hold, check for private hold. */ 04553 AST_LIST_TRAVERSE(&trunk->stations, station_ref, entry) { 04554 AST_LIST_TRAVERSE(&station_ref->station->trunks, trunk_ref, entry) { 04555 if (trunk_ref->trunk != trunk || station_ref->station == station) 04556 continue; 04557 if (trunk_ref->state == SLA_TRUNK_STATE_ONHOLD_BYME && 04558 station_ref->station->hold_access == SLA_HOLD_PRIVATE) 04559 return 1; 04560 return 0; 04561 } 04562 } 04563 04564 return 0; 04565 }
| 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 4777 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().
04779 { 04780 struct sla_station_ref *timed_out_station; 04781 04782 AST_LIST_TRAVERSE(&ringing_trunk->timed_out_stations, timed_out_station, entry) { 04783 if (station == timed_out_station->station) 04784 return 1; 04785 } 04786 04787 return 0; 04788 }
| 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 5589 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().
05590 { 05591 struct sla_trunk_ref *trunk_ref = NULL; 05592 05593 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) { 05594 if (trunk_ref->state == SLA_TRUNK_STATE_IDLE) 05595 break; 05596 } 05597 05598 return trunk_ref; 05599 }
| 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 4798 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().
04800 { 04801 struct sla_trunk_ref *s_trunk_ref; 04802 struct sla_ringing_trunk *ringing_trunk = NULL; 04803 04804 AST_LIST_TRAVERSE(&station->trunks, s_trunk_ref, entry) { 04805 AST_LIST_TRAVERSE_SAFE_BEGIN(&sla.ringing_trunks, ringing_trunk, entry) { 04806 /* Make sure this is the trunk we're looking for */ 04807 if (s_trunk_ref->trunk != ringing_trunk->trunk) 04808 continue; 04809 04810 /* This trunk on the station is ringing. But, make sure this station 04811 * didn't already time out while this trunk was ringing. */ 04812 if (sla_check_timed_out_station(ringing_trunk, station)) 04813 continue; 04814 04815 if (rm) 04816 AST_LIST_REMOVE_CURRENT(entry); 04817 04818 if (trunk_ref) 04819 *trunk_ref = s_trunk_ref; 04820 04821 break; 04822 } 04823 AST_LIST_TRAVERSE_SAFE_END; 04824 04825 if (ringing_trunk) 04826 break; 04827 } 04828 04829 return ringing_trunk; 04830 }
| static struct sla_ringing_station* sla_create_ringing_station | ( | struct sla_station * | station | ) | [static, read] |
Definition at line 4611 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().
04612 { 04613 struct sla_ringing_station *ringing_station; 04614 04615 if (!(ringing_station = ast_calloc(1, sizeof(*ringing_station)))) 04616 return NULL; 04617 04618 ringing_station->station = station; 04619 ringing_station->ring_begin = ast_tvnow(); 04620 04621 return ringing_station; 04622 }
| static struct sla_station_ref* sla_create_station_ref | ( | struct sla_station * | station | ) | [static, read] |
Definition at line 4599 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().
04600 { 04601 struct sla_station_ref *station_ref; 04602 04603 if (!(station_ref = ast_calloc(1, sizeof(*station_ref)))) 04604 return NULL; 04605 04606 station_ref->station = station; 04607 04608 return station_ref; 04609 }
| static void sla_destroy | ( | void | ) | [static] |
Definition at line 5999 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().
06000 { 06001 struct sla_trunk *trunk; 06002 struct sla_station *station; 06003 06004 AST_RWLIST_WRLOCK(&sla_trunks); 06005 while ((trunk = AST_RWLIST_REMOVE_HEAD(&sla_trunks, entry))) 06006 destroy_trunk(trunk); 06007 AST_RWLIST_UNLOCK(&sla_trunks); 06008 06009 AST_RWLIST_WRLOCK(&sla_stations); 06010 while ((station = AST_RWLIST_REMOVE_HEAD(&sla_stations, entry))) 06011 destroy_station(station); 06012 AST_RWLIST_UNLOCK(&sla_stations); 06013 06014 if (sla.thread != AST_PTHREADT_NULL) { 06015 ast_mutex_lock(&sla.lock); 06016 sla.stop = 1; 06017 ast_cond_signal(&sla.cond); 06018 ast_mutex_unlock(&sla.lock); 06019 pthread_join(sla.thread, NULL); 06020 } 06021 06022 /* Drop any created contexts from the dialplan */ 06023 ast_context_destroy(NULL, sla_registrar); 06024 06025 ast_mutex_destroy(&sla.lock); 06026 ast_cond_destroy(&sla.cond); 06027 }
| static void sla_dial_state_callback | ( | struct ast_dial * | dial | ) | [static] |
Definition at line 4769 of file app_meetme.c.
References SLA_EVENT_DIAL_STATE, and sla_queue_event().
Referenced by sla_ring_station().
04770 { 04771 sla_queue_event(SLA_EVENT_DIAL_STATE); 04772 }
| static struct sla_station* sla_find_station | ( | const char * | name | ) | [static, read] |
Find an SLA station by name.
Definition at line 4534 of file app_meetme.c.
References AST_RWLIST_TRAVERSE, and sla_station::name.
Referenced by sla_station_exec().
04535 { 04536 struct sla_station *station = NULL; 04537 04538 AST_RWLIST_TRAVERSE(&sla_stations, station, entry) { 04539 if (!strcasecmp(station->name, name)) 04540 break; 04541 } 04542 04543 return station; 04544 }
| static struct sla_trunk* sla_find_trunk | ( | const char * | name | ) | [static, read] |
Find an SLA trunk by name.
Definition at line 4519 of file app_meetme.c.
References AST_RWLIST_TRAVERSE, and sla_trunk::name.
Referenced by sla_trunk_exec().
04520 { 04521 struct sla_trunk *trunk = NULL; 04522 04523 AST_RWLIST_TRAVERSE(&sla_trunks, trunk, entry) { 04524 if (!strcasecmp(trunk->name, name)) 04525 break; 04526 } 04527 04528 return trunk; 04529 }
| static struct sla_trunk_ref* sla_find_trunk_ref | ( | const struct sla_station * | station, | |
| const struct sla_trunk * | trunk | |||
| ) | [static, read] |
Definition at line 5019 of file app_meetme.c.
References AST_LIST_TRAVERSE, sla_trunk_ref::trunk, and sla_station::trunks.
Referenced by sla_check_station_delay().
05021 { 05022 struct sla_trunk_ref *trunk_ref = NULL; 05023 05024 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) { 05025 if (trunk_ref->trunk == trunk) 05026 break; 05027 } 05028 05029 return trunk_ref; 05030 }
| 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 4574 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().
04576 { 04577 struct sla_trunk_ref *trunk_ref = NULL; 04578 04579 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) { 04580 if (strcasecmp(trunk_ref->trunk->name, name)) 04581 continue; 04582 04583 if ( (trunk_ref->trunk->barge_disabled 04584 && trunk_ref->state == SLA_TRUNK_STATE_UP) || 04585 (trunk_ref->trunk->hold_stations 04586 && trunk_ref->trunk->hold_access == SLA_HOLD_PRIVATE 04587 && trunk_ref->state != SLA_TRUNK_STATE_ONHOLD_BYME) || 04588 sla_check_station_hold_access(trunk_ref->trunk, station) ) 04589 { 04590 trunk_ref = NULL; 04591 } 04592 04593 break; 04594 } 04595 04596 return trunk_ref; 04597 }
| static void sla_handle_dial_state_event | ( | void | ) | [static] |
Definition at line 4832 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().
04833 { 04834 struct sla_ringing_station *ringing_station; 04835 04836 AST_LIST_TRAVERSE_SAFE_BEGIN(&sla.ringing_stations, ringing_station, entry) { 04837 struct sla_trunk_ref *s_trunk_ref = NULL; 04838 struct sla_ringing_trunk *ringing_trunk = NULL; 04839 struct run_station_args args; 04840 enum ast_dial_result dial_res; 04841 pthread_t dont_care; 04842 ast_mutex_t cond_lock; 04843 ast_cond_t cond; 04844 04845 switch ((dial_res = ast_dial_state(ringing_station->station->dial))) { 04846 case AST_DIAL_RESULT_HANGUP: 04847 case AST_DIAL_RESULT_INVALID: 04848 case AST_DIAL_RESULT_FAILED: 04849 case AST_DIAL_RESULT_TIMEOUT: 04850 case AST_DIAL_RESULT_UNANSWERED: 04851 AST_LIST_REMOVE_CURRENT(entry); 04852 sla_stop_ringing_station(ringing_station, SLA_STATION_HANGUP_NORMAL); 04853 break; 04854 case AST_DIAL_RESULT_ANSWERED: 04855 AST_LIST_REMOVE_CURRENT(entry); 04856 /* Find the appropriate trunk to answer. */ 04857 ast_mutex_lock(&sla.lock); 04858 ringing_trunk = sla_choose_ringing_trunk(ringing_station->station, &s_trunk_ref, 1); 04859 ast_mutex_unlock(&sla.lock); 04860 if (!ringing_trunk) { 04861 ast_debug(1, "Found no ringing trunk for station '%s' to answer!\n", ringing_station->station->name); 04862 break; 04863 } 04864 /* Track the channel that answered this trunk */ 04865 s_trunk_ref->chan = ast_dial_answered(ringing_station->station->dial); 04866 /* Actually answer the trunk */ 04867 answer_trunk_chan(ringing_trunk->trunk->chan); 04868 sla_change_trunk_state(ringing_trunk->trunk, SLA_TRUNK_STATE_UP, ALL_TRUNK_REFS, NULL); 04869 /* Now, start a thread that will connect this station to the trunk. The rest of 04870 * the code here sets up the thread and ensures that it is able to save the arguments 04871 * before they are no longer valid since they are allocated on the stack. */ 04872 args.trunk_ref = s_trunk_ref; 04873 args.station = ringing_station->station; 04874 args.cond = &cond; 04875 args.cond_lock = &cond_lock; 04876 ast_free(ringing_trunk); 04877 ast_free(ringing_station); 04878 ast_mutex_init(&cond_lock); 04879 ast_cond_init(&cond, NULL); 04880 ast_mutex_lock(&cond_lock); 04881 ast_pthread_create_detached_background(&dont_care, NULL, run_station, &args); 04882 ast_cond_wait(&cond, &cond_lock); 04883 ast_mutex_unlock(&cond_lock); 04884 ast_mutex_destroy(&cond_lock); 04885 ast_cond_destroy(&cond); 04886 break; 04887 case AST_DIAL_RESULT_TRYING: 04888 case AST_DIAL_RESULT_RINGING: 04889 case AST_DIAL_RESULT_PROGRESS: 04890 case AST_DIAL_RESULT_PROCEEDING: 04891 break; 04892 } 04893 if (dial_res == AST_DIAL_RESULT_ANSWERED) { 04894 /* Queue up reprocessing ringing trunks, and then ringing stations again */ 04895 sla_queue_event(SLA_EVENT_RINGING_TRUNK); 04896 sla_queue_event(SLA_EVENT_DIAL_STATE); 04897 break; 04898 } 04899 } 04900 AST_LIST_TRAVERSE_SAFE_END; 04901 }
| static void sla_handle_hold_event | ( | struct sla_event * | event | ) | [static] |
Definition at line 5149 of file app_meetme.c.
References sla_trunk::active_stations, ast_atomic_fetchadd_int(), AST_CONTROL_HOLD, AST_DEVICE_ONHOLD, ast_devstate_changed(), ast_indicate(), ast_softhangup(), AST_SOFTHANGUP_DEV, sla_trunk_ref::chan, sla_trunk::chan, sla_trunk::hold_stations, INACTIVE_TRUNK_REFS, sla_trunk::name, sla_station::name, sla_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().
05150 { 05151 ast_atomic_fetchadd_int((int *) &event->trunk_ref->trunk->hold_stations, 1); 05152 event->trunk_ref->state = SLA_TRUNK_STATE_ONHOLD_BYME; 05153 ast_devstate_changed(AST_DEVICE_ONHOLD, "SLA:%s_%s", 05154 event->station->name, event->trunk_ref->trunk->name); 05155 sla_change_trunk_state(event->trunk_ref->trunk, SLA_TRUNK_STATE_ONHOLD, 05156 INACTIVE_TRUNK_REFS, event->trunk_ref); 05157 05158 if (event->trunk_ref->trunk->active_stations == 1) { 05159 /* The station putting it on hold is the only one on the call, so start 05160 * Music on hold to the trunk. */ 05161 event->trunk_ref->trunk->on_hold = 1; 05162 ast_indicate(event->trunk_ref->trunk->chan, AST_CONTROL_HOLD); 05163 } 05164 05165 ast_softhangup(event->trunk_ref->chan, AST_SOFTHANGUP_DEV); 05166 event->trunk_ref->chan = NULL; 05167 }
| static void sla_handle_ringing_trunk_event | ( | void | ) | [static] |
Definition at line 5139 of file app_meetme.c.
References ast_mutex_lock(), ast_mutex_unlock(), sla, sla_hangup_stations(), and sla_ring_stations().
Referenced by sla_thread().
05140 { 05141 ast_mutex_lock(&sla.lock); 05142 sla_ring_stations(); 05143 ast_mutex_unlock(&sla.lock); 05144 05145 /* Find stations that shouldn't be ringing anymore. */ 05146 sla_hangup_stations(); 05147 }
| static void sla_hangup_stations | ( | void | ) | [static] |
Definition at line 5111 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().
05112 { 05113 struct sla_trunk_ref *trunk_ref; 05114 struct sla_ringing_station *ringing_station; 05115 05116 AST_LIST_TRAVERSE_SAFE_BEGIN(&sla.ringing_stations, ringing_station, entry) { 05117 AST_LIST_TRAVERSE(&ringing_station->station->trunks, trunk_ref, entry) { 05118 struct sla_ringing_trunk *ringing_trunk; 05119 ast_mutex_lock(&sla.lock); 05120 AST_LIST_TRAVERSE(&sla.ringing_trunks, ringing_trunk, entry) { 05121 if (trunk_ref->trunk == ringing_trunk->trunk) 05122 break; 05123 } 05124 ast_mutex_unlock(&sla.lock); 05125 if (ringing_trunk) 05126 break; 05127 } 05128 if (!trunk_ref) { 05129 AST_LIST_REMOVE_CURRENT(entry); 05130 ast_dial_join(ringing_station->station->dial); 05131 ast_dial_destroy(ringing_station->station->dial); 05132 ringing_station->station->dial = NULL; 05133 ast_free(ringing_station); 05134 } 05135 } 05136 AST_LIST_TRAVERSE_SAFE_END 05137 }
| static const char* sla_hold_str | ( | unsigned int | hold_access | ) | [static] |
Definition at line 1452 of file app_meetme.c.
References SLA_HOLD_OPEN, and SLA_HOLD_PRIVATE.
Referenced by sla_show_stations(), and sla_show_trunks().
01453 { 01454 const char *hold = "Unknown"; 01455 01456 switch (hold_access) { 01457 case SLA_HOLD_OPEN: 01458 hold = "Open"; 01459 break; 01460 case SLA_HOLD_PRIVATE: 01461 hold = "Private"; 01462 default: 01463 break; 01464 } 01465 01466 return hold; 01467 }
| static int sla_load_config | ( | int | reload | ) | [static] |
Definition at line 6285 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_FILEINVALID, CONFIG_STATUS_FILEUNCHANGED, LOG_ERROR, LOG_WARNING, sla, sla_build_station(), sla_build_trunk(), SLA_CONFIG_FILE, sla_thread(), and type.
Referenced by load_config(), and sla_check_reload().
06286 { 06287 struct ast_config *cfg; 06288 struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; 06289 const char *cat = NULL; 06290 int res = 0; 06291 const char *val; 06292 06293 if (!reload) { 06294 ast_mutex_init(&sla.lock); 06295 ast_cond_init(&sla.cond, NULL); 06296 } 06297 06298 if (!(cfg = ast_config_load(SLA_CONFIG_FILE, config_flags))) { 06299 return 0; /* Treat no config as normal */ 06300 } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) { 06301 return 0; 06302 } else if (cfg == CONFIG_STATUS_FILEINVALID) { 06303 ast_log(LOG_ERROR, "Config file " SLA_CONFIG_FILE " is in an invalid format. Aborting.\n"); 06304 return 0; 06305 } 06306 06307 if ((val = ast_variable_retrieve(cfg, "general", "attemptcallerid"))) 06308 sla.attempt_callerid = ast_true(val); 06309 06310 while ((cat = ast_category_browse(cfg, cat)) && !res) { 06311 const char *type; 06312 if (!strcasecmp(cat, "general")) 06313 continue; 06314 if (!(type = ast_variable_retrieve(cfg, cat, "type"))) { 06315 ast_log(LOG_WARNING, "Invalid entry in %s defined with no type!\n", 06316 SLA_CONFIG_FILE); 06317 continue; 06318 } 06319 if (!strcasecmp(type, "trunk")) 06320 res = sla_build_trunk(cfg, cat); 06321 else if (!strcasecmp(type, "station")) 06322 res = sla_build_station(cfg, cat); 06323 else { 06324 ast_log(LOG_WARNING, "Entry in %s defined with invalid type '%s'!\n", 06325 SLA_CONFIG_FILE, type); 06326 } 06327 } 06328 06329 ast_config_destroy(cfg); 06330 06331 if (!reload && (!AST_LIST_EMPTY(&sla_stations) || !AST_LIST_EMPTY(&sla_stations))) 06332 ast_pthread_create(&sla.thread, NULL, sla_thread, NULL); 06333 06334 return res; 06335 }
| static int sla_process_timers | ( | struct timespec * | ts | ) | [static] |
Calculate the time until the next known event.
Definition at line 5327 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().
05328 { 05329 unsigned int timeout = UINT_MAX; 05330 struct timeval wait; 05331 unsigned int change_made = 0; 05332 05333 /* Check for ring timeouts on ringing trunks */ 05334 if (sla_calc_trunk_timeouts(&timeout)) 05335 change_made = 1; 05336 05337 /* Check for ring timeouts on ringing stations */ 05338 if (sla_calc_station_timeouts(&timeout)) 05339 change_made = 1; 05340 05341 /* Check for station ring delays */ 05342 if (sla_calc_station_delays(&timeout)) 05343 change_made = 1; 05344 05345 /* queue reprocessing of ringing trunks */ 05346 if (change_made) 05347 sla_queue_event_nolock(SLA_EVENT_RINGING_TRUNK); 05348 05349 /* No timeout */ 05350 if (timeout == UINT_MAX) 05351 return 0; 05352 05353 if (ts) { 05354 wait = ast_tvadd(ast_tvnow(), ast_samp2tv(timeout, 1000)); 05355 ts->tv_sec = wait.tv_sec; 05356 ts->tv_nsec = wait.tv_usec * 1000; 05357 } 05358 05359 return 1; 05360 }
| static void sla_queue_event | ( | enum sla_event_type | type | ) | [static] |
Definition at line 1756 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().
01757 { 01758 sla_queue_event_full(type, NULL, NULL, 1); 01759 }
| 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 1762 of file app_meetme.c.
References ast_debug, AST_LIST_TRAVERSE, ast_log(), AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_strlen_zero(), sla_trunk_ref::chan, ast_conference::confno, LOG_ERROR, sla_trunk::name, sla_queue_event_full(), sla_trunk_ref::trunk, and sla_station::trunks.
Referenced by conf_run().
01764 { 01765 struct sla_station *station; 01766 struct sla_trunk_ref *trunk_ref = NULL; 01767 char *trunk_name; 01768 01769 trunk_name = ast_strdupa(conf->confno); 01770 strsep(&trunk_name, "_"); 01771 if (ast_strlen_zero(trunk_name)) { 01772 ast_log(LOG_ERROR, "Invalid conference name for SLA - '%s'!\n", conf->confno); 01773 return; 01774 } 01775 01776 AST_RWLIST_RDLOCK(&sla_stations); 01777 AST_RWLIST_TRAVERSE(&sla_stations, station, entry) { 01778 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) { 01779 if (trunk_ref->chan == chan && !strcmp(trunk_ref->trunk->name, trunk_name)) 01780 break; 01781 } 01782 if (trunk_ref) 01783 break; 01784 } 01785 AST_RWLIST_UNLOCK(&sla_stations); 01786 01787 if (!trunk_ref) { 01788 ast_debug(1, "Trunk not found for event!\n"); 01789 return; 01790 } 01791 01792 sla_queue_event_full(type, trunk_ref, station, 1); 01793 }
| 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 1724 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().
01726 { 01727 struct sla_event *event; 01728 01729 if (sla.thread == AST_PTHREADT_NULL) { 01730 return; 01731 } 01732 01733 if (!(event = ast_calloc(1, sizeof(*event)))) 01734 return; 01735 01736 event->type = type; 01737 event->trunk_ref = trunk_ref; 01738 event->station = station; 01739 01740 if (!lock) { 01741 AST_LIST_INSERT_TAIL(&sla.event_q, event, entry); 01742 return; 01743 } 01744 01745 ast_mutex_lock(&sla.lock); 01746 AST_LIST_INSERT_TAIL(&sla.event_q, event, entry); 01747 ast_cond_signal(&sla.cond); 01748 ast_mutex_unlock(&sla.lock); 01749 }
| static void sla_queue_event_nolock | ( | enum sla_event_type | type | ) | [static] |
Definition at line 1751 of file app_meetme.c.
References sla_queue_event_full().
Referenced by sla_process_timers().
01752 { 01753 sla_queue_event_full(type, NULL, NULL, 0); 01754 }
| static int sla_ring_station | ( | struct sla_ringing_trunk * | ringing_trunk, | |
| struct sla_station * | station | |||
| ) | [static] |
Ring a station.
Definition at line 4944 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_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, and sla_ringing_trunk::trunk.
Referenced by sla_ring_stations().
04945 { 04946 char *tech, *tech_data; 04947 struct ast_dial *dial; 04948 struct sla_ringing_station *ringing_station; 04949 const char *cid_name = NULL, *cid_num = NULL; 04950 enum ast_dial_result res; 04951 04952 if (!(dial = ast_dial_create())) 04953 return -1; 04954 04955 ast_dial_set_state_callback(dial, sla_dial_state_callback); 04956 tech_data = ast_strdupa(station->device); 04957 tech = strsep(&tech_data, "/"); 04958 04959 if (ast_dial_append(dial, tech, tech_data) == -1) { 04960 ast_dial_destroy(dial); 04961 return -1; 04962 } 04963 04964 if (!sla.attempt_callerid && !ast_strlen_zero(ringing_trunk->trunk->chan->cid.cid_name)) { 04965 cid_name = ast_strdupa(ringing_trunk->trunk->chan->cid.cid_name); 04966 ast_free(ringing_trunk->trunk->chan->cid.cid_name); 04967 ringing_trunk->trunk->chan->cid.cid_name = NULL; 04968 } 04969 if (!sla.attempt_callerid && !ast_strlen_zero(ringing_trunk->trunk->chan->cid.cid_num)) { 04970 cid_num = ast_strdupa(ringing_trunk->trunk->chan->cid.cid_num); 04971 ast_free(ringing_trunk->trunk->chan->cid.cid_num); 04972 ringing_trunk->trunk->chan->cid.cid_num = NULL; 04973 } 04974 04975 res = ast_dial_run(dial, ringing_trunk->trunk->chan, 1); 04976 04977 if (cid_name) 04978 ringing_trunk->trunk->chan->cid.cid_name = ast_strdup(cid_name); 04979 if (cid_num) 04980 ringing_trunk->trunk->chan->cid.cid_num = ast_strdup(cid_num); 04981 04982 if (res != AST_DIAL_RESULT_TRYING) { 04983 struct sla_failed_station *failed_station; 04984 ast_dial_destroy(dial); 04985 if (!(failed_station = ast_calloc(1, sizeof(*failed_station)))) 04986 return -1; 04987 failed_station->station = station; 04988 failed_station->last_try = ast_tvnow(); 04989 AST_LIST_INSERT_HEAD(&sla.failed_stations, failed_station, entry); 04990 return -1; 04991 } 04992 if (!(ringing_station = sla_create_ringing_station(station))) { 04993 ast_dial_join(dial); 04994 ast_dial_destroy(dial); 04995 return -1; 04996 } 04997 04998 station->dial = dial; 04999 05000 AST_LIST_INSERT_HEAD(&sla.ringing_stations, ringing_station, entry); 05001 05002 return 0; 05003 }
| static void sla_ring_stations | ( | void | ) | [static] |
Ring stations based on current set of ringing trunks.
Definition at line 5070 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().
05071 { 05072 struct sla_station_ref *station_ref; 05073 struct sla_ringing_trunk *ringing_trunk; 05074 05075 /* Make sure that every station that uses at least one of the ringing 05076 * trunks, is ringing. */ 05077 AST_LIST_TRAVERSE(&sla.ringing_trunks, ringing_trunk, entry) { 05078 AST_LIST_TRAVERSE(&ringing_trunk->trunk->stations, station_ref, entry) { 05079 int time_left; 05080 05081 /* Is this station already ringing? */ 05082 if (sla_check_ringing_station(station_ref->station)) 05083 continue; 05084 05085 /* Is this station already in a call? */ 05086 if (sla_check_inuse_station(station_ref->station)) 05087 continue; 05088 05089 /* Did we fail to dial this station earlier? If so, has it been 05090 * a minute since we tried? */ 05091 if (sla_check_failed_station(station_ref->station)) 05092 continue; 05093 05094 /* If this station already timed out while this trunk was ringing, 05095 * do not dial it again for this ringing trunk. */ 05096 if (sla_check_timed_out_station(ringing_trunk, station_ref->station)) 05097 continue; 05098 05099 /* Check for a ring delay in progress */ 05100 time_left = sla_check_station_delay(station_ref->station, ringing_trunk); 05101 if (time_left != INT_MAX && time_left > 0) 05102 continue; 05103 05104 /* It is time to make this station begin to ring. Do it! */ 05105 sla_ring_station(ringing_trunk, station_ref->station); 05106 } 05107 } 05108 /* Now, all of the stations that should be ringing, are ringing. */ 05109 }
| static char* sla_show_stations | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 1534 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.
01535 { 01536 const struct sla_station *station; 01537 01538 switch (cmd) { 01539 case CLI_INIT: 01540 e->command = "sla show stations"; 01541 e->usage = 01542 "Usage: sla show stations\n" 01543 " This will list all stations defined in sla.conf\n"; 01544 return NULL; 01545 case CLI_GENERATE: 01546 return NULL; 01547 } 01548 01549 ast_cli(a->fd, "\n" 01550 "=============================================================\n" 01551 "=== Configured SLA Stations =================================\n" 01552 "=============================================================\n" 01553 "===\n"); 01554 AST_RWLIST_RDLOCK(&sla_stations); 01555 AST_RWLIST_TRAVERSE(&sla_stations, station, entry) { 01556 struct sla_trunk_ref *trunk_ref; 01557 char ring_timeout[16] = "(none)"; 01558 char ring_delay[16] = "(none)"; 01559 if (station->ring_timeout) { 01560 snprintf(ring_timeout, sizeof(ring_timeout), 01561 "%u", station->ring_timeout); 01562 } 01563 if (station->ring_delay) { 01564 snprintf(ring_delay, sizeof(ring_delay), 01565 "%u", station->ring_delay); 01566 } 01567 ast_cli(a->fd, "=== ---------------------------------------------------------\n" 01568 "=== Station Name: %s\n" 01569 "=== ==> Device: %s\n" 01570 "=== ==> AutoContext: %s\n" 01571 "=== ==> RingTimeout: %s\n" 01572 "=== ==> RingDelay: %s\n" 01573 "=== ==> HoldAccess: %s\n" 01574 "=== ==> Trunks ...\n", 01575 station->name, station->device, 01576 S_OR(station->autocontext, "(none)"), 01577 ring_timeout, ring_delay, 01578 sla_hold_str(station->hold_access)); 01579 AST_RWLIST_RDLOCK(&sla_trunks); 01580 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) { 01581 if (trunk_ref->ring_timeout) { 01582 snprintf(ring_timeout, sizeof(ring_timeout), 01583 "%u", trunk_ref->ring_timeout); 01584 } else 01585 strcpy(ring_timeout, "(none)"); 01586 if (trunk_ref->ring_delay) { 01587 snprintf(ring_delay, sizeof(ring_delay), 01588 "%u", trunk_ref->ring_delay); 01589 } else 01590 strcpy(ring_delay, "(none)"); 01591 ast_cli(a->fd, "=== ==> Trunk Name: %s\n" 01592 "=== ==> State: %s\n" 01593 "=== ==> RingTimeout: %s\n" 01594 "=== ==> RingDelay: %s\n", 01595 trunk_ref->trunk->name, 01596 trunkstate2str(trunk_ref->state), 01597 ring_timeout, ring_delay); 01598 } 01599 AST_RWLIST_UNLOCK(&sla_trunks); 01600 ast_cli(a->fd, "=== ---------------------------------------------------------\n" 01601 "===\n"); 01602 } 01603 AST_RWLIST_UNLOCK(&sla_stations); 01604 ast_cli(a->fd, "============================================================\n" 01605 "\n"); 01606 01607 return CLI_SUCCESS; 01608 }
| static char* sla_show_trunks | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 1469 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.
01470 { 01471 const struct sla_trunk *trunk; 01472 01473 switch (cmd) { 01474 case CLI_INIT: 01475 e->command = "sla show trunks"; 01476 e->usage = 01477 "Usage: sla show trunks\n" 01478 " This will list all trunks defined in sla.conf\n"; 01479 return NULL; 01480 case CLI_GENERATE: 01481 return NULL; 01482 } 01483 01484 ast_cli(a->fd, "\n" 01485 "=============================================================\n" 01486 "=== Configured SLA Trunks ===================================\n" 01487 "=============================================================\n" 01488 "===\n"); 01489 AST_RWLIST_RDLOCK(&sla_trunks); 01490 AST_RWLIST_TRAVERSE(&sla_trunks, trunk, entry) { 01491 struct sla_station_ref *station_ref; 01492 char ring_timeout[16] = "(none)"; 01493 if (trunk->ring_timeout) 01494 snprintf(ring_timeout, sizeof(ring_timeout), "%u Seconds", trunk->ring_timeout); 01495 ast_cli(a->fd, "=== ---------------------------------------------------------\n" 01496 "=== Trunk Name: %s\n" 01497 "=== ==> Device: %s\n" 01498 "=== ==> AutoContext: %s\n" 01499 "=== ==> RingTimeout: %s\n" 01500 "=== ==> BargeAllowed: %s\n" 01501 "=== ==> HoldAccess: %s\n" 01502 "=== ==> Stations ...\n", 01503 trunk->name, trunk->device, 01504 S_OR(trunk->autocontext, "(none)"), 01505 ring_timeout, 01506 trunk->barge_disabled ? "No" : "Yes", 01507 sla_hold_str(trunk->hold_access)); 01508 AST_RWLIST_RDLOCK(&sla_stations); 01509 AST_LIST_TRAVERSE(&trunk->stations, station_ref, entry) 01510 ast_cli(a->fd, "=== ==> Station name: %s\n", station_ref->station->name); 01511 AST_RWLIST_UNLOCK(&sla_stations); 01512 ast_cli(a->fd, "=== ---------------------------------------------------------\n===\n"); 01513 } 01514 AST_RWLIST_UNLOCK(&sla_trunks); 01515 ast_cli(a->fd, "=============================================================\n\n"); 01516 01517 return CLI_SUCCESS; 01518 }
| static enum ast_device_state sla_state | ( | const char * | data | ) | [static] |
Definition at line 5923 of file app_meetme.c.
References AST_DEVICE_INVALID, AST_LIST_TRAVERSE, ast_log(), AST_RWLIST_RDLOCK, AST_RWLIST_UNLOCK, buf, LOG_ERROR, sla_trunk::name, sla_station::name, sla_state_to_devstate(), sla_trunk_ref::state, sla_trunk_ref::trunk, and sla_station::trunks.
Referenced by load_module().
05924 { 05925 char *buf, *station_name, *trunk_name; 05926 struct sla_station *station; 05927 struct sla_trunk_ref *trunk_ref; 05928 enum ast_device_state res = AST_DEVICE_INVALID; 05929 05930 trunk_name = buf = ast_strdupa(data); 05931 station_name = strsep(&trunk_name, "_"); 05932 05933 AST_RWLIST_RDLOCK(&sla_stations); 05934 AST_LIST_TRAVERSE(&sla_stations, station, entry) { 05935 if (strcasecmp(station_name, station->name)) 05936 continue; 05937 AST_RWLIST_RDLOCK(&sla_trunks); 05938 AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) { 05939 if (!strcasecmp(trunk_name, trunk_ref->trunk->name)) 05940 break; 05941 } 05942 if (!trunk_ref) { 05943 AST_RWLIST_UNLOCK(&sla_trunks); 05944 break; 05945 } 05946 res = sla_state_to_devstate(trunk_ref->state); 05947 AST_RWLIST_UNLOCK(&sla_trunks); 05948 } 05949 AST_RWLIST_UNLOCK(&sla_stations); 05950 05951 if (res == AST_DEVICE_INVALID) { 05952 ast_log(LOG_ERROR, "Could not determine state for trunk %s on station %s!\n", 05953 trunk_name, station_name); 05954 } 05955 05956 return res; 05957 }
| static enum ast_device_state sla_state_to_devstate | ( | enum sla_trunk_state | state | ) | [static] |
Definition at line 4624 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().
04625 { 04626 switch (state) { 04627 case SLA_TRUNK_STATE_IDLE: 04628 return AST_DEVICE_NOT_INUSE; 04629 case SLA_TRUNK_STATE_RINGING: 04630 return AST_DEVICE_RINGING; 04631 case SLA_TRUNK_STATE_UP: 04632 return AST_DEVICE_INUSE; 04633 case SLA_TRUNK_STATE_ONHOLD: 04634 case SLA_TRUNK_STATE_ONHOLD_BYME: 04635 return AST_DEVICE_ONHOLD; 04636 } 04637 04638 return AST_DEVICE_UNKNOWN; 04639 }
| static int sla_station_exec | ( | struct ast_channel * | chan, | |
| void * | data | |||
| ) | [static] |
Definition at line 5601 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_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, sla_ringing_trunk::trunk, sla_trunk_ref::trunk, and dial_trunk_args::trunk_ref.
Referenced by load_module().
05602 { 05603 char *station_name, *trunk_name; 05604 struct sla_station *station; 05605 struct sla_trunk_ref *trunk_ref = NULL; 05606 char conf_name[MAX_CONFNUM]; 05607 struct ast_flags conf_flags = { 0 }; 05608 struct ast_conference *conf; 05609 05610 if (ast_strlen_zero(data)) { 05611 ast_log(LOG_WARNING, "Invalid Arguments to SLAStation!\n"); 05612 pbx_builtin_setvar_helper(chan, "SLASTATION_STATUS", "FAILURE"); 05613 return 0; 05614 } 05615 05616 trunk_name = ast_strdupa(data); 05617 station_name = strsep(&trunk_name, "_"); 05618 05619 if (ast_strlen_zero(station_name)) { 05620 ast_log(LOG_WARNING, "Invalid Arguments to SLAStation!\n"); 05621 pbx_builtin_setvar_helper(chan, "SLASTATION_STATUS", "FAILURE"); 05622 return 0; 05623 } 05624 05625 AST_RWLIST_RDLOCK(&sla_stations); 05626 station = sla_find_station(station_name); 05627 if (station) 05628 ast_atomic_fetchadd_int((int *) &station->ref_count, 1); 05629 AST_RWLIST_UNLOCK(&sla_stations); 05630 05631 if (!station) { 05632 ast_log(LOG_WARNING, "Station '%s' not found!\n", station_name); 05633 pbx_builtin_setvar_helper(chan, "SLASTATION_STATUS", "FAILURE"); 05634 sla_queue_event(SLA_EVENT_CHECK_RELOAD); 05635 return 0; 05636 } 05637 05638 AST_RWLIST_RDLOCK(&sla_trunks); 05639 if (!ast_strlen_zero(trunk_name)) { 05640 trunk_ref = sla_find_trunk_ref_byname(station, trunk_name); 05641 } else 05642 trunk_ref = sla_choose_idle_trunk(station); 05643 AST_RWLIST_UNLOCK(&sla_trunks); 05644 05645 if (!trunk_ref) { 05646 if (ast_strlen_zero(trunk_name)) 05647 ast_log(LOG_NOTICE, "No trunks available for call.\n"); 05648 else { 05649 ast_log(LOG_NOTICE, "Can't join existing call on trunk " 05650 "'%s' due to access controls.\n", trunk_name); 05651 } 05652 pbx_builtin_setvar_helper(chan, "SLASTATION_STATUS", "CONGESTION"); 05653 ast_atomic_fetchadd_int((int *) &station->ref_count, -1); 05654 sla_queue_event(SLA_EVENT_CHECK_RELOAD); 05655 return 0; 05656 } 05657 05658 if (trunk_ref->state == SLA_TRUNK_STATE_ONHOLD_BYME) { 05659 if (ast_atomic_dec_and_test((int *) &trunk_ref->trunk->hold_stations) == 1) 05660 sla_change_trunk_state(trunk_ref->trunk, SLA_TRUNK_STATE_UP, ALL_TRUNK_REFS, NULL); 05661 else { 05662 trunk_ref->state = SLA_TRUNK_STATE_UP; 05663 ast_devstate_changed(AST_DEVICE_INUSE, 05664 "SLA:%s_%s", station->name, trunk_ref->trunk->name); 05665 } 05666 } else if (trunk_ref->state == SLA_TRUNK_STATE_RINGING) { 05667 struct sla_ringing_trunk *ringing_trunk; 05668 05669 ast_mutex_lock(&sla.lock); 05670 AST_LIST_TRAVERSE_SAFE_BEGIN(&sla.ringing_trunks, ringing_trunk, entry) { 05671 if (ringing_trunk->trunk == trunk_ref->trunk) { 05672 AST_LIST_REMOVE_CURRENT(entry); 05673 break; 05674 } 05675 } 05676 AST_LIST_TRAVERSE_SAFE_END 05677 ast_mutex_unlock(&sla.lock); 05678 05679 if (ringing_trunk) { 05680 answer_trunk_chan(ringing_trunk->trunk->chan); 05681 sla_change_trunk_state(ringing_trunk->trunk, SLA_TRUNK_STATE_UP, ALL_TRUNK_REFS, NULL); 05682 05683 free(ringing_trunk); 05684 05685 /* Queue up reprocessing ringing trunks, and then ringing stations again */ 05686 sla_queue_event(SLA_EVENT_RINGING_TRUNK); 05687 sla_queue_event(SLA_EVENT_DIAL_STATE); 05688 } 05689 } 05690 05691 trunk_ref->chan = chan; 05692 05693 if (!trunk_ref->trunk->chan) { 05694 ast_mutex_t cond_lock; 05695 ast_cond_t cond; 05696 pthread_t dont_care; 05697 struct dial_trunk_args args = { 05698 .trunk_ref = trunk_ref, 05699 .station = station, 05700 .cond_lock = &cond_lock, 05701 .cond = &cond, 05702 }; 05703 sla_change_trunk_state(trunk_ref->trunk, SLA_TRUNK_STATE_UP, ALL_TRUNK_REFS, NULL); 05704 /* Create a thread to dial the trunk and dump it into the conference. 05705 * However, we want to wait until the trunk has been dialed and the 05706 * conference is created before continuing on here. */ 05707 ast_autoservice_start(chan); 05708 ast_mutex_init(&cond_lock); 05709 ast_cond_init(&cond, NULL); 05710 ast_mutex_lock(&cond_lock); 05711 ast_pthread_create_detached_background(&dont_care, NULL, dial_trunk, &args); 05712 ast_cond_wait(&cond, &cond_lock); 05713 ast_mutex_unlock(&cond_lock); 05714 ast_mutex_destroy(&cond_lock); 05715 ast_cond_destroy(&cond); 05716 ast_autoservice_stop(chan); 05717 if (!trunk_ref->trunk->chan) { 05718 ast_debug(1, "Trunk didn't get created. chan: %lx\n", (long) trunk_ref->trunk->chan); 05719 pbx_builtin_setvar_helper(chan, "SLASTATION_STATUS", "CONGESTION"); 05720 sla_change_trunk_state(trunk_ref->trunk, SLA_TRUNK_STATE_IDLE, ALL_TRUNK_REFS, NULL); 05721 trunk_ref->chan = NULL; 05722 ast_atomic_fetchadd_int((int *) &station->ref_count, -1); 05723 sla_queue_event(SLA_EVENT_CHECK_RELOAD); 05724 return 0; 05725 } 05726 } 05727 05728 if (ast_atomic_fetchadd_int((int *) &trunk_ref->trunk->active_stations, 1) == 0 && 05729 trunk_ref->trunk->on_hold) { 05730 trunk_ref->trunk->on_hold = 0; 05731 ast_indicate(trunk_ref->trunk->chan, AST_CONTROL_UNHOLD); 05732 sla_change_trunk_state(trunk_ref->trunk, SLA_TRUNK_STATE_UP, ALL_TRUNK_REFS, NULL); 05733 } 05734 05735 snprintf(conf_name, sizeof(conf_name), "SLA_%s", trunk_ref->trunk->name); 05736 ast_set_flag(&conf_flags, 05737 CONFFLAG_QUIET | CONFFLAG_MARKEDEXIT | CONFFLAG_PASS_DTMF | CONFFLAG_SLA_STATION); 05738 ast_answer(chan); 05739 conf = build_conf(conf_name, "", "", 0, 0, 1, chan); 05740 if (conf) { 05741 conf_run(chan, conf, conf_flags.flags, NULL); 05742 dispose_conf(conf); 05743 conf = NULL; 05744 } 05745 trunk_ref->chan = NULL; 05746 if (ast_atomic_dec_and_test((int *) &trunk_ref->trunk->active_stations) && 05747 trunk_ref->state != SLA_TRUNK_STATE_ONHOLD_BYME) { 05748 strncat(conf_name, ",K", sizeof(conf_name) - strlen(conf_name) - 1); 05749 admin_exec(NULL, conf_name); 05750 trunk_ref->trunk->hold_stations = 0; 05751 sla_change_trunk_state(trunk_ref->trunk, SLA_TRUNK_STATE_IDLE, ALL_TRUNK_REFS, NULL); 05752 } 05753 05754 pbx_builtin_setvar_helper(chan, "SLASTATION_STATUS", "SUCCESS"); 05755 05756 ast_atomic_fetchadd_int((int *) &station->ref_count, -1); 05757 sla_queue_event(SLA_EVENT_CHECK_RELOAD); 05758 05759 return 0; 05760 }
| static void sla_stop_ringing_station | ( | struct sla_ringing_station * | ringing_station, | |
| enum sla_station_hangup | hangup | |||
| ) | [static] |
Definition at line 4734 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().
04736 { 04737 struct sla_ringing_trunk *ringing_trunk; 04738 struct sla_trunk_ref *trunk_ref; 04739 struct sla_station_ref *station_ref; 04740 04741 ast_dial_join(ringing_station->station->dial); 04742 ast_dial_destroy(ringing_station->station->dial); 04743 ringing_station->station->dial = NULL; 04744 04745 if (hangup == SLA_STATION_HANGUP_NORMAL) 04746 goto done; 04747 04748 /* If the station is being hung up because of a timeout, then add it to the 04749 * list of timed out stations on each of the ringing trunks. This is so 04750 * that when doing further processing to figure out which stations should be 04751 * ringing, which trunk to answer, determining timeouts, etc., we know which 04752 * ringing trunks we should ignore. */ 04753 AST_LIST_TRAVERSE(&sla.ringing_trunks, ringing_trunk, entry) { 04754 AST_LIST_TRAVERSE(&ringing_station->station->trunks, trunk_ref, entry) { 04755 if (ringing_trunk->trunk == trunk_ref->trunk) 04756 break; 04757 } 04758 if (!trunk_ref) 04759 continue; 04760 if (!(station_ref = sla_create_station_ref(ringing_station->station))) 04761 continue; 04762 AST_LIST_INSERT_TAIL(&ringing_trunk->timed_out_stations, station_ref, entry); 04763 } 04764 04765 done: 04766 ast_free(ringing_station); 04767 }
| static void sla_stop_ringing_trunk | ( | struct sla_ringing_trunk * | ringing_trunk | ) | [static] |
Definition at line 4719 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().
04720 { 04721 char buf[80]; 04722 struct sla_station_ref *station_ref; 04723 04724 snprintf(buf, sizeof(buf), "SLA_%s,K", ringing_trunk->trunk->name); 04725 admin_exec(NULL, buf); 04726 sla_change_trunk_state(ringing_trunk->trunk, SLA_TRUNK_STATE_IDLE, ALL_TRUNK_REFS, NULL); 04727 04728 while ((station_ref = AST_LIST_REMOVE_HEAD(&ringing_trunk->timed_out_stations, entry))) 04729 ast_free(station_ref); 04730 04731 ast_free(ringing_trunk); 04732 }
| static void* sla_thread | ( | void * | data | ) | [static] |
Definition at line 5407 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().
05408 { 05409 struct sla_failed_station *failed_station; 05410 struct sla_ringing_station *ringing_station; 05411 05412 ast_mutex_lock(&sla.lock); 05413 05414 while (!sla.stop) { 05415 struct sla_event *event; 05416 struct timespec ts = { 0, }; 05417 unsigned int have_timeout = 0; 05418 05419 if (AST_LIST_EMPTY(&sla.event_q)) { 05420 if ((have_timeout = sla_process_timers(&ts))) 05421 ast_cond_timedwait(&sla.cond, &sla.lock, &ts); 05422 else 05423 ast_cond_wait(&sla.cond, &sla.lock); 05424 if (sla.stop) 05425 break; 05426 } 05427 05428 if (have_timeout) 05429 sla_process_timers(NULL); 05430 05431 while ((event = AST_LIST_REMOVE_HEAD(&sla.event_q, entry))) { 05432 ast_mutex_unlock(&sla.lock); 05433 switch (event->type) { 05434 case SLA_EVENT_HOLD: 05435 sla_handle_hold_event(event); 05436 break; 05437 case SLA_EVENT_DIAL_STATE: 05438 sla_handle_dial_state_event(); 05439 break; 05440 case SLA_EVENT_RINGING_TRUNK: 05441 sla_handle_ringing_trunk_event(); 05442 break; 05443 case SLA_EVENT_RELOAD: 05444 sla.reload = 1; 05445 case SLA_EVENT_CHECK_RELOAD: 05446 break; 05447 } 05448 ast_free(event); 05449 ast_mutex_lock(&sla.lock); 05450 } 05451 05452 if (sla.reload) 05453 sla_check_reload(); 05454 } 05455 05456 ast_mutex_unlock(&sla.lock); 05457 05458 while ((ringing_station = AST_LIST_REMOVE_HEAD(&sla.ringing_stations, entry))) 05459 ast_free(ringing_station); 05460 05461 while ((failed_station = AST_LIST_REMOVE_HEAD(&sla.failed_stations, entry))) 05462 ast_free(failed_station); 05463 05464 return NULL; 05465 }
| static int sla_trunk_exec | ( | struct ast_channel * | chan, | |
| void * | data | |||
| ) | [static] |
Definition at line 5808 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_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().
05809 { 05810 char conf_name[MAX_CONFNUM]; 05811 struct ast_conference *conf; 05812 struct ast_flags conf_flags = { 0 }; 05813 struct sla_trunk *trunk; 05814 struct sla_ringing_trunk *ringing_trunk; 05815 AST_DECLARE_APP_ARGS(args, 05816 AST_APP_ARG(trunk_name); 05817 AST_APP_ARG(options); 05818 ); 05819 char *opts[SLA_TRUNK_OPT_ARG_ARRAY_SIZE] = { NULL, }; 05820 char *conf_opt_args[OPT_ARG_ARRAY_SIZE] = { NULL, }; 05821 struct ast_flags opt_flags = { 0 }; 05822 char *parse; 05823 05824 if (ast_strlen_zero(data)) { 05825 ast_log(LOG_ERROR, "The SLATrunk application requires an argument, the trunk name\n"); 05826 return -1; 05827 } 05828 05829 parse = ast_strdupa(data); 05830 AST_STANDARD_APP_ARGS(args, parse); 05831 if (args.argc == 2) { 05832 if (ast_app_parse_options(sla_trunk_opts, &opt_flags, opts, args.options)) { 05833 ast_log(LOG_ERROR, "Error parsing options for SLATrunk\n"); 05834 return -1; 05835 } 05836 } 05837 05838 AST_RWLIST_RDLOCK(&sla_trunks); 05839 trunk = sla_find_trunk(args.trunk_name); 05840 if (trunk) 05841 ast_atomic_fetchadd_int((int *) &trunk->ref_count, 1); 05842 AST_RWLIST_UNLOCK(&sla_trunks); 05843 05844 if (!trunk) { 05845 ast_log(LOG_ERROR, "SLA Trunk '%s' not found!\n", args.trunk_name); 05846 pbx_builtin_setvar_helper(chan, "SLATRUNK_STATUS", "FAILURE"); 05847 ast_atomic_fetchadd_int((int *) &trunk->ref_count, -1); 05848 sla_queue_event(SLA_EVENT_CHECK_RELOAD); 05849 return 0; 05850 } 05851 05852 if (trunk->chan) { 05853 ast_log(LOG_ERROR, "Call came in on %s, but the trunk is already in use!\n", 05854 args.trunk_name); 05855 pbx_builtin_setvar_helper(chan, "SLATRUNK_STATUS", "FAILURE"); 05856 ast_atomic_fetchadd_int((int *) &trunk->ref_count, -1); 05857 sla_queue_event(SLA_EVENT_CHECK_RELOAD); 05858 return 0; 05859 } 05860 05861 trunk->chan = chan; 05862 05863 if (!(ringing_trunk = queue_ringing_trunk(trunk))) { 05864 pbx_builtin_setvar_helper(chan, "SLATRUNK_STATUS", "FAILURE"); 05865 ast_atomic_fetchadd_int((int *) &trunk->ref_count, -1); 05866 sla_queue_event(SLA_EVENT_CHECK_RELOAD); 05867 return 0; 05868 } 05869 05870 snprintf(conf_name, sizeof(conf_name), "SLA_%s", args.trunk_name); 05871 conf = build_conf(conf_name, "", "", 1, 1, 1, chan); 05872 if (!conf) { 05873 pbx_builtin_setvar_helper(chan, "SLATRUNK_STATUS", "FAILURE"); 05874 ast_atomic_fetchadd_int((int *) &trunk->ref_count, -1); 05875 sla_queue_event(SLA_EVENT_CHECK_RELOAD); 05876 return 0; 05877 } 05878 ast_set_flag(&conf_flags, 05879 CONFFLAG_QUIET | CONFFLAG_MARKEDEXIT | CONFFLAG_MARKEDUSER | CONFFLAG_PASS_DTMF | CONFFLAG_NO_AUDIO_UNTIL_UP); 05880 05881 if (ast_test_flag(&opt_flags, SLA_TRUNK_OPT_MOH)) { 05882 ast_indicate(chan, -1); 05883 ast_set_flag(&conf_flags, CONFFLAG_MOH); 05884 conf_opt_args[OPT_ARG_MOH_CLASS] = opts[SLA_TRUNK_OPT_ARG_MOH_CLASS]; 05885 } else 05886 ast_indicate(chan, AST_CONTROL_RINGING); 05887 05888 conf_run(chan, conf, conf_flags.flags, opts); 05889 dispose_conf(conf); 05890 conf = NULL; 05891 trunk->chan = NULL; 05892 trunk->on_hold = 0; 05893 05894 sla_change_trunk_state(trunk, SLA_TRUNK_STATE_IDLE, ALL_TRUNK_REFS, NULL); 05895 05896 if (!pbx_builtin_getvar_helper(chan, "SLATRUNK_STATUS")) 05897 pbx_builtin_setvar_helper(chan, "SLATRUNK_STATUS", "SUCCESS"); 05898 05899 /* Remove the entry from the list of ringing trunks if it is still there. */ 05900 ast_mutex_lock(&sla.lock); 05901 AST_LIST_TRAVERSE_SAFE_BEGIN(&sla.ringing_trunks, ringing_trunk, entry) { 05902 if (ringing_trunk->trunk == trunk) { 05903 AST_LIST_REMOVE_CURRENT(entry); 05904 break; 05905 } 05906 } 05907 AST_LIST_TRAVERSE_SAFE_END; 05908 ast_mutex_unlock(&sla.lock); 05909 if (ringing_trunk) { 05910 ast_free(ringing_trunk); 05911 pbx_builtin_setvar_helper(chan, "SLATRUNK_STATUS", "UNANSWERED"); 05912 /* Queue reprocessing of ringing trunks to make stations stop ringing 05913 * that shouldn't be ringing after this trunk stopped. */ 05914 sla_queue_event(SLA_EVENT_RINGING_TRUNK); 05915 } 05916 05917 ast_atomic_fetchadd_int((int *) &trunk->ref_count, -1); 05918 sla_queue_event(SLA_EVENT_CHECK_RELOAD); 05919 05920 return 0; 05921 }
| static const char* trunkstate2str | ( | enum sla_trunk_state | state | ) | [static] |
Definition at line 1520 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().
01521 { 01522 #define S(e) case e: return # e; 01523 switch (state) { 01524 S(SLA_TRUNK_STATE_IDLE) 01525 S(SLA_TRUNK_STATE_RINGING) 01526 S(SLA_TRUNK_STATE_UP) 01527 S(SLA_TRUNK_STATE_ONHOLD) 01528 S(SLA_TRUNK_STATE_ONHOLD_BYME) 01529 } 01530 return "Uknown State"; 01531 #undef S 01532 }
| static void tweak_listen_volume | ( | struct ast_conf_user * | user, | |
| enum volume_action | action | |||
| ) | [static] |
Definition at line 993 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().
00994 { 00995 tweak_volume(&user->listen, action); 00996 /* attempt to make the adjustment in the channel driver; 00997 if successful, don't adjust in the frame reading routine 00998 */ 00999 if (!set_listen_volume(user, user->listen.desired)) 01000 user->listen.actual = 0; 01001 else 01002 user->listen.actual = user->listen.desired; 01003 }
| static void tweak_talk_volume | ( | struct ast_conf_user * | user, | |
| enum volume_action | action | |||
| ) | [static] |
Definition at line 981 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().
00982 { 00983 tweak_volume(&user->talk, action); 00984 /* attempt to make the adjustment in the channel driver; 00985 if successful, don't adjust in the frame reading routine 00986 */ 00987 if (!set_talk_volume(user, user->talk.desired)) 00988 user->talk.actual = 0; 00989 else 00990 user->talk.actual = user->talk.desired; 00991 }
| static void tweak_volume | ( | struct volume * | vol, | |
| enum volume_action | action | |||
| ) | [static] |
Definition at line 946 of file app_meetme.c.
References volume::desired, VOL_DOWN, and VOL_UP.
Referenced by tweak_listen_volume(), and tweak_talk_volume().
00947 { 00948 switch (action) { 00949 case VOL_UP: 00950 switch (vol->desired) { 00951 case 5: 00952 break; 00953 case 0: 00954 vol->desired = 2; 00955 break; 00956 case -2: 00957 vol->desired = 0; 00958 break; 00959 default: 00960 vol->desired++; 00961 break; 00962 } 00963 break; 00964 case VOL_DOWN: 00965 switch (vol->desired) { 00966 case -5: 00967 break; 00968 case 2: 00969 vol->desired = 0; 00970 break; 00971 case 0: 00972 vol->desired = -2; 00973 break; 00974 default: 00975 vol->desired--; 00976 break; 00977 } 00978 } 00979 }
| static int unload_module | ( | void | ) | [static] |
Definition at line 6435 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().
06436 { 06437 int res = 0; 06438 06439 ast_cli_unregister_multiple(cli_meetme, ARRAY_LEN(cli_meetme)); 06440 res = ast_manager_unregister("MeetmeMute"); 06441 res |= ast_manager_unregister("MeetmeUnmute"); 06442 res |= ast_manager_unregister("MeetmeList"); 06443 res |= ast_unregister_application(app4); 06444 res |= ast_unregister_application(app3); 06445 res |= ast_unregister_application(app2); 06446 res |= ast_unregister_application(app); 06447 res |= ast_unregister_application(slastation_app); 06448 res |= ast_unregister_application(slatrunk_app); 06449 06450 ast_devstate_prov_del("Meetme"); 06451 ast_devstate_prov_del("SLA"); 06452 06453 sla_destroy(); 06454 06455 res |= ast_custom_function_unregister(&meetme_info_acf); 06456 ast_unload_realtime("meetme"); 06457 06458 return res; 06459 }
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 = "0901e4e500243c855563a2d78b0c03e4" , .load = load_module, .unload = unload_module, .reload = reload, } [static] |
Definition at line 6500 of file app_meetme.c.
const char* app = "MeetMe" [static] |
Definition at line 568 of file app_meetme.c.
const char* app2 = "MeetMeCount" [static] |
Definition at line 569 of file app_meetme.c.
const char* app3 = "MeetMeAdmin" [static] |
Definition at line 570 of file app_meetme.c.
const char* app4 = "MeetMeChannelAdmin" [static] |
Definition at line 571 of file app_meetme.c.
struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 6500 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 850 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 859 of file app_meetme.c.
struct ast_cli_entry cli_meetme[] [static] |
Definition at line 1610 of file app_meetme.c.
Definition at line 841 of file app_meetme.c.
Referenced by _macro_exec(), ast_safe_sleep_conditional(), gosubif_exec(), and smdi_message_wait().
unsigned int conf_map[1024] = {0, } [static] |
Definition at line 652 of file app_meetme.c.
Referenced by build_conf(), conf_exec(), and dispose_conf().
int earlyalert [static] |
Definition at line 578 of file app_meetme.c.
int endalert [static] |
Definition at line 579 of file app_meetme.c.
| struct { ... } event_q |
int extendby [static] |
Definition at line 580 of file app_meetme.c.
| struct { ... } failed_stations |
Definition at line 843 of file app_meetme.c.
Referenced by ast_format_str_reduce(), ast_print_group(), ast_str_substitute_variables(), ast_xmldoc_build_seealso(), cdr_handler(), check_goto(), context_merge(), gen_prios(), generic_thread_loop(), get_goto_target(), h261_encap(), h263_encap(), h263p_encap(), h264_encap(), listfilter(), log_jack_status(), misdn_lib_init(), mpeg4_encap(), multiplexed_thread_function(), odbc_log(), pgsql_log(), realtime_update2_handler(), realtimefield_read(), update2_curl(), update2_pgsql(), update2_prepare(), xmldoc_get_syntax_cmd(), and xmldoc_parse_cmd_enumlist().
int fuzzystart [static] |
Definition at line 577 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 867 of file app_meetme.c.
Definition at line 843 of file app_meetme.c.
Referenced by __ao2_callback(), __verboser(), add_extensions(), 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(), and try_firmware().
Definition at line 842 of file app_meetme.c.
Referenced by dahdi_request(), dahdi_restart(), dahdi_set_swgain(), dahdi_show_channel(), dahdi_show_channels(), handle_ss7_block_cic(), handle_ss7_block_linkset(), handle_ss7_unblock_cic(), handle_ss7_unblock_linkset(), load_config(), load_module(), load_rpt_vars(), reload(), rpt_master(), smdi_message_wait(), sqlite3_log(), and unload_module().
char mandescr_meetmelist[] [static] |
Definition at line 4284 of file app_meetme.c.
struct ast_custom_function meetme_info_acf [static] |
Definition at line 6406 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 566 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 852 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 583 of file app_meetme.c.
int rt_schedule [static] |
Definition at line 576 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 782 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 5806 of file app_meetme.c.
Referenced by sla_trunk_exec().
const char* slastation_app = "SLAStation" [static] |
Definition at line 572 of file app_meetme.c.
const char* slatrunk_app = "SLATrunk" [static] |
Definition at line 573 of file app_meetme.c.
| unsigned int stop |
Definition at line 847 of file app_meetme.c.
Referenced by controlplayback_exec(), handle_controlstreamfile(), and queue_exec().
| pthread_t thread |
The SLA thread ID
Definition at line 840 of file app_meetme.c.
Referenced by __schedule_action(), __unload_module(), ast_bridge_depart(), bridge_call_thread_launch(), find_idle_thread(), handle_cli_iax2_show_threads(), iax2_process_thread(), iax2_process_thread_cleanup(), launch_monitor_thread(), load_module(), multiplexed_add_or_remove(), socket_read(), start_network_thread(), and unload_module().
1.6.2