Merged revisions 58474 via svnmerge from
authorRussell Bryant <russell@russellbryant.com>
Thu, 8 Mar 2007 20:56:57 +0000 (20:56 +0000)
committerRussell Bryant <russell@russellbryant.com>
Thu, 8 Mar 2007 20:56:57 +0000 (20:56 +0000)
https://origsvn.digium.com/svn/asterisk/branches/1.4

........
r58474 | russell | 2007-03-08 14:54:56 -0600 (Thu, 08 Mar 2007) | 3 lines

Refactor hold handling a bit so that it does not require keeping the call up
when a call is put on hold.

........

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@58475 65c4cc65-6c06-0410-ace0-fbb531ad65f3

apps/app_meetme.c

index 5b77321..313d7ab 100644 (file)
@@ -65,6 +65,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/astobj.h"
 #include "asterisk/devicestate.h"
 #include "asterisk/dial.h"
+#include "asterisk/causes.h"
 
 #include "enter.h"
 #include "leave.h"
@@ -360,6 +361,7 @@ enum sla_trunk_state {
        SLA_TRUNK_STATE_RINGING,
        SLA_TRUNK_STATE_UP,
        SLA_TRUNK_STATE_ONHOLD,
+       SLA_TRUNK_STATE_ONHOLD_BYME,
 };
 
 enum sla_hold_access {
@@ -448,8 +450,6 @@ static const char sla_registrar[] = "SLA";
 enum sla_event_type {
        /*! A station has put the call on hold */
        SLA_EVENT_HOLD,
-       /*! A station has taken the call off of hold */
-       SLA_EVENT_UNHOLD,
        /*! The state of a dial has changed */
        SLA_EVENT_DIAL_STATE,
        /*! The state of a ringing trunk has changed */
@@ -1062,6 +1062,7 @@ static const char *trunkstate2str(enum sla_trunk_state state)
        S(SLA_TRUNK_STATE_RINGING)
        S(SLA_TRUNK_STATE_UP)
        S(SLA_TRUNK_STATE_ONHOLD)
+       S(SLA_TRUNK_STATE_ONHOLD_BYME)
        }
        return "Uknown State";
 #undef S
@@ -1271,7 +1272,7 @@ static void sla_queue_event(enum sla_event_type type)
 }
 
 /*! \brief Queue a SLA event from the conference */
-static void sla_queue_event_conf(enum sla_event_type type, const struct ast_channel *chan,
+static void sla_queue_event_conf(enum sla_event_type type, struct ast_channel *chan,
        struct ast_conference *conf)
 {
        struct sla_station *station;
@@ -1301,6 +1302,9 @@ static void sla_queue_event_conf(enum sla_event_type type, const struct ast_chan
                return;
        }
 
+       ast_softhangup(chan, AST_CAUSE_NORMAL);
+       trunk_ref->chan = NULL;
+
        sla_queue_event_full(type, trunk_ref, station, 1);
 }
 
@@ -2101,8 +2105,6 @@ static int conf_run(struct ast_channel *chan, struct ast_conference *conf, int c
                                        case AST_CONTROL_HOLD:
                                                sla_queue_event_conf(SLA_EVENT_HOLD, chan, conf);
                                                break;
-                                       case AST_CONTROL_UNHOLD:
-                                               sla_queue_event_conf(SLA_EVENT_UNHOLD, chan, conf);
                                        default:
                                                break;
                                        }
@@ -3104,7 +3106,8 @@ static struct sla_station *sla_find_station(const char *name)
        return station;
 }
 
-static int sla_check_station_hold_access(const struct sla_trunk *trunk)
+static int sla_check_station_hold_access(const struct sla_trunk *trunk,
+       const struct sla_station *station)
 {
        struct sla_station_ref *station_ref;
        struct sla_trunk_ref *trunk_ref;
@@ -3112,9 +3115,9 @@ static int sla_check_station_hold_access(const struct sla_trunk *trunk)
        /* For each station that has this call on hold, check for private hold. */
        AST_LIST_TRAVERSE(&trunk->stations, station_ref, entry) {
                AST_LIST_TRAVERSE(&station_ref->station->trunks, trunk_ref, entry) {
-                       if (trunk_ref->trunk != trunk)
+                       if (trunk_ref->trunk != trunk || station_ref->station == station)
                                continue;
-                       if (trunk_ref->state == SLA_TRUNK_STATE_ONHOLD && trunk_ref->chan &&
+                       if (trunk_ref->state == SLA_TRUNK_STATE_ONHOLD_BYME &&
                                station_ref->station->hold_access == SLA_HOLD_PRIVATE)
                                return 1;
                        return 0;
@@ -3143,8 +3146,9 @@ static struct sla_trunk_ref *sla_find_trunk_ref_byname(const struct sla_station
                if ( (trunk_ref->trunk->barge_disabled 
                        && trunk_ref->state != SLA_TRUNK_STATE_IDLE) ||
                        (trunk_ref->trunk->hold_stations 
-                       && trunk_ref->trunk->hold_access == SLA_HOLD_PRIVATE) ||
-                       sla_check_station_hold_access(trunk_ref->trunk) )
+                       && trunk_ref->trunk->hold_access == SLA_HOLD_PRIVATE
+                       && trunk_ref->state != SLA_TRUNK_STATE_ONHOLD_BYME) ||
+                       sla_check_station_hold_access(trunk_ref->trunk, station) )
                        trunk_ref = NULL;
 
                break;
@@ -3179,14 +3183,15 @@ static struct sla_ringing_station *sla_create_ringing_station(struct sla_station
 }
 
 static void sla_change_trunk_state(const struct sla_trunk *trunk, enum sla_trunk_state state, 
-       enum sla_which_trunk_refs inactive_only)
+       enum sla_which_trunk_refs inactive_only, const struct sla_trunk_ref *exclude)
 {
        struct sla_station *station;
        struct sla_trunk_ref *trunk_ref;
 
        AST_LIST_TRAVERSE(&sla_stations, station, entry) {
                AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) {
-                       if (trunk_ref->trunk != trunk || (inactive_only ? trunk_ref->chan : 0))
+                       if (trunk_ref->trunk != trunk || (inactive_only ? trunk_ref->chan : 0)
+                               || trunk_ref == exclude)
                                continue;
                        trunk_ref->state = state;
                        ast_device_state_changed("SLA:%s_%s", station->name, trunk->name);
@@ -3232,10 +3237,11 @@ static void *run_station(void *data)
                conf = NULL;
        }
        trunk_ref->chan = NULL;
-       if (ast_atomic_dec_and_test((int *) &trunk_ref->trunk->active_stations)) {
+       if (ast_atomic_dec_and_test((int *) &trunk_ref->trunk->active_stations) &&
+               !trunk_ref->trunk->hold_stations) {
                strncat(conf_name, "|K", sizeof(conf_name) - strlen(conf_name) - 1);
                admin_exec(NULL, conf_name);
-               sla_change_trunk_state(trunk_ref->trunk, SLA_TRUNK_STATE_IDLE, ALL_TRUNK_REFS);
+               sla_change_trunk_state(trunk_ref->trunk, SLA_TRUNK_STATE_IDLE, ALL_TRUNK_REFS, NULL);
        }
 
        ast_dial_join(station->dial);
@@ -3252,7 +3258,7 @@ static void sla_stop_ringing_trunk(struct sla_ringing_trunk *ringing_trunk)
 
        snprintf(buf, sizeof(buf), "SLA_%s|K", ringing_trunk->trunk->name);
        admin_exec(NULL, buf);
-       sla_change_trunk_state(ringing_trunk->trunk, SLA_TRUNK_STATE_IDLE, ALL_TRUNK_REFS);
+       sla_change_trunk_state(ringing_trunk->trunk, SLA_TRUNK_STATE_IDLE, ALL_TRUNK_REFS, NULL);
 
        while ((station_ref = AST_LIST_REMOVE_HEAD(&ringing_trunk->timed_out_stations, entry)))
                free(station_ref);
@@ -3396,7 +3402,7 @@ static void sla_handle_dial_state_event(void)
                        s_trunk_ref->chan = ast_dial_answered(ringing_station->station->dial);
                        /* Actually answer the trunk */
                        ast_answer(ringing_trunk->trunk->chan);
-                       sla_change_trunk_state(ringing_trunk->trunk, SLA_TRUNK_STATE_UP, ALL_TRUNK_REFS);
+                       sla_change_trunk_state(ringing_trunk->trunk, SLA_TRUNK_STATE_UP, ALL_TRUNK_REFS, NULL);
                        /* Now, start a thread that will connect this station to the trunk.  The rest of
                         * the code here sets up the thread and ensures that it is able to save the arguments
                         * before they are no longer valid since they are allocated on the stack. */
@@ -3663,21 +3669,11 @@ static void sla_handle_ringing_trunk_event(void)
 static void sla_handle_hold_event(struct sla_event *event)
 {
        ast_atomic_fetchadd_int((int *) &event->trunk_ref->trunk->hold_stations, 1);
-       event->trunk_ref->state = SLA_TRUNK_STATE_ONHOLD;
+       event->trunk_ref->state = SLA_TRUNK_STATE_ONHOLD_BYME;
        ast_device_state_changed("SLA:%s_%s", 
                event->station->name, event->trunk_ref->trunk->name);
-       sla_change_trunk_state(event->trunk_ref->trunk, SLA_TRUNK_STATE_ONHOLD, INACTIVE_TRUNK_REFS);   
-}
-
-static void sla_handle_unhold_event(struct sla_event *event)
-{
-       if (ast_atomic_dec_and_test((int *) &event->trunk_ref->trunk->hold_stations) == 1)
-               sla_change_trunk_state(event->trunk_ref->trunk, SLA_TRUNK_STATE_UP, ALL_TRUNK_REFS);
-       else {
-               event->trunk_ref->state = SLA_TRUNK_STATE_UP;
-               ast_device_state_changed("SLA:%s_%s",
-                       event->station->name, event->trunk_ref->trunk->name);
-       }
+       sla_change_trunk_state(event->trunk_ref->trunk, SLA_TRUNK_STATE_ONHOLD, 
+               INACTIVE_TRUNK_REFS, event->trunk_ref);
 }
 
 /*! \brief Process trunk ring timeouts
@@ -3902,9 +3898,6 @@ static void *sla_thread(void *data)
                        case SLA_EVENT_HOLD:
                                sla_handle_hold_event(event);
                                break;
-                       case SLA_EVENT_UNHOLD:
-                               sla_handle_unhold_event(event);                         
-                               break;
                        case SLA_EVENT_DIAL_STATE:
                                sla_handle_dial_state_event();
                                break;
@@ -4076,9 +4069,9 @@ static int sla_station_exec(struct ast_channel *chan, void *data)
        }
 
        AST_RWLIST_RDLOCK(&sla_trunks);
-       if (!ast_strlen_zero(trunk_name))
+       if (!ast_strlen_zero(trunk_name)) {
                trunk_ref = sla_find_trunk_ref_byname(station, trunk_name);
-       else
+       } else
                trunk_ref = sla_choose_idle_trunk(station);
        AST_RWLIST_UNLOCK(&sla_trunks);
 
@@ -4093,6 +4086,15 @@ static int sla_station_exec(struct ast_channel *chan, void *data)
                return 0;
        }
 
+       if (trunk_ref->state == SLA_TRUNK_STATE_ONHOLD_BYME) {
+               if (ast_atomic_dec_and_test((int *) &trunk_ref->trunk->hold_stations) == 1)
+                       sla_change_trunk_state(trunk_ref->trunk, SLA_TRUNK_STATE_UP, ALL_TRUNK_REFS, NULL);
+               else {
+                       trunk_ref->state = SLA_TRUNK_STATE_UP;
+                       ast_device_state_changed("SLA:%s_%s", station->name, trunk_ref->trunk->name);
+               }
+       }
+
        trunk_ref->chan = chan;
 
        if (!trunk_ref->trunk->chan) {
@@ -4106,7 +4108,7 @@ static int sla_station_exec(struct ast_channel *chan, void *data)
                        .cond_lock = &cond_lock,
                        .cond = &cond,
                };
-               sla_change_trunk_state(trunk_ref->trunk, SLA_TRUNK_STATE_UP, ALL_TRUNK_REFS);
+               sla_change_trunk_state(trunk_ref->trunk, SLA_TRUNK_STATE_UP, ALL_TRUNK_REFS, NULL);
                /* Create a thread to dial the trunk and dump it into the conference.
                 * However, we want to wait until the trunk has been dialed and the
                 * conference is created before continuing on here. */
@@ -4126,7 +4128,7 @@ static int sla_station_exec(struct ast_channel *chan, void *data)
                if (!trunk_ref->trunk->chan) {
                        ast_log(LOG_DEBUG, "Trunk didn't get created. chan: %lx\n", (long) trunk_ref->trunk->chan);
                        pbx_builtin_setvar_helper(chan, "SLASTATION_STATUS", "CONGESTION");
-                       sla_change_trunk_state(trunk_ref->trunk, SLA_TRUNK_STATE_IDLE, ALL_TRUNK_REFS);
+                       sla_change_trunk_state(trunk_ref->trunk, SLA_TRUNK_STATE_IDLE, ALL_TRUNK_REFS, NULL);
                        trunk_ref->chan = NULL;
                        return 0;
                }
@@ -4148,7 +4150,7 @@ static int sla_station_exec(struct ast_channel *chan, void *data)
        if (res == 1) { 
                strncat(conf_name, "|K", sizeof(conf_name) - strlen(conf_name) - 1);
                admin_exec(NULL, conf_name);
-               sla_change_trunk_state(trunk_ref->trunk, SLA_TRUNK_STATE_IDLE, ALL_TRUNK_REFS);
+               sla_change_trunk_state(trunk_ref->trunk, SLA_TRUNK_STATE_IDLE, ALL_TRUNK_REFS, NULL);
        }
        
        pbx_builtin_setvar_helper(chan, "SLASTATION_STATUS", "SUCCESS");
@@ -4178,7 +4180,7 @@ static struct sla_ringing_trunk *queue_ringing_trunk(struct sla_trunk *trunk)
        ringing_trunk->trunk = trunk;
        ringing_trunk->ring_begin = ast_tvnow();
 
-       sla_change_trunk_state(trunk, SLA_TRUNK_STATE_RINGING, 0);
+       sla_change_trunk_state(trunk, SLA_TRUNK_STATE_RINGING, ALL_TRUNK_REFS, NULL);
 
        ast_mutex_lock(&sla.lock);
        AST_LIST_INSERT_HEAD(&sla.ringing_trunks, ringing_trunk, entry);
@@ -4290,6 +4292,7 @@ static enum ast_device_state sla_state(const char *data)
                        res = AST_DEVICE_INUSE;
                        break;
                case SLA_TRUNK_STATE_ONHOLD:
+               case SLA_TRUNK_STATE_ONHOLD_BYME:
                        res = AST_DEVICE_ONHOLD;
                        break;
                }