[asterisk-commits] oej: branch oej/tdd-sip r97628 - in /team/oej/tdd-sip: ./ apps/ channels/ cod...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Wed Jan 9 15:09:53 CST 2008
Author: oej
Date: Wed Jan 9 15:09:52 2008
New Revision: 97628
URL: http://svn.digium.com/view/asterisk?view=rev&rev=97628
Log:
Reset, resolve
Added:
team/oej/tdd-sip/channels/console_board.c
- copied unchanged from r97623, trunk/channels/console_board.c
team/oej/tdd-sip/images/font.png
- copied unchanged from r97623, trunk/images/font.png
Modified:
team/oej/tdd-sip/ (props changed)
team/oej/tdd-sip/CHANGES
team/oej/tdd-sip/apps/app_meetme.c
team/oej/tdd-sip/apps/app_queue.c
team/oej/tdd-sip/apps/app_voicemail.c
team/oej/tdd-sip/channels/Makefile
team/oej/tdd-sip/channels/chan_console.c
team/oej/tdd-sip/channels/chan_gtalk.c
team/oej/tdd-sip/channels/chan_mgcp.c
team/oej/tdd-sip/channels/chan_oss.c
team/oej/tdd-sip/channels/chan_sip.c
team/oej/tdd-sip/channels/chan_zap.c
team/oej/tdd-sip/channels/console_gui.c
team/oej/tdd-sip/channels/console_video.c
team/oej/tdd-sip/channels/console_video.h
team/oej/tdd-sip/codecs/codec_zap.c
team/oej/tdd-sip/configs/queues.conf.sample
team/oej/tdd-sip/funcs/func_groupcount.c
team/oej/tdd-sip/images/kpad2.jpg
team/oej/tdd-sip/main/asterisk.c
team/oej/tdd-sip/main/autoservice.c
team/oej/tdd-sip/main/cli.c
team/oej/tdd-sip/main/editline/readline.c
team/oej/tdd-sip/main/utils.c
team/oej/tdd-sip/res/res_features.c
team/oej/tdd-sip/res/res_jabber.c
Propchange: team/oej/tdd-sip/
------------------------------------------------------------------------------
automerge = http://www.codename-pineapple.org/
Propchange: team/oej/tdd-sip/
------------------------------------------------------------------------------
Binary property 'branch-1.4-blocked' - no diff available.
Propchange: team/oej/tdd-sip/
------------------------------------------------------------------------------
Binary property 'branch-1.4-merged' - no diff available.
Propchange: team/oej/tdd-sip/
------------------------------------------------------------------------------
--- svnmerge-integrated (original)
+++ svnmerge-integrated Wed Jan 9 15:09:52 2008
@@ -1,1 +1,1 @@
-/trunk:1-97117
+/trunk:1-97627
Modified: team/oej/tdd-sip/CHANGES
URL: http://svn.digium.com/view/asterisk/team/oej/tdd-sip/CHANGES?view=diff&rev=97628&r1=97627&r2=97628
==============================================================================
--- team/oej/tdd-sip/CHANGES (original)
+++ team/oej/tdd-sip/CHANGES Wed Jan 9 15:09:52 2008
@@ -265,6 +265,9 @@
* Added new channel variable QUEUE_MIN_PENALTY
* QUEUE_MAX_PENALTY and QUEUE_MIN_PENALTY may be adjusted in mid-call by defining
rules in queuerules.conf. See configs/queuerules.conf.sample for details
+ * Added a new parameter for member definition, called state_interface. This may be
+ used so that a member may be called via one interface but have a different interface's
+ device state reported.
MeetMe Changes
--------------
Modified: team/oej/tdd-sip/apps/app_meetme.c
URL: http://svn.digium.com/view/asterisk/team/oej/tdd-sip/apps/app_meetme.c?view=diff&rev=97628&r1=97627&r2=97628
==============================================================================
--- team/oej/tdd-sip/apps/app_meetme.c (original)
+++ team/oej/tdd-sip/apps/app_meetme.c Wed Jan 9 15:09:52 2008
@@ -1796,7 +1796,7 @@
goto outrun;
}
- retryzap = (strcasecmp(chan->tech->type, "Zap") || chan->audiohooks ? 1 : 0);
+ retryzap = (strcasecmp(chan->tech->type, "Zap") || (chan->audiohooks || chan->monitor) ? 1 : 0);
user->zapchannel = !retryzap;
zapretry:
@@ -2240,14 +2240,14 @@
break;
if (c) {
- if (c->fds[0] != origfd || (user->zapchannel && c->audiohooks)) {
+ if (c->fds[0] != origfd || (user->zapchannel && (c->audiohooks || c->monitor))) {
if (using_pseudo) {
/* Kill old pseudo */
close(fd);
using_pseudo = 0;
}
ast_debug(1, "Ooh, something swapped out under us, starting over\n");
- retryzap = (strcasecmp(c->tech->type, "Zap") || c->audiohooks ? 1 : 0);
+ retryzap = (strcasecmp(c->tech->type, "Zap") || (c->audiohooks || c->monitor) ? 1 : 0);
user->zapchannel = !retryzap;
goto zapretry;
}
Modified: team/oej/tdd-sip/apps/app_queue.c
URL: http://svn.digium.com/view/asterisk/team/oej/tdd-sip/apps/app_queue.c?view=diff&rev=97628&r1=97627&r2=97628
==============================================================================
--- team/oej/tdd-sip/apps/app_queue.c (original)
+++ team/oej/tdd-sip/apps/app_queue.c Wed Jan 9 15:09:52 2008
@@ -352,7 +352,8 @@
};
struct member {
- char interface[80]; /*!< Technology/Location */
+ char interface[80]; /*!< Technology/Location to dial to reach this member*/
+ char state_interface[80]; /*!< Technology/Location from which to read devicestate changes */
char membername[80]; /*!< Member name to use in queue logs */
int penalty; /*!< Are we a last resort? */
int calls; /*!< Number of calls serviced by this member */
@@ -496,6 +497,7 @@
static void update_realtime_members(struct call_queue *q);
static int set_member_paused(const char *queuename, const char *interface, const char *reason, int paused);
+/*! \brief sets the QUEUESTATUS channel variable */
static void set_queue_result(struct ast_channel *chan, enum queue_result res)
{
int i;
@@ -603,6 +605,12 @@
QUEUE_NORMAL
};
+/*! \brief Check if members are available
+ *
+ * This function checks to see if members are available to be called. If any member
+ * is available, the function immediately returns QUEUE_NORMAL. If no members are available,
+ * the appropriate reason why is returned
+ */
static enum queue_member_status get_member_status(struct call_queue *q, int max_penalty, int min_penalty)
{
struct member *member;
@@ -644,7 +652,7 @@
int state;
char dev[0];
};
-
+/*! \brief set a member's status based on device state of that member's state_interface*/
static void *handle_statechange(struct statechange *sc)
{
struct call_queue *q;
@@ -690,7 +698,7 @@
while ((cur = ao2_iterator_next(&mem_iter))) {
char *interface;
char *slash_pos;
- interface = ast_strdupa(cur->interface);
+ interface = ast_strdupa(cur->state_interface);
if ((slash_pos = strchr(interface, '/')))
if ((slash_pos = strchr(slash_pos + 1, '/')))
*slash_pos = '\0';
@@ -747,6 +755,7 @@
.thread = AST_PTHREADT_NULL,
};
+/*! \brief Consumer of the statechange queue */
static void *device_state_thread(void *data)
{
struct statechange *sc = NULL;
@@ -780,7 +789,7 @@
return NULL;
}
-
+/*! \brief Producer of the statechange queue */
static int statechange_queue(const char *dev, enum ast_device_state state)
{
struct statechange *sc;
@@ -798,7 +807,6 @@
return 0;
}
-
static void device_state_cb(const struct ast_event *event, void *unused)
{
enum ast_device_state state;
@@ -815,7 +823,8 @@
statechange_queue(device, state);
}
-static struct member *create_queue_member(const char *interface, const char *membername, int penalty, int paused)
+/*! \brief allocate space for new queue member and set fields based on parameters passed */
+static struct member *create_queue_member(const char *interface, const char *membername, int penalty, int paused, const char *state_interface)
{
struct member *cur;
@@ -823,6 +832,10 @@
cur->penalty = penalty;
cur->paused = paused;
ast_copy_string(cur->interface, interface, sizeof(cur->interface));
+ if (!ast_strlen_zero(state_interface))
+ ast_copy_string(cur->state_interface, state_interface, sizeof(cur->state_interface));
+ else
+ ast_copy_string(cur->state_interface, interface, sizeof(cur->state_interface));
if (!ast_strlen_zero(membername))
ast_copy_string(cur->membername, membername, sizeof(cur->membername));
else
@@ -958,20 +971,20 @@
{
struct call_queue *q;
struct member *mem, tmpmem;
- struct ao2_iterator queue_iter;
+ struct ao2_iterator queue_iter, mem_iter;
int ret = 0;
ast_copy_string(tmpmem.interface, interface, sizeof(tmpmem.interface));
queue_iter = ao2_iterator_init(queues, 0);
while ((q = ao2_iterator_next(&queue_iter))) {
-
ao2_lock(q);
- if ((mem = ao2_find(q->members, &tmpmem, OBJ_POINTER))) {
- ao2_ref(mem, -1);
- ao2_unlock(q);
- queue_unref(q);
- ret = 1;
- break;
+ mem_iter = ao2_iterator_init(q->members, 0);
+ while ((mem = ao2_iterator_next(&mem_iter))) {
+ if (!strcasecmp(mem->state_interface, interface)) {
+ ao2_ref(mem, -1);
+ ret = 1;
+ break;
+ }
}
ao2_unlock(q);
queue_unref(q);
@@ -991,7 +1004,7 @@
ast_debug(1, "Removing %s from the list of interfaces that make up all of our queue members.\n", interface);
AST_LIST_REMOVE_CURRENT(list);
ast_free(curint);
- }
+ }
break;
}
}
@@ -1256,7 +1269,7 @@
}
}
-static void rt_handle_member_record(struct call_queue *q, char *interface, const char *membername, const char *penalty_str, const char *paused_str)
+static void rt_handle_member_record(struct call_queue *q, char *interface, const char *membername, const char *penalty_str, const char *paused_str, const char* state_interface)
{
struct member *m, tmpmem;
int penalty = 0;
@@ -1280,10 +1293,10 @@
/* Create a new one if not found, else update penalty */
if (!m) {
- if ((m = create_queue_member(interface, membername, penalty, paused))) {
+ if ((m = create_queue_member(interface, membername, penalty, paused, state_interface))) {
m->dead = 0;
m->realtime = 1;
- add_to_interfaces(interface);
+ add_to_interfaces(state_interface);
ao2_link(q->members, m);
ao2_ref(m, -1);
m = NULL;
@@ -1293,6 +1306,11 @@
m->dead = 0; /* Do not delete this one. */
if (paused_str)
m->paused = paused;
+ if (strcasecmp(state_interface, m->state_interface)) {
+ remove_from_interfaces(m->state_interface);
+ ast_copy_string(m->state_interface, state_interface, sizeof(m->state_interface));
+ add_to_interfaces(m->state_interface);
+ }
m->penalty = penalty;
ao2_ref(m, -1);
}
@@ -1307,7 +1325,7 @@
while ((cur = ao2_iterator_next(&mem_iter))) {
if (all || !cur->dynamic) {
ao2_unlink(q->members, cur);
- remove_from_interfaces(cur->interface);
+ remove_from_interfaces(cur->state_interface);
q->membercount--;
}
ao2_ref(cur, -1);
@@ -1436,7 +1454,8 @@
rt_handle_member_record(q, interface,
ast_variable_retrieve(member_config, interface, "membername"),
ast_variable_retrieve(member_config, interface, "penalty"),
- ast_variable_retrieve(member_config, interface, "paused"));
+ ast_variable_retrieve(member_config, interface, "paused"),
+ ast_variable_retrieve(member_config, interface, "state_interface"));
}
/* Delete all realtime members that have been deleted in DB. */
@@ -1444,9 +1463,7 @@
while ((m = ao2_iterator_next(&mem_iter))) {
if (m->dead) {
ao2_unlink(q->members, m);
- ao2_unlock(q);
- remove_from_interfaces(m->interface);
- ao2_lock(q);
+ remove_from_interfaces(m->state_interface);
q->membercount--;
}
ao2_ref(m, -1);
@@ -1549,7 +1566,8 @@
rt_handle_member_record(q, interface,
S_OR(ast_variable_retrieve(member_config, interface, "membername"), interface),
ast_variable_retrieve(member_config, interface, "penalty"),
- ast_variable_retrieve(member_config, interface, "paused"));
+ ast_variable_retrieve(member_config, interface, "paused"),
+ ast_variable_retrieve(member_config, interface, "state_interface"));
}
/* Delete all realtime members that have been deleted in DB. */
@@ -1557,9 +1575,7 @@
while ((m = ao2_iterator_next(&mem_iter))) {
if (m->dead) {
ao2_unlink(q->members, m);
- ao2_unlock(q);
- remove_from_interfaces(m->interface);
- ao2_lock(q);
+ remove_from_interfaces(m->state_interface);
q->membercount--;
}
ao2_ref(m, -1);
@@ -2013,6 +2029,11 @@
return vars;
}
+/*! \brief Part 2 of ring_one
+ *
+ * Does error checking before attempting to request a channel and call a member. This
+ * function is only called from ring_one
+ */
static int ring_entry(struct queue_ent *qe, struct callattempt *tmp, int *busies)
{
int res;
@@ -2160,6 +2181,14 @@
return best;
}
+/*! \brief Place a call to a queue member
+ *
+ * Once metrics have been calculated for each member, this function is used
+ * to place a call to the appropriate member (or members). The low-level
+ * channel-handling and error detection is handled in ring_entry
+ *
+ * Returns 1 if a member was called successfully, 0 otherwise
+ */
static int ring_one(struct queue_ent *qe, struct callattempt *outgoing, int *busies)
{
int ret = 0;
@@ -2317,7 +2346,16 @@
}
#define AST_MAX_WATCHERS 256
-
+/*! \brief Wait for a member to answer the call
+ *
+ * \param[in] qe the queue_ent corresponding to the caller in the queue
+ * \param[in] outgoing the list of callattempts. Relevant ones will have their chan and stillgoing parameters non-zero
+ * \param[in] to the amount of time (in milliseconds) to wait for a response
+ * \param[out] digit if a user presses a digit to exit the queue, this is the digit the caller pressed
+ * \param[in] prebusies number of busy members calculated prior to calling wait_for_answer
+ * \param[in] caller_disconnect if the 'H' option is used when calling Queue(), this is used to detect if the caller pressed * to disconnect the call
+ * \param[in] forwardsallowed used to detect if we should allow call forwarding, based on the 'i' option to Queue()
+ */
static struct callattempt *wait_for_answer(struct queue_ent *qe, struct callattempt *outgoing, int *to, char *digit, int prebusies, int caller_disconnect, int forwardsallowed)
{
const char *queue = qe->parent->name;
@@ -2564,7 +2602,15 @@
return peer;
}
-
+/*! \brief Check if we should start attempting to call queue members
+ *
+ * The behavior of this function is dependent first on whether autofill is enabled
+ * and second on whether the ring strategy is ringall. If autofill is not enabled,
+ * then return true if we're the head of the queue. If autofill is enabled, then
+ * we count the available members and see if the number of available members is enough
+ * that given our position in the queue, we would theoretically be able to connect to
+ * one of those available members
+ */
static int is_our_turn(struct queue_ent *qe)
{
struct queue_ent *ch;
@@ -2629,7 +2675,6 @@
return res;
}
-
static void update_qe_rule(struct queue_ent *qe)
{
int max_penalty = qe->pr->max_relative ? qe->max_penalty + qe->pr->max_value : qe->pr->max_value;
@@ -2652,6 +2697,16 @@
qe->pr = AST_LIST_NEXT(qe->pr, list);
}
+/*! \brief The waiting areas for callers who are not actively calling members
+ *
+ * This function is one large loop. This function will return if a caller
+ * either exits the queue or it becomes that caller's turn to attempt calling
+ * queue members. Inside the loop, we service the caller with periodic announcements,
+ * holdtime announcements, etc. as configured in queues.conf
+ *
+ * \retval 0 if the caller's turn has arrived
+ * \retval -1 if the caller should exit the queue.
+ */
static int wait_our_turn(struct queue_ent *qe, int ringing, enum queue_result *reason)
{
int res = 0;
@@ -2754,6 +2809,12 @@
return 0;
}
+/*! \brief Calculate the metric of each member in the outgoing callattempts
+ *
+ * A numeric metric is given to each member depending on the ring strategy used
+ * by the queue. Members with lower metrics will be called before members with
+ * higher metrics
+ */
static int calc_metric(struct call_queue *q, struct member *mem, int pos, struct queue_ent *qe, struct callattempt *tmp)
{
if ((qe->max_penalty && (mem->penalty > qe->max_penalty)) || (qe->min_penalty && (mem->penalty < qe->min_penalty)))
@@ -2852,7 +2913,32 @@
(long)(callstart - qe->start), (long)(time(NULL) - callstart), reason,
qe->parent->eventwhencalled == QUEUE_EVENT_VARIABLES ? vars2manager(qe->chan, vars, vars_len) : "");
}
-
+/*! \brief A large function which calls members, updates statistics, and bridges the caller and a member
+ *
+ * Here is the process of this function
+ * 1. Process any options passed to the Queue() application. Options here mean the third argument to Queue()
+ * 2. Iterate trough the members of the queue, creating a callattempt corresponding to each member. During this
+ * iteration, we also check the dialed_interfaces datastore to see if we have already attempted calling this
+ * member. If we have, we do not create a callattempt. This is in place to prevent call forwarding loops. Also
+ * during each iteration, we call calc_metric to determine which members should be rung when.
+ * 3. Call ring_one to place a call to the appropriate member(s)
+ * 4. Call wait_for_answer to wait for an answer. If no one answers, return.
+ * 5. Take care of any holdtime announcements, member delays, or other options which occur after a call has been answered.
+ * 6. Start the monitor or mixmonitor if the option is set
+ * 7. Remove the caller from the queue to allow other callers to advance
+ * 8. Bridge the call.
+ * 9. Do any post processing after the call has disconnected.
+ *
+ * \param[in] qe the queue_ent structure which corresponds to the caller attempting to reach members
+ * \param[in] options the options passed as the third parameter to the Queue() application
+ * \param[in] url the url passed as the fourth parameter to the Queue() application
+ * \param[in,out] tries the number of times we have tried calling queue members
+ * \param[out] noption set if the call to Queue() has the 'n' option set.
+ * \param[in] agi the agi passed as the fifth parameter to the Queue() application
+ * \param[in] macro the macro passed as the sixth parameter to the Queue() application
+ * \param[in] gosub the gosub passed as the seventh parameter to the Queue() application
+ * \param[in] ringing 1 if the 'r' option is set, otherwise 0
+ */
static int try_calling(struct queue_ent *qe, const char *options, char *announceoverride, const char *url, int *tries, int *noption, const char *agi, const char *macro, const char *gosub, int ringing)
{
struct member *cur;
@@ -3578,6 +3664,7 @@
"MemberName: %s\r\n",
q->name, mem->interface, mem->membername);
ao2_unlink(q->members, mem);
+ remove_from_interfaces(mem->state_interface);
ao2_ref(mem, -1);
if (queue_persistent_members)
@@ -3591,14 +3678,11 @@
queue_unref(q);
}
- if (res == RES_OKAY)
- remove_from_interfaces(interface);
-
return res;
}
-static int add_to_queue(const char *queuename, const char *interface, const char *membername, int penalty, int paused, int dump)
+static int add_to_queue(const char *queuename, const char *interface, const char *membername, int penalty, int paused, int dump, const char *state_interface)
{
struct call_queue *q;
struct member *new_member, *old_member;
@@ -3613,8 +3697,8 @@
ao2_lock(q);
if ((old_member = interface_exists(q, interface)) == NULL) {
- add_to_interfaces(interface);
- if ((new_member = create_queue_member(interface, membername, penalty, paused))) {
+ if ((new_member = create_queue_member(interface, membername, penalty, paused, state_interface))) {
+ add_to_interfaces(state_interface);
new_member->dynamic = 1;
ao2_link(q->members, new_member);
q->membercount++;
@@ -3797,6 +3881,7 @@
char *member;
char *interface;
char *membername = NULL;
+ char *state_interface;
char *penalty_tok;
int penalty = 0;
char *paused_tok;
@@ -3846,6 +3931,7 @@
penalty_tok = strsep(&member, ";");
paused_tok = strsep(&member, ";");
membername = strsep(&member, ";");
+ state_interface = strsep(&member, ";");
if (!penalty_tok) {
ast_log(LOG_WARNING, "Error parsing persistent member string for '%s' (penalty)\n", queue_name);
@@ -3866,12 +3952,10 @@
ast_log(LOG_WARNING, "Error converting paused: %s: Expected 0 or 1.\n", paused_tok);
break;
}
- if (ast_strlen_zero(membername))
- membername = interface;
ast_debug(1, "Reload Members: Queue: %s Member: %s Name: %s Penalty: %d Paused: %d\n", queue_name, interface, membername, penalty, paused);
- if (add_to_queue(queue_name, interface, membername, penalty, paused, 0) == RES_OUTOFMEMORY) {
+ if (add_to_queue(queue_name, interface, membername, penalty, paused, 0, state_interface) == RES_OUTOFMEMORY) {
ast_log(LOG_ERROR, "Out of Memory when reloading persistent queue member\n");
break;
}
@@ -4020,6 +4104,7 @@
AST_APP_ARG(penalty);
AST_APP_ARG(options);
AST_APP_ARG(membername);
+ AST_APP_ARG(state_interface);
);
int penalty = 0;
@@ -4046,7 +4131,7 @@
}
}
- switch (add_to_queue(args.queuename, args.interface, args.membername, penalty, 0, queue_persistent_members)) {
+ switch (add_to_queue(args.queuename, args.interface, args.membername, penalty, 0, queue_persistent_members, args.state_interface)) {
case RES_OKAY:
ast_queue_log(args.queuename, chan->uniqueid, args.interface, "ADDMEMBER", "%s", "");
ast_log(LOG_NOTICE, "Added interface '%s' to queue '%s'\n", args.interface, args.queuename);
@@ -4133,6 +4218,18 @@
AST_LIST_UNLOCK(&rule_lists);
}
+/*!\brief The starting point for all queue calls
+ *
+ * The process involved here is to
+ * 1. Parse the options specified in the call to Queue()
+ * 2. Join the queue
+ * 3. Wait in a loop until it is our turn to try calling a queue member
+ * 4. Attempt to call a queue member
+ * 5. If 4. did not result in a bridged call, then check for between
+ * call options such as periodic announcements etc.
+ * 6. Try 4 again uless some condition (such as an expiration time) causes us to
+ * exit the queue.
+ */
static int queue_exec(struct ast_channel *chan, void *data)
{
int res=-1;
@@ -4803,7 +4900,7 @@
int new;
const char *general_val = NULL;
char parse[80];
- char *interface;
+ char *interface, *state_interface;
char *membername = NULL;
int penalty;
struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
@@ -4812,6 +4909,7 @@
AST_APP_ARG(interface);
AST_APP_ARG(penalty);
AST_APP_ARG(membername);
+ AST_APP_ARG(state_interface);
);
/*First things first. Let's load queuerules.conf*/
@@ -4880,8 +4978,10 @@
/* Check if a queue with this name already exists */
if (q->found) {
ast_log(LOG_WARNING, "Queue '%s' already defined! Skipping!\n", cat);
- if (!new)
+ if (!new) {
ao2_unlock(q);
+ queue_unref(q);
+ }
continue;
}
/* Due to the fact that the "linear" strategy will have a different allocation
@@ -4933,11 +5033,22 @@
while (*membername && *membername < 33) membername++;
}
+ if (!ast_strlen_zero(args.state_interface)) {
+ state_interface = args.state_interface;
+ while (*state_interface && *state_interface < 33) state_interface++;
+ } else
+ state_interface = interface;
+
/* Find the old position in the list */
ast_copy_string(tmpmem.interface, interface, sizeof(tmpmem.interface));
cur = ao2_find(q->members, &tmpmem, OBJ_POINTER | OBJ_UNLINK);
-
- newm = create_queue_member(interface, membername, penalty, cur ? cur->paused : 0);
+ /* Only attempt removing from interfaces list if the new state_interface is different than the old one */
+ if (cur && strcasecmp(cur->state_interface, state_interface)) {
+ remove_from_interfaces(cur->state_interface);
+ }
+ newm = create_queue_member(interface, membername, penalty, cur ? cur->paused : 0, state_interface);
+ if (!cur || (cur && strcasecmp(cur->state_interface, state_interface)))
+ add_to_interfaces(state_interface);
ao2_link(q->members, newm);
ao2_ref(newm, -1);
newm = NULL;
@@ -4945,8 +5056,6 @@
if (cur)
ao2_ref(cur, -1);
else {
- /* Add them to the master int list if necessary */
- add_to_interfaces(interface);
q->membercount++;
}
} else {
@@ -4961,16 +5070,16 @@
ao2_ref(cur, -1);
continue;
}
-
- remove_from_interfaces(cur->interface);
+ ast_log(LOG_DEBUG, "%s in queue marked as delme, we should be deleting...\n", cur->interface);
q->membercount--;
ao2_unlink(q->members, cur);
+ remove_from_interfaces(cur->interface);
ao2_ref(cur, -1);
}
if (new) {
ao2_link(queues, q);
- } else
+ } else
ao2_unlock(q);
queue_unref(q);
}
@@ -5352,7 +5461,7 @@
static int manager_add_queue_member(struct mansession *s, const struct message *m)
{
- const char *queuename, *interface, *penalty_s, *paused_s, *membername;
+ const char *queuename, *interface, *penalty_s, *paused_s, *membername, *state_interface;
int paused, penalty = 0;
queuename = astman_get_header(m, "Queue");
@@ -5360,6 +5469,7 @@
penalty_s = astman_get_header(m, "Penalty");
paused_s = astman_get_header(m, "Paused");
membername = astman_get_header(m, "MemberName");
+ state_interface = astman_get_header(m, "StateInterface");
if (ast_strlen_zero(queuename)) {
astman_send_error(s, m, "'Queue' not specified.");
@@ -5381,7 +5491,7 @@
else
paused = abs(ast_true(paused_s));
- switch (add_to_queue(queuename, interface, membername, penalty, paused, queue_persistent_members)) {
+ switch (add_to_queue(queuename, interface, membername, penalty, paused, queue_persistent_members, state_interface)) {
case RES_OKAY:
ast_queue_log(queuename, "MANAGER", interface, "ADDMEMBER", "%s", "");
astman_send_ack(s, m, "Added interface to queue");
@@ -5537,26 +5647,28 @@
static char *handle_queue_add_member(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
{
- char *queuename, *interface, *membername = NULL;
+ char *queuename, *interface, *membername = NULL, *state_interface = NULL;
int penalty;
switch ( cmd ) {
case CLI_INIT:
e->command = "queue add member";
e->usage =
- "Usage: queue add member <channel> to <queue> [penalty <penalty>]\n";
+ "Usage: queue add member <channel> to <queue> [[[penalty <penalty>] as <membername>] state_interface <interface>]\n";
return NULL;
case CLI_GENERATE:
return complete_queue_add_member(a->line, a->word, a->pos, a->n);
}
- if ((a->argc != 6) && (a->argc != 8) && (a->argc != 10)) {
+ if ((a->argc != 6) && (a->argc != 8) && (a->argc != 10) && (a->argc != 12)) {
return CLI_SHOWUSAGE;
} else if (strcmp(a->argv[4], "to")) {
return CLI_SHOWUSAGE;
- } else if ((a->argc == 8) && strcmp(a->argv[6], "penalty")) {
+ } else if ((a->argc >= 8) && strcmp(a->argv[6], "penalty")) {
return CLI_SHOWUSAGE;
- } else if ((a->argc == 10) && strcmp(a->argv[8], "as")) {
+ } else if ((a->argc >= 10) && strcmp(a->argv[8], "as")) {
+ return CLI_SHOWUSAGE;
+ } else if ((a->argc == 12) && strcmp(a->argv[10], "state_interface")) {
return CLI_SHOWUSAGE;
}
@@ -5580,7 +5692,11 @@
membername = a->argv[9];
}
- switch (add_to_queue(queuename, interface, membername, penalty, 0, queue_persistent_members)) {
+ if (a->argc >= 12) {
+ state_interface = a->argv[11];
+ }
+
+ switch (add_to_queue(queuename, interface, membername, penalty, 0, queue_persistent_members, state_interface)) {
case RES_OKAY:
ast_queue_log(queuename, "CLI", interface, "ADDMEMBER", "%s", "");
ast_cli(a->fd, "Added interface '%s' to queue '%s'\n", interface, queuename);
Modified: team/oej/tdd-sip/apps/app_voicemail.c
URL: http://svn.digium.com/view/asterisk/team/oej/tdd-sip/apps/app_voicemail.c?view=diff&rev=97628&r1=97627&r2=97628
==============================================================================
--- team/oej/tdd-sip/apps/app_voicemail.c (original)
+++ team/oej/tdd-sip/apps/app_voicemail.c Wed Jan 9 15:09:52 2008
@@ -240,13 +240,15 @@
OPT_RECORDGAIN = (1 << 3),
OPT_PREPEND_MAILBOX = (1 << 4),
OPT_AUTOPLAY = (1 << 6),
+ OPT_DTMFEXIT = (1 << 7),
} vm_option_flags;
enum {
OPT_ARG_RECORDGAIN = 0,
OPT_ARG_PLAYFOLDER = 1,
+ OPT_ARG_DTMFEXIT = 2,
/* This *must* be the last value in this enum! */
- OPT_ARG_ARRAY_SIZE = 2,
+ OPT_ARG_ARRAY_SIZE = 3,
} vm_option_args;
AST_APP_OPTIONS(vm_app_options, {
@@ -254,6 +256,7 @@
AST_APP_OPTION('b', OPT_BUSY_GREETING),
AST_APP_OPTION('u', OPT_UNAVAIL_GREETING),
AST_APP_OPTION_ARG('g', OPT_RECORDGAIN, OPT_ARG_RECORDGAIN),
+ AST_APP_OPTION_ARG('d', OPT_DTMFEXIT, OPT_ARG_DTMFEXIT),
AST_APP_OPTION('p', OPT_PREPEND_MAILBOX),
AST_APP_OPTION_ARG('a', OPT_AUTOPLAY, OPT_ARG_PLAYFOLDER),
});
@@ -496,12 +499,14 @@
" application. The possible values are:\n"
" SUCCESS | USEREXIT | FAILED\n\n"
" Options:\n"
- " b - Play the 'busy' greeting to the calling party.\n"
- " g(#) - Use the specified amount of gain when recording the voicemail\n"
- " message. The units are whole-number decibels (dB).\n"
- " s - Skip the playback of instructions for leaving a message to the\n"
- " calling party.\n"
- " u - Play the 'unavailable' greeting.\n";
+ " b - Play the 'busy' greeting to the calling party.\n"
+ " d([c]) - Accept digits for a new extension in context c, if played during\n"
+ " the greeting. Context defaults to the current context.\n"
+ " g(#) - Use the specified amount of gain when recording the voicemail\n"
+ " message. The units are whole-number decibels (dB).\n"
+ " s - Skip the playback of instructions for leaving a message to the\n"
+ " calling party.\n"
+ " u - Play the 'unavailable' greeting.\n";
static char *synopsis_vmain = "Check Voicemail messages";
@@ -2743,11 +2748,11 @@
{
struct vm_state *sendvms = NULL, *destvms = NULL;
char messagestring[10]; /*I guess this could be a problem if someone has more than 999999999 messages...*/
- if (!(sendvms = get_vm_state_by_imapuser(vmu->imapuser, 2))) {
+ if (!(sendvms = get_vm_state_by_imapuser(vmu->imapuser, 0))) {
ast_log(LOG_ERROR, "Couldn't get vm_state for originator's mailbox!!\n");
return -1;
}
- if (!(destvms = get_vm_state_by_imapuser(recip->imapuser, 2))) {
+ if (!(destvms = get_vm_state_by_imapuser(recip->imapuser, 0))) {
ast_log(LOG_ERROR, "Couldn't get vm_state for destination mailbox!\n");
return -1;
}
@@ -2952,6 +2957,7 @@
struct leave_vm_options {
unsigned int flags;
signed char record_gain;
+ char *exitcontext;
};
static int leave_voicemail(struct ast_channel *chan, char *ext, struct leave_vm_options *options)
@@ -2983,11 +2989,11 @@
char ext_context[256] = "";
char fmt[80];
char *context;
- char ecodes[16] = "#";
+ char ecodes[17] = "#";
char tmp[1024] = "", *tmpptr;
struct ast_vm_user *vmu;
struct ast_vm_user svm;
- const char *category = NULL;
+ const char *category = NULL, *code, *alldtmf = "0123456789ABCD*#";
ast_copy_string(tmp, ext, sizeof(tmp));
ext = tmp;
@@ -3056,6 +3062,15 @@
else if (!ast_strlen_zero(chan->macrocontext) && ast_exists_extension(chan, chan->macrocontext, "a", 1, chan->cid.cid_num)) {
strncat(ecodes, "*", sizeof(ecodes) - strlen(ecodes) - 1);
ausemacro = 1;
+ }
+
+ if (ast_test_flag(options, OPT_DTMFEXIT)) {
+ for (code = alldtmf; *code; code++) {
+ char e[2] = "";
+ e[0] = *code;
+ if (strchr(ecodes, e[0]) == NULL && ast_canmatch_extension(chan, chan->context, e, 1, chan->cid.cid_num))
+ strncat(ecodes, e, sizeof(ecodes) - strlen(ecodes) - 1);
+ }
}
/* Play the beginning intro if desired */
@@ -3102,7 +3117,7 @@
ast_stopstream(chan);
/* Check for a '*' here in case the caller wants to escape from voicemail to something
other than the operator -- an automated attendant or mailbox login for example */
- if (res == '*') {
+ if (!ast_strlen_zero(vmu->exit) && (res == '*')) {
chan->exten[0] = 'a';
chan->exten[1] = '\0';
if (!ast_strlen_zero(vmu->exit)) {
@@ -3117,7 +3132,7 @@
}
/* Check for a '0' here */
- if (res == '0') {
+ if (ast_test_flag(vmu, VM_OPERATOR) && res == '0') {
transfer:
if (ouseexten || ousemacro) {
chan->exten[0] = 'o';
@@ -3134,6 +3149,16 @@
}
return 0;
}
+
+ /* Allow all other digits to exit Voicemail and return to the dialplan */
+ if (ast_test_flag(options, OPT_DTMFEXIT) && res > 0) {
+ if (!ast_strlen_zero(options->exitcontext))
+ ast_copy_string(chan->context, options->exitcontext, sizeof(chan->context));
+ free_user(vmu);
+ pbx_builtin_setvar_helper(chan, "VMSTATUS", "USEREXIT");
+ return res;
+ }
+
if (res < 0) {
free_user(vmu);
pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
@@ -4936,7 +4961,7 @@
stream = mail_open (stream, tmp, debug ? OP_DEBUG : NIL);
if (stream == NIL) {
ast_log (LOG_ERROR, "Can't connect to imap server %s\n", tmp);
- return NIL;
+ return -1;
}
get_mailbox_delimiter(stream);
/* update delimiter in imapfolder */
@@ -7400,7 +7425,7 @@
if (args.argc == 2) {
if (ast_app_parse_options(vm_app_options, &flags, opts, args.argv1))
return -1;
- ast_copy_flags(&leave_options, &flags, OPT_SILENT | OPT_BUSY_GREETING | OPT_UNAVAIL_GREETING);
+ ast_copy_flags(&leave_options, &flags, OPT_SILENT | OPT_BUSY_GREETING | OPT_UNAVAIL_GREETING | OPT_DTMFEXIT);
if (ast_test_flag(&flags, OPT_RECORDGAIN)) {
int gain;
@@ -7410,6 +7435,10 @@
} else {
leave_options.record_gain = (signed char) gain;
}
+ }
+ if (ast_test_flag(&flags, OPT_DTMFEXIT)) {
+ if (!ast_strlen_zero(opts[OPT_ARG_DTMFEXIT]))
+ leave_options.exitcontext = opts[OPT_ARG_DTMFEXIT];
}
}
} else {
Modified: team/oej/tdd-sip/channels/Makefile
URL: http://svn.digium.com/view/asterisk/team/oej/tdd-sip/channels/Makefile?view=diff&rev=97628&r1=97627&r2=97628
==============================================================================
--- team/oej/tdd-sip/channels/Makefile (original)
+++ team/oej/tdd-sip/channels/Makefile Wed Jan 9 15:09:52 2008
@@ -102,4 +102,4 @@
chan_vpb.oo: ASTCFLAGS:=$(filter-out -Wdeclaration-after-statement,$(ASTCFLAGS))
-$(if $(filter chan_oss,$(EMBEDDED_MODS)),modules.link,chan_oss.so): console_video.o vgrabbers.o
+$(if $(filter chan_oss,$(EMBEDDED_MODS)),modules.link,chan_oss.so): console_video.o vgrabbers.o console_board.o
Modified: team/oej/tdd-sip/channels/chan_console.c
URL: http://svn.digium.com/view/asterisk/team/oej/tdd-sip/channels/chan_console.c?view=diff&rev=97628&r1=97627&r2=97628
==============================================================================
--- team/oej/tdd-sip/channels/chan_console.c (original)
+++ team/oej/tdd-sip/channels/chan_console.c Wed Jan 9 15:09:52 2008
@@ -29,7 +29,7 @@
*
* \ingroup channel_drivers
*
- * \arg http://www.portaudio.com/
+ * \extref Portaudio http://www.portaudio.com/
*
* To install portaudio v19 from svn, check it out using the following command:
* - svn co https://www.portaudio.com/repos/portaudio/branches/v19-devel
Modified: team/oej/tdd-sip/channels/chan_gtalk.c
URL: http://svn.digium.com/view/asterisk/team/oej/tdd-sip/channels/chan_gtalk.c?view=diff&rev=97628&r1=97627&r2=97628
==============================================================================
--- team/oej/tdd-sip/channels/chan_gtalk.c (original)
+++ team/oej/tdd-sip/channels/chan_gtalk.c Wed Jan 9 15:09:52 2008
@@ -896,6 +896,9 @@
return NULL;
}
+ /* Set CALLERID(name) to the full JID of the remote peer */
+ ast_copy_string(tmp->cid_name, tmp->them, sizeof(tmp->cid_name));
+
if(strchr(tmp->us, '/')) {
data = ast_strdupa(tmp->us);
exten = strsep(&data, "/");
@@ -917,7 +920,6 @@
int fmt;
int what;
const char *n2;
- char *data = NULL, *cid = NULL;
if (title)
n2 = title;
@@ -981,20 +983,7 @@
ast_module_ref(ast_module_info->self);
ast_copy_string(tmp->context, client->context, sizeof(tmp->context));
ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
- /* Don't use ast_set_callerid() here because it will
- * generate a needless NewCallerID event */
- if (!strcasecmp(client->name, "guest")) {
- data = ast_strdupa(i->them);
- if (strchr(data, '/')) {
- cid = strsep(&data, "/");
- } else
- cid = data;
- } else {
- data = ast_strdupa(client->user);
- cid = data;
- }
- cid = strsep(&cid, "@");
- tmp->cid.cid_ani = ast_strdup(cid);
+
if (!ast_strlen_zero(i->exten) && strcmp(i->exten, "s"))
tmp->cid.cid_dnid = ast_strdup(i->exten);
tmp->priority = 1;
Modified: team/oej/tdd-sip/channels/chan_mgcp.c
URL: http://svn.digium.com/view/asterisk/team/oej/tdd-sip/channels/chan_mgcp.c?view=diff&rev=97628&r1=97627&r2=97628
==============================================================================
--- team/oej/tdd-sip/channels/chan_mgcp.c (original)
+++ team/oej/tdd-sip/channels/chan_mgcp.c Wed Jan 9 15:09:52 2008
@@ -428,6 +428,7 @@
static int mgcp_senddigit_begin(struct ast_channel *ast, char digit);
static int mgcp_senddigit_end(struct ast_channel *ast, char digit, unsigned int duration);
static int mgcp_devicestate(void *data);
+static void add_header_offhook(struct mgcp_subchannel *sub, struct mgcp_request *resp);
static const struct ast_channel_tech mgcp_tech = {
.type = "MGCP",
@@ -1300,23 +1301,50 @@
static int mgcp_senddigit_begin(struct ast_channel *ast, char digit)
{
- /* Let asterisk play inband indications */
- return -1;
+ struct mgcp_subchannel *sub = ast->tech_pvt;
+ struct mgcp_endpoint *p = sub->parent;
+ int res = 0;
+
+ ast_mutex_lock(&sub->lock);
+ if (p->dtmfmode & MGCP_DTMF_INBAND || p->dtmfmode & MGCP_DTMF_HYBRID) {
+ ast_log(LOG_DEBUG, "Sending DTMF using inband/hybrid\n");
+ res = -1; /* Let asterisk play inband indications */
+ } else if (p->dtmfmode & MGCP_DTMF_RFC2833) {
+ ast_log(LOG_DEBUG, "Sending DTMF using RFC2833");
+ ast_rtp_senddigit_begin(sub->rtp, digit);
+ } else {
+ ast_log(LOG_ERROR, "Don't know about DTMF_MODE %d\n", p->dtmfmode);
+ }
+ ast_mutex_unlock(&sub->lock);
+
+ return res;
}
static int mgcp_senddigit_end(struct ast_channel *ast, char digit, unsigned int duration)
{
struct mgcp_subchannel *sub = ast->tech_pvt;
+ struct mgcp_endpoint *p = sub->parent;
+ int res = 0;
char tmp[4];
- tmp[0] = 'D';
- tmp[1] = '/';
- tmp[2] = digit;
- tmp[3] = '\0';
ast_mutex_lock(&sub->lock);
- transmit_notify_request(sub, tmp);
+ if (p->dtmfmode & MGCP_DTMF_INBAND || p->dtmfmode & MGCP_DTMF_HYBRID) {
+ ast_log(LOG_DEBUG, "Stopping DTMF using inband/hybrid\n");
+ res = -1; /* Tell Asterisk to stop inband indications */
+ } else if (p->dtmfmode & MGCP_DTMF_RFC2833) {
+ ast_log(LOG_DEBUG, "Stopping DTMF using RFC2833\n");
+ tmp[0] = 'D';
+ tmp[1] = '/';
+ tmp[2] = digit;
+ tmp[3] = '\0';
+ transmit_notify_request(sub, tmp);
+ ast_rtp_senddigit_end(sub->rtp, digit);
+ } else {
+ ast_log(LOG_ERROR, "Don't know about DTMF_MODE %d\n", p->dtmfmode);
+ }
ast_mutex_unlock(&sub->lock);
- return -1; /* Return non-zero so that Asterisk will stop the inband indications */
+
+ return res;
}
/*!
@@ -2209,7 +2237,7 @@
add_header(&resp, "R", "L/hd(N)");
break;
case MGCP_OFFHOOK:
- add_header(&resp, "R", (sub->rtp && (p->dtmfmode & MGCP_DTMF_INBAND)) ? "L/hu(N),L/hf(N)" : "L/hu(N),L/hf(N),D/[0-9#*](N)");
+ add_header_offhook(sub, &resp);
break;
}
if (!ast_strlen_zero(tone)) {
@@ -2251,7 +2279,7 @@
add_header(&resp, "R", "L/hd(N)");
break;
case MGCP_OFFHOOK:
- add_header(&resp, "R", (sub->rtp && (p->dtmfmode & MGCP_DTMF_INBAND)) ? "L/hu(N),L/hf(N)" : "L/hu(N),L/hf(N),D/[0-9#*](N)");
+ add_header_offhook(sub, &resp);
break;
}
if (!ast_strlen_zero(tone2)) {
@@ -2292,7 +2320,7 @@
add_header(&resp, "R", "L/hd(N)");
break;
case MGCP_OFFHOOK:
- add_header(&resp, "R", (sub->rtp && (p->dtmfmode & MGCP_DTMF_INBAND)) ? "L/hu(N), L/hf(N)" : "L/hu(N),L/hf(N),D/[0-9#*](N)");
+ add_header_offhook(sub, &resp);
break;
}
/* fill in new fields */
@@ -2301,6 +2329,16 @@
[... 1788 lines stripped ...]
More information about the asterisk-commits
mailing list