////////////////////////////////////////////////////////////////////////////////
//
//  Licensed to the Apache Software Foundation (ASF) under one or more
//  contributor license agreements.  See the NOTICE file distributed with
//  this work for additional information regarding copyright ownership.
//  The ASF licenses this file to You under the Apache License, Version 2.0
//  (the "License"); you may not use this file except in compliance with
//  the License.  You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.
//
////////////////////////////////////////////////////////////////////////////////

package mx.messaging
{

import flash.errors.IllegalOperationError;
import flash.events.EventDispatcher;
import flash.events.TimerEvent;
import flash.utils.Dictionary;
import flash.utils.Timer;

import mx.core.mx_internal;
import mx.events.PropertyChangeEvent;
import mx.messaging.channels.NetConnectionChannel;
import mx.messaging.channels.PollingChannel;
import mx.messaging.config.ServerConfig;
import mx.messaging.errors.NoChannelAvailableError;
import mx.messaging.events.ChannelEvent;
import mx.messaging.events.ChannelFaultEvent;
import mx.messaging.events.MessageEvent;
import mx.messaging.events.MessageFaultEvent;
import mx.messaging.messages.AcknowledgeMessage;
import mx.messaging.messages.CommandMessage;
import mx.messaging.messages.ErrorMessage;
import mx.messaging.messages.IMessage;
import mx.resources.IResourceManager;
import mx.resources.ResourceManager;
import mx.rpc.AsyncDispatcher;
import mx.rpc.AsyncToken;
import mx.rpc.events.AbstractEvent;
import mx.rpc.events.FaultEvent;
import mx.rpc.events.ResultEvent;
import mx.utils.Base64Encoder;

use namespace mx_internal;

[DefaultProperty("channels")]

/**
 *  Dispatched after a Channel in the ChannelSet has connected to its endpoint.
 *
 *  @eventType mx.messaging.events.ChannelEvent.CONNECT
 *
 *  @langversion 3.0
 *  @playerversion Flash 9
 *  @playerversion AIR 1.1
 *  @productversion BlazeDS 4
 *  @productversion LCDS 3
 */
[Event(name="channelConnect", type="mx.messaging.events.ChannelEvent")]

/**
 *  Dispatched after a Channel in the ChannelSet has disconnected from its
 *  endpoint.
 *
 *  @eventType mx.messaging.events.ChannelEvent.DISCONNECT
 *
 *  @langversion 3.0
 *  @playerversion Flash 9
 *  @playerversion AIR 1.1
 *  @productversion BlazeDS 4
 *  @productversion LCDS 3
 */
[Event(name="channelDisconnect", type="mx.messaging.events.ChannelEvent")]

/**
 *  Dispatched after a Channel in the ChannelSet has faulted.
 *
 *  @eventType mx.messaging.events.ChannelFaultEvent.FAULT
 *
 *  @langversion 3.0
 *  @playerversion Flash 9
 *  @playerversion AIR 1.1
 *  @productversion BlazeDS 4
 *  @productversion LCDS 3
 */
[Event(name="channelFault", type="mx.messaging.events.ChannelFaultEvent")]

/**
 * The result event is dispatched when a login or logout call successfully returns.
 * @eventType mx.rpc.events.ResultEvent.RESULT
 *
 *  @langversion 3.0
 *  @playerversion Flash 9
 *  @playerversion AIR 1.1
 *  @productversion BlazeDS 4
 *  @productversion LCDS 3
 */
[Event(name="result", type="mx.rpc.events.ResultEvent")]

/**
 * The fault event is dispatched when a login or logout call fails.
 * @eventType mx.rpc.events.FaultEvent.FAULT
 *
 *  @langversion 3.0
 *  @playerversion Flash 9
 *  @playerversion AIR 1.1
 *  @productversion BlazeDS 4
 *  @productversion LCDS 3
 */
[Event(name="fault", type="mx.rpc.events.FaultEvent")]

/**
 *  Dispatched when a property of the ChannelSet changes.
 *
 *  @eventType mx.events.PropertyChangeEvent.PROPERTY_CHANGE
 *
 *  @langversion 3.0
 *  @playerversion Flash 9
 *  @playerversion AIR 1.1
 *  @productversion BlazeDS 4
 *  @productversion LCDS 3
 */
[Event(name="propertyChange", type="mx.events.PropertyChangeEvent")]

[ResourceBundle("messaging")]

/**
 *  The ChannelSet is a set of Channels that are used to send messages to a
 *  target destination. The ChannelSet improves the quality of service on the
 *  client by hunting through its Channels to send messages in the face of
 *  network failures or individual Channel problems.
 *
 *  @langversion 3.0
 *  @playerversion Flash 9
 *  @playerversion AIR 1.1
 *  @productversion BlazeDS 4
 *  @productversion LCDS 3
 */
public class ChannelSet extends EventDispatcher
{
    //--------------------------------------------------------------------------
    //
    // Constructor
    //
    //--------------------------------------------------------------------------

    /**
     *  Constructs a ChannelSet.
     *  If the <code>channelIds</code> argument is provided, the ChannelSet will
     *  use automatically configured Channels obtained via <code>ServerConfig.getChannel()</code>
     *  to reach a destination.
     *  Attempting to manually assign Channels to a ChannelSet that uses configured
     *  Channels is not allowed.
     *
     *  <p>If the <code>channelIds</code> argument is not provided or is null,
     *  Channels must be manually created and added to the ChannelSet in order
     *  to connect and send messages.</p>
     *
     *  <p>If the ChannelSet is clustered using url-load-balancing (where each server
     *  declares a unique RTMP or HTTP URL and the client fails over from one URL to
     *  the next), the first time that a Channel in the ChannelSet successfully connects
     *  the ChannelSet will automatically make a request for all of the endpoints across
     *  the cluster for all member Channels and will assign these failover URLs to each
     *  respective Channel.
     *  This allows Channels in the ChannelSet to failover individually, and when failover
     *  options for a specific Channel are exhausted the ChannelSet will advance to the next
     *  Channel in the set to attempt to reconnect.</p>
     *
     *  <p>Regardless of clustering, if a Channel cannot connect or looses
     *  connectivity, the ChannelSet will advance to its next available Channel
     *  and attempt to reconnect.
     *  This allows the ChannelSet to hunt through Channels that use different
     *  protocols, ports, etc., in search of one that can connect to its endpoint
     *  successfully.</p>
     *
     *  @param channelIds The ids of configured Channels obtained from ServerConfig for this ChannelSet to
     *                    use. If null, Channels must be manually added to the ChannelSet.
     *
     *  @param clusteredWithURLLoadBalancing True if the Channels in the ChannelSet are clustered
     *                   using url load balancing.
     *
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion BlazeDS 4
     *  @productversion LCDS 3
     */
    public function ChannelSet(channelIds:Array = null, clusteredWithURLLoadBalancing:Boolean = false)
    {
        super();
        _clustered = clusteredWithURLLoadBalancing;
        _connected = false;
        _connecting = false;
        _currentChannelIndex = -1;
        if (channelIds != null)
        {
            _channelIds = channelIds;
            _channels = new Array(_channelIds.length);
            _configured = true;
        }
        else
        {
            _channels = [];
            _configured = false;
        }
        _hasRequestedClusterEndpoints = false;
        _hunting = false;
        _messageAgents = [];
        _pendingMessages = new Dictionary();
        _pendingSends = [];
        _shouldBeConnected = false;
        _shouldHunt = true;
    }

    //--------------------------------------------------------------------------
    //
    // Variables
    //
    //--------------------------------------------------------------------------

    /**
     *  @private
     *  Helper MessageAgent used for direct authentication.
     */
    private var _authAgent:AuthenticationAgent;

    /**
     *  @private
     *  Flag indicating whether the ChannelSet is in the process of connecting
     *  over the current Channel.
     */
    private var _connecting:Boolean;

    /**
     *  @private
     *  Stored credentials to be set on the member channels.
     */
    private var _credentials:String;

    /**
     *  @private
     *  The character-set encoding used to create the credentials String.
     */
    private var _credentialsCharset:String;

    /**
     *  @private
     *  Current index into the _channels/_channelIds arrays.
     */
    private var _currentChannelIndex:int;

    /**
     *  @private
     *  This flag restricts our cluster request to only happen upon initial
     *  connect to the cluster.
     */
    private var _hasRequestedClusterEndpoints:Boolean;

    /**
     *  @private
     *  Timer used to issue periodic heartbeats to the remote host if the
     *  client is idle, and not actively sending messages.
     */
    private var _heartbeatTimer:Timer;

    /**
     *  @private
     *  Flag indicating whether the ChannelSet is in the process of hunting to a
     *  new Channel; this lets us control the "reconnecting" flag on
     *  CONNECT ChannelEvents that we dispatch when we hunt to a new
     *  Channel that isn't internally failing over. The new Channel doesn't know we're
     *  in a reconnect attempt when it makes its initial connect attempt so this lets
     *  us set "reconnecting" to true on the CONNECT event if it succeeds.
     */
    private var _hunting:Boolean;

    /**
     *  @private
     *  A dictionary of pending messages used to filter out duplicate
     *  messages passed to the ChannelSet to send while it is not connected.
     *  This allows agents to perform message resend behavior (i.e. Consumer resubscribe
     *  attempts) without worrying about duplicate messages queuing up and being sent to
     *  the server once a connection is established.
     */
    private var _pendingMessages:Dictionary;

    /**
     *  @private
     *  An array of PendingSend instances to pass into send() when a connection
     *  is (re)established.
     */
    private var _pendingSends:Array;

    /**
     *  @private
     *  A timer used to do a delayed reconnect for NetConnection channels.
     */
    private var _reconnectTimer:Timer = null;

    /**
     *  @private
     *  Flag indicating whether the ChannelSet should be connected.
     *  If true, the ChannelSet will attempt to hunt to the next available
     *  Channel when a disconnect or fault occurs. If false, hunting is not
     *  performed.
     */
    private var _shouldBeConnected:Boolean;

    /**
     *  @private
     *  Flag indicating whether a Channel disconnect/fault should trigger hunting or not;
     *  used when connected Channels are removed from the ChannelSet which should not trigger
     *  hunting.
     */
    private var _shouldHunt:Boolean;

    /**
     *  @private
     */
    private var resourceManager:IResourceManager =
                                    ResourceManager.getInstance();

    //--------------------------------------------------------------------------
    //
    // Properties
    //
    //--------------------------------------------------------------------------

    //----------------------------------
    //  authenticated
    //----------------------------------

    /**
     *  @private
     */
    private var _authenticated:Boolean;

    [Bindable(event="propertyChange")]
    /**
     *  Indicates whether the ChannelSet has an underlying Channel that successfully
     *  authenticated with its endpoint.
     *
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion BlazeDS 4
     *  @productversion LCDS 3
     */
    public function get authenticated():Boolean
    {
        return _authenticated;
    }

    /**
     *  @private
     */
    mx_internal function setAuthenticated(value:Boolean, creds:String, notifyAgents:Boolean=true):void
    {
        if (_authenticated != value)
        {
            var event:PropertyChangeEvent = PropertyChangeEvent.createUpdateEvent(this, "authenticated", _authenticated, value);
            _authenticated = value;

            if (notifyAgents)
            {
                var ma:MessageAgent;
                for (var i:int = 0; i < _messageAgents.length; i++)
                {
                    ma = MessageAgent(_messageAgents[i]);
                    ma.setAuthenticated(value, creds);
                }
            }

            if (!value && _authAgent != null)
                _authAgent.state = AuthenticationAgent.LOGGED_OUT_STATE;

            dispatchEvent(event);
        }
    }

    //----------------------------------
    //  channels
    //----------------------------------

    /**
     *  @private
     */
    private var _channels:Array;

    /**
     *  Provides access to the Channels in the ChannelSet.
     *  This property may be used to assign a set of channels at once or channels
     *  may be added directly to the ChannelSet via addChannel() individually.
     *  If this ChannelSet is <code>configured</code> automatically the individual
     *  channels are created lazily and added to this property as needed.
     *
     *  @throws flash.errors.IllegalOperationError If the ChannelSet is
     *             <code>configured</code>, assigning to this property is not allowed.
     *
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion BlazeDS 4
     *  @productversion LCDS 3
     */
    public function get channels():Array
    {
        return _channels;
    }

    [ArrayElementType("mx.messaging.Channel")]
    /**
     *  @private
     */
    public function set channels(values:Array):void
    {
        if (configured)
        {
            var message:String = resourceManager.getString(
                "messaging", "cannotAddWhenConfigured");
            throw new IllegalOperationError(message);
        }

        // Remove existing channels
        var channelsToRemove:Array = _channels.slice();
        var n:int = channelsToRemove.length;
        for (var i:int = 0; i < n; i++)
        {
            removeChannel(channelsToRemove[i]);
        }

        // Add new channels
        if (values != null && values.length > 0)
        {
            var m:int = values.length;
            for (var j:int = 0; j < m; j++)
            {
                addChannel(values[j]);
            }
        }
    }

    //----------------------------------
    //  channelIds
    //----------------------------------

    /**
     *  @private
     */
    private var _channelIds:Array;

    /**
     *  The ids of the Channels used by the ChannelSet.
     *
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion BlazeDS 4
     *  @productversion LCDS 3
     */
    public function get channelIds():Array
    {
        if (_channelIds != null)
        {
            return _channelIds;
        }
        else
        {
            var ids:Array = [];
            var n:int = _channels.length;
            for (var i:int = 0; i < n; i++)
            {
                if (_channels[i] != null)
                    ids.push(_channels[i].id);
                else
                    ids.push(null);
            }
            return ids;
        }
    }

    //----------------------------------
    //  currentChannel
    //----------------------------------

    /**
     *  @private
     */
    private var _currentChannel:Channel;

    /**
     *  Returns the current Channel for the ChannelSet.
     *
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion BlazeDS 4
     *  @productversion LCDS 3
     */
    public function get currentChannel():Channel
    {
        return _currentChannel;
    }

    //----------------------------------
    //  channelFailoverURIs
    //----------------------------------

    /**
     *  @private
     */
    private var _channelFailoverURIs:Object;

    /**
     *  @private
     *  Map of arrays of failoverURIs keyed by channel id for the Channels in this ChannelSet.
     *  This property is assigned to by the ClusterMessageResponder in order to update the
     *  member Channels with their failoverURIs.
     */
    mx_internal function get channelFailoverURIs():Object
    {
        return _channelFailoverURIs;
    }

    /**
     *  @private
     */
    mx_internal function set channelFailoverURIs(value:Object):void
    {
        _channelFailoverURIs = value;
        // Update any existing Channels in the set with their current failover endpoint URIs.
        var n:int = _channels.length;
        for (var i:int = 0; i < n; i++)
        {
            var channel:Channel = _channels[i];
            if (channel == null)
            {
                break; // The rest of the Channels have not been loaded yet.
            }
            else if (_channelFailoverURIs[channel.id] != null)
            {
                channel.failoverURIs = _channelFailoverURIs[channel.id];
            }
        }
    }

    //----------------------------------
    //  configured
    //----------------------------------

    /**
     *  @private
     */
    private var _configured:Boolean;

    /**
     *  Indicates whether the ChannelSet is using automatically configured
     *  Channels or manually assigned Channels.
     *
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion BlazeDS 4
     *  @productversion LCDS 3
     */
    mx_internal function get configured():Boolean
    {
        return _configured;
    }

    //----------------------------------
    //  connected
    //----------------------------------

    /**
     *  @private
     */
    private var _connected:Boolean;

    [Bindable(event="propertyChange")]
    /**
     *  Indicates whether the ChannelSet is connected.
     */
    public function get connected():Boolean
    {
        return _connected;
    }

    /**
     *  @private
     */
    protected function setConnected(value:Boolean):void
    {
        if (_connected != value)
        {
            var event:PropertyChangeEvent = PropertyChangeEvent.createUpdateEvent(this, "connected", _connected, value)
            _connected = value;
            dispatchEvent(event);
            setAuthenticated(value && currentChannel && currentChannel.authenticated, _credentials, false /* Agents also listen for channel disconnects */);
            if (!connected)
            {
                unscheduleHeartbeat();
            }
            else if (heartbeatInterval > 0)
            {
                scheduleHeartbeat();
            }
        }
    }

    //----------------------------------
    //  clustered
    //----------------------------------

    /**
     *  @private
     */
    private var _clustered:Boolean;

    /**
     *  Indicates whether the ChannelSet targets a clustered destination.
     *  If true, upon a successful connection the ChannelSet will query the
     *  destination for all clustered endpoints for its Channels and will assign
     *  failoverURIs to them.
     *  Channel ids are used to assign failoverURIs to the proper Channel instances
     *  so this requires that all Channels in the ChannelSet have non-null ids and an
     *  Error will be thrown when this property is set to true if this is not the case.
     *  If the ChannelSet is not using url load balancing on the client this
     *  property should not be set to true.
     *
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion BlazeDS 4
     *  @productversion LCDS 3
     */
    public function get clustered():Boolean
    {
        return _clustered;
    }

    /**
     *  @private
     */
    public function set clustered(value:Boolean):void
    {
        if (_clustered != value)
        {
            if (value)
            {
                // Cannot have a clustered ChannelSet that contains Channels with null ids.
                var ids:Array = channelIds;
                var n:int = ids.length;
                for (var i:int = 0; i < n; i++)
                {
                    if (ids[i] == null)
                    {
                        var message:String = resourceManager.getString(
                            "messaging", "cannotSetClusteredWithdNullChannelIds");
                        throw new IllegalOperationError(message);
                    }
                }
            }
            _clustered = value;
        }
    }

    //----------------------------------
    //  heartbeatInterval
    //----------------------------------

    /**
     *  @private
     */
    private var _heartbeatInterval:int = 0;

    /**
     *  The number of milliseconds between heartbeats sent to the remote
     *  host while this ChannelSet is actively connected but idle.
     *  Any outbound message traffic will delay heartbeats temporarily, with
     *  this number of milliseconds elapsing after the last sent message before
     *  the next heartbeat is issued.
     *  <p>
     *  This property is useful for applications that connect to a remote host
     *  to received pushed updates and are not actively sending any messages, but
     *  still wish to be notified of a dropped connection even when the networking
     *  layer fails to provide such notification directly. By issuing periodic
     *  heartbeats the client can force the networking layer to report a timeout
     *  if the underlying connection has dropped without notification and the
     *  application can respond to the disconnect appropriately.
     *  </p>
     *  <p>
     *  Any non-positive value disables heartbeats to the remote host.
     *  The default value is 0 indicating that heartbeats are disabled.
     *  If the application sets this value it should prefer a longer rather than
     *  shorter interval, to avoid placing unnecessary load on the remote host.
     *  As an illustrative example, low-level TCP socket keep-alives generally
     *  default to an interval of 2 hours. That is a longer interval than most
     *  applications that enable heartbeats will likely want to use, but it
     *  serves as a clear precedent to prefer a longer interval over a shorter
     *  interval.
     *  </p>
     *  <p>
     *  If the currently connected underlying Channel issues poll requests to
     *  the remote host, heartbeats are suppressed because the periodic poll
     *  requests effectively take their place.</p>
     */
    public function get heartbeatInterval():int
    {
        return _heartbeatInterval;
    }

    /**
     *  @private
     */
    public function set heartbeatInterval(value:int):void
    {
        if (_heartbeatInterval != value)
        {
            var event:PropertyChangeEvent = PropertyChangeEvent.createUpdateEvent(this, "heartbeatInterval", _heartbeatInterval, value);
            _heartbeatInterval = value;
            dispatchEvent(event);
            if (_heartbeatInterval > 0 && connected)
            {
                scheduleHeartbeat();
            }
        }
    }

    //----------------------------------
    //  initialDestinationId
    //----------------------------------

    /**
     *  @private
     */
    private var _initialDestinationId:String;

    /**
     *  Provides access to the initial destination this ChannelSet is used to access.
     *  When the clustered property is true, this value is used to request available failover URIs
     *  for the configured channels for the destination.
     *
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion BlazeDS 4
     *  @productversion LCDS 3
     */
    public function get initialDestinationId():String
    {
        return _initialDestinationId;
    }

    /**
     *  @private
     */
    public function set initialDestinationId(value:String):void
    {
        _initialDestinationId = value;
    }

    //----------------------------------
    //  messageAgents
    //----------------------------------

    /**
     *  @private
     */
    private var _messageAgents:Array;

    /**
     *  Provides access to the set of MessageAgents that use this ChannelSet.
     *
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion BlazeDS 4
     *  @productversion LCDS 3
     */
    public function get messageAgents():Array
    {
        return _messageAgents;
    }

    //--------------------------------------------------------------------------
    //
    // Overridden Methods
    //
    //--------------------------------------------------------------------------

    /**
     *  Returns a String containing the ids of the Channels in the ChannelSet.
     *
     *  @return String representation of the ChannelSet.
     *
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion BlazeDS 4
     *  @productversion LCDS 3
     */
    override public function toString():String
    {
        var s:String = "[ChannelSet ";
        for (var i:uint = 0; i < _channels.length; i++)
        {
            if (_channels[i] != null)
                s += _channels[i].id + " ";
        }
        s += "]";
        return s;
    }

    //--------------------------------------------------------------------------
    //
    // Methods
    //
    //--------------------------------------------------------------------------

    /**
     *  Adds a Channel to the ChannelSet. A Channel with a null id cannot be added
     *  to the ChannelSet if the ChannelSet targets a clustered destination.
     *
     *  @param channel The Channel to add.
     *
     *  @throws flash.errors.IllegalOperationError If the ChannelSet is
     *             <code>configured</code>, adding a Channel is not supported.
     *             This error is also thrown if the ChannelSet's <code>clustered</code> property
     *             is <code>true</code> but the Channel has a null id.
     *
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion BlazeDS 4
     *  @productversion LCDS 3
     */
    public function addChannel(channel:Channel):void
    {
        if (channel == null)
            return;

        var message:String;

        if (configured)
        {
            message = resourceManager.getString(
                "messaging", "cannotAddWhenConfigured");
            throw new IllegalOperationError(message);
        }

        if (clustered && channel.id == null)
        {
            message = resourceManager.getString(
                "messaging", "cannotAddNullIdChannelWhenClustered");
            throw new IllegalOperationError(message);
        }

        if (_channels.indexOf(channel) != -1)
            return; // Channel already exists in the set.

        _channels.push(channel);
        if (_credentials)
            channel.setCredentials(_credentials, null, _credentialsCharset);
    }

    /**
     *  Removes a Channel from the ChannelSet. If the Channel to remove is
     *  currently connected and being used by the ChannelSet, it is
     *  disconnected as well as removed.
     *
     *  @param channel The Channel to remove.
     *
     *  @throws flash.errors.IllegalOperationError If the ChannelSet is
     *             <code>configured</code>, removing a Channel is not supported.
     *
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion BlazeDS 4
     *  @productversion LCDS 3
     */
    public function removeChannel(channel:Channel):void
    {
        if (configured)
        {
            var message:String = resourceManager.getString(
                "messaging", "cannotRemoveWhenConfigured");
            throw new IllegalOperationError(message);
        }

        var channelIndex:int = _channels.indexOf(channel);
        if (channelIndex > -1)
        {
            _channels.splice(channelIndex, 1);
            // If the Channel being removed is currently in use, we need
            // to null it out for re-hunting, and potentially disconnect it.
            if ((_currentChannel != null) && (_currentChannel == channel))
            {
                if (connected)
                {
                    _shouldHunt = false;
                    disconnectChannel();
                }
                _currentChannel = null;
                _currentChannelIndex = -1;
            }
        }
    }

    /**
     *  Connects a MessageAgent to the ChannelSet. Once connected, the agent
     *  can use the ChannelSet to send messages.
     *
     *  @param agent The MessageAgent to connect.
     *
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion BlazeDS 4
     *  @productversion LCDS 3
     */
    public function connect(agent:MessageAgent):void
    {
        if ((agent != null) && (_messageAgents.indexOf(agent) == -1))
        {
            _shouldBeConnected = true;
            _messageAgents.push(agent);
            agent.internalSetChannelSet(this);
            // Wire up agent's channel event listeners to this ChannelSet.
            addEventListener(ChannelEvent.CONNECT, agent.channelConnectHandler);
            addEventListener(ChannelEvent.DISCONNECT, agent.channelDisconnectHandler);
            addEventListener(ChannelFaultEvent.FAULT, agent.channelFaultHandler);

            // If the ChannelSet is already connected, notify the agent.
            if (connected && !agent.needsConfig)
                agent.channelConnectHandler(ChannelEvent.createEvent(ChannelEvent.CONNECT,
                                                                     _currentChannel,
                                                                     false,
                                                                     false,
                                                                     connected));
        }
    }

    /**
     *  Disconnects a specific MessageAgent from the ChannelSet. If this is the
     *  last MessageAgent using the ChannelSet and the current Channel in the set is
     *  connected, the Channel will physically disconnect from the server.
     *
     *  @param agent The MessageAgent to disconnect.
     *
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion BlazeDS 4
     *  @productversion LCDS 3
     */
    public function disconnect(agent:MessageAgent):void
    {
        if (agent == null) // Disconnect the ChannelSet completely.
        {
            var allMessageAgents:Array = _messageAgents.slice();
            var n:int = allMessageAgents.length;
            for (var i:int = 0; i < n; i++)
            {
                allMessageAgents[i].disconnect();
            }
            if (_authAgent != null)
            {
                _authAgent.state = AuthenticationAgent.SHUTDOWN_STATE;
                _authAgent = null;
            }
        }
        else // Disconnect a specific MessageAgent.
        {
            var agentIndex:int = agent != null ? _messageAgents.indexOf(agent) : -1;
            if (agentIndex != -1)
            {
                _messageAgents.splice(agentIndex, 1);
                // Remove the agent as a listener to this ChannelSet.
                removeEventListener(ChannelEvent.CONNECT, agent.channelConnectHandler);
                removeEventListener(ChannelEvent.DISCONNECT, agent.channelDisconnectHandler);
                removeEventListener(ChannelFaultEvent.FAULT, agent.channelFaultHandler);

                if (connected || _connecting) // Notify the agent of the disconnect.
                {
                    agent.channelDisconnectHandler(ChannelEvent.createEvent(ChannelEvent.DISCONNECT,
                                                                            _currentChannel, false));
                }
                else // Remove any pending sends for this agent.
                {
                    var n2:int = _pendingSends.length;
                    for (var j:int = 0; j < n2; j++)
                    {
                        var ps:PendingSend = PendingSend(_pendingSends[j]);
                        if (ps.agent == agent)
                        {
                            _pendingSends.splice(j, 1);
                            j--;
                            n2--;
                            delete _pendingMessages[ps.message];
                        }
                    }
                }
                // Shut down the underlying Channel connection if this ChannelSet has
                // no more agents using it.
                if (_messageAgents.length == 0)
                {
                    _shouldBeConnected = false;
                    _currentChannelIndex = -1;
                    if (connected)
                        disconnectChannel();
                }

                // Null out automatically assigned ChannelSet on agent; if manually assigned leave it alone.
                if (agent.channelSetMode == MessageAgent.AUTO_CONFIGURED_CHANNELSET)
                    agent.internalSetChannelSet(null);
            }
        }
    }

    /**
     *  Disconnects all associated MessageAgents and disconnects any underlying Channel that
     *  is connected.
     *  Unlike <code>disconnect(MessageAgent)</code> which is invoked by the disconnect implementations
     *  of specific service components, this method provides a single, convenient point to shut down
     *  connectivity between the client and server.
     *
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion BlazeDS 4
     *  @productversion LCDS 3
     */
    public function disconnectAll():void
    {
        disconnect(null);
    }

    /**
     *  Handles a CONNECT ChannelEvent and redispatches the event.
     *
     *  @param event The ChannelEvent.
     *
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion BlazeDS 4
     *  @productversion LCDS 3
     */
    public function channelConnectHandler(event:ChannelEvent):void
    {
        _connecting = false;
        _connected = true; // Set internally to allow us to send pending messages before dispatching the connect event.
        _currentChannelIndex = -1; // Reset index so that future disconnects are followed by hunting through all available options in order.

        // Send any pending messages.
        while (_pendingSends.length > 0)
        {
            var ps:PendingSend = PendingSend(_pendingSends.shift());
            delete _pendingMessages[ps.message];

            var command:CommandMessage = ps.message as CommandMessage;
            if (command != null)
            {
                // Filter out any commands to trigger connection establishment, and ack them locally.
                if (command.operation == CommandMessage.TRIGGER_CONNECT_OPERATION)
                {
                    var ack:AcknowledgeMessage = new AcknowledgeMessage();
                    ack.clientId = ps.agent.clientId;
                    ack.correlationId = command.messageId;
                    ps.agent.acknowledge(ack, command);
                    continue;
                }

                if (!ps.agent.configRequested && ps.agent.needsConfig &&
                    (command.operation == CommandMessage.CLIENT_PING_OPERATION))
                {
                    command.headers[CommandMessage.NEEDS_CONFIG_HEADER] = true;
                    ps.agent.configRequested = true;
                }
            }

            send(ps.agent, ps.message);
        }

        if (_hunting)
        {
            event.reconnecting = true;
            _hunting = false;
        }

        // Redispatch Channel connect event.
        dispatchEvent(event);
        // Dispatch delayed "connected" property change event.
        var connectedChangeEvent:PropertyChangeEvent = PropertyChangeEvent.createUpdateEvent(this, "connected", false, true)
        dispatchEvent(connectedChangeEvent);
    }

    /**
     *  Handles a DISCONNECT ChannelEvent and redispatches the event.
     *
     *  @param event The ChannelEvent.
     *
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion BlazeDS 4
     *  @productversion LCDS 3
     */
    public function channelDisconnectHandler(event:ChannelEvent):void
    {
        _connecting = false;
        setConnected(false);

        // If we should be connected and the Channel isn't failing over
        // internally and wasn't rejected, hunt and try to reconnect.
        if (_shouldBeConnected && !event.reconnecting && !event.rejected)
        {
            if (_shouldHunt && hunt())
            {
                event.reconnecting = true;
                dispatchEvent(event);
                if (_currentChannel is NetConnectionChannel)
                {
                    // Insert slight delay for reconnect to allow NetConnection
                    // based channels to shut down and clean up in preparation
                    // for our next connect attempt.
                    if (_reconnectTimer == null)
                    {
                        _reconnectTimer = new Timer(1, 1);
                        _reconnectTimer.addEventListener(TimerEvent.TIMER, reconnectChannel);
                        _reconnectTimer.start();
                    }
                }
                else // No need to wait with other channel types.
                {
                    connectChannel();
                }
            }
            else // No more hunting options; give up and fault pending sends.
            {
                dispatchEvent(event);
                faultPendingSends(event);
            }
        }
        else
        {
            dispatchEvent(event);
            // If the underlying Channel was rejected, fault pending sends.
            if (event.rejected)
                faultPendingSends(event);
        }
        // Flip this back to true in case it was turned off by an explicit Channel removal
        // that triggered the current disconnect event.
        _shouldHunt = true;
    }

    /**
     *  Handles a ChannelFaultEvent and redispatches the event.
     *
     *  @param event The ChannelFaultEvent.
     *
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion BlazeDS 4
     *  @productversion LCDS 3
     */
    public function channelFaultHandler(event:ChannelFaultEvent):void
    {
        if (event.channel.connected)
        {
            dispatchEvent(event);
        }
        else // The channel fault has resulted in disconnecting.
        {
            _connecting = false;
            setConnected(false);

            // If we should be connected and the Channel isn't failing over
            // internally, hunt and try to reconnect.
            if (_shouldBeConnected && !event.reconnecting && !event.rejected)
            {
                if (hunt())
                {
                    event.reconnecting = true;
                    dispatchEvent(event);
                    if (_currentChannel is NetConnectionChannel)
                    {
                        // Insert slight delay for reconnect to allow
                        // NetConnection based channels to shut down and clean
                        // up in preparation for our next connect attempt.
                        if (_reconnectTimer == null)
                        {
                            _reconnectTimer = new Timer(1, 1);
                            _reconnectTimer.addEventListener(TimerEvent.TIMER, reconnectChannel);
                            _reconnectTimer.start();
                        }
                    }
                    else // No need to wait with other channel types.
                    {
                        connectChannel();
                    }
                }
                else // No more hunting options; give up and fault pending sends.
                {
                    dispatchEvent(event);
                    faultPendingSends(event);
                }
            }
            else
            {
                dispatchEvent(event);
                // If the underlying Channel was rejected, fault pending sends.
                if (event.rejected)
                    faultPendingSends(event);
            }
        }
    }

    /**
     *  Authenticates the ChannelSet with the server using the provided credentials.
     *  Unlike other operations on Channels and the ChannelSet, this operation returns an
     *  AsyncToken that client code may add a responder to in order to handle success or
     *  failure directly.
     *  If the ChannelSet is not connected to the server when this method is invoked it will
     *  trigger a connect attempt, and if successful, send the login command to the server.
     *  Only one login or logout operation may be pending at a time and overlapping calls will
     *  generate an IllegalOperationError.
     *  Invoking login when the ChannelSet is already authenticated will generate also generate
     *  an IllegalOperationError.
     *
     *  @param username The username.
     *  @param password The password.
     *  @param charset The character set encoding to use while encoding the
     *  credentials. The default is null, which implies the legacy charset of
     *  ISO-Latin-1. The only other supported charset is &quot;UTF-8&quot;.
     *
     *  @return Returns a token that client code may add a responder to in order to handle
     *  success or failure directly.
     *
     *  @throws flash.errors.IllegalOperationError in two situations; if the ChannelSet is
     *          already authenticated, or if a login or logout operation is currently in progress.
     *
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion BlazeDS 4
     *  @productversion LCDS 3
     */
    public function login(username:String, password:String, charset:String=null):AsyncToken
    {
        if (authenticated)
            throw new IllegalOperationError("ChannelSet is already authenticated.");

        if ((_authAgent != null) && (_authAgent.state != AuthenticationAgent.LOGGED_OUT_STATE))
            throw new IllegalOperationError("ChannelSet is in the process of logging in or logging out.");

        if (charset != Base64Encoder.CHARSET_UTF_8)
            charset = null; // Use legacy charset, ISO-Latin-1.

        var credentials:String = null;
        if (username != null && password != null)
        {
            var rawCredentials:String = username + ":" + password;
            var encoder:Base64Encoder = new Base64Encoder();
            if (charset == Base64Encoder.CHARSET_UTF_8)
                encoder.encodeUTFBytes(rawCredentials);
            else
                encoder.encode(rawCredentials);
            credentials = encoder.drain();
        }

        var msg:CommandMessage = new CommandMessage();
        msg.operation = CommandMessage.LOGIN_OPERATION;
        msg.body = credentials;
        if (charset != null)
            msg.headers[CommandMessage.CREDENTIALS_CHARSET_HEADER] = charset;

        // A non-null, non-empty destination is required to send using an agent.
        // This value is ignored on the server and the message must be handled by an AuthenticationService.
        msg.destination = "auth";

        var token:AsyncToken = new AsyncToken(msg);
        if (_authAgent == null)
            _authAgent = new AuthenticationAgent(this);
        _authAgent.registerToken(token);
        _authAgent.state = AuthenticationAgent.LOGGING_IN_STATE;
        send(_authAgent, msg);
        return token;
    }

    /**
     *  Logs the ChannelSet out from the server. Unlike other operations on Channels
     *  and the ChannelSet, this operation returns an AsyncToken that client code may
     *  add a responder to in order to handle success or failure directly.
     *  If logout is successful any credentials that have been cached for use in
     *  automatic reconnects are cleared for the ChannelSet and its Channels and their
     *  authenticated state is set to false.
     *  If the ChannelSet is not connected to the server when this method is invoked it
     *  will trigger a connect attempt, and if successful, send a logout command to the server.
     *
     *  <p>The MessageAgent argument is present to support legacy logout behavior and client code that
     *  invokes this method should not pass a MessageAgent reference. Just invoke <code>logout()</code>
     *  passing no arguments.</p>
     *
     *  <p>This method is also invoked by service components from their <code>logout()</code>
     *  methods, and these components pass a MessageAgent reference to this method when they logout.
     *  The presence of this argument is the trigger to execute legacy logout behavior that differs
     *  from the new behavior described above.
     *  Legacy behavior only sends a logout request to the server if the client is connected
     *  and authenticated.
     *  If these conditions are not met the legacy behavior for this method is to do nothing other
     *  than clear any credentials that have been cached for use in automatic reconnects.</p>
     *
     *  @param agent Legacy argument. The MessageAgent that is initiating the logout.
     *
     *  @return Returns a token that client code may
     *  add a responder to in order to handle success or failure directly.
     *
     *  @throws flash.errors.IllegalOperationError if a login or logout operation is currently in progress.
     */
    public function logout(agent:MessageAgent=null):AsyncToken
    {
        _credentials = null;
        if (agent == null)
        {
            if ((_authAgent != null) && (_authAgent.state == AuthenticationAgent.LOGGING_OUT_STATE
                                         || _authAgent.state == AuthenticationAgent.LOGGING_IN_STATE))
                throw new IllegalOperationError("ChannelSet is in the process of logging in or logging out.");

            // Clear out current credentials on the client.
            var n:int = _messageAgents.length;
            var i:int = 0;
            for (; i < n; i++)
            {
                _messageAgents[i].internalSetCredentials(null);
            }
            n = _channels.length;
            for (i = 0; i < n; i++)
            {
                if (_channels[i] != null)
                {
                    _channels[i].internalSetCredentials(null);
                    if (_channels[i] is PollingChannel)
                        PollingChannel(_channels[i]).disablePolling();
                }
            }

            var msg:CommandMessage = new CommandMessage();
            msg.operation = CommandMessage.LOGOUT_OPERATION;

            // A non-null, non-empty destination is required to send using an agent.
            // This value is ignored on the server and the message must be handled by an AuthenticationService.
            msg.destination = "auth";

            var token:AsyncToken = new AsyncToken(msg);
            if (_authAgent == null)
                _authAgent = new AuthenticationAgent(this);
            _authAgent.registerToken(token);
            _authAgent.state = AuthenticationAgent.LOGGING_OUT_STATE;
            send(_authAgent, msg);
            return token;
        }
        else // Legacy logout logic.
        {
            var n2:int = _channels.length;
            for (var i2:int = 0; i2 < n2; i2++)
            {
                if (_channels[i2] != null)
                    _channels[i2].logout(agent);
            }
            return null; // Legacy service logout() impls don't expect a token.
        }
    }

    /**
     *  Sends a message from a MessageAgent over the currently connected Channel.
     *
     *  @param agent The MessageAgent sending the message.
     *
     *  @param message The Message to send.
     *
     *  @throws mx.messaging.errors.NoChannelAvailableError If the ChannelSet has no internal
     *                                  Channels to use.
     *
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion BlazeDS 4
     *  @productversion LCDS 3
     */
    public function send(agent:MessageAgent, message:IMessage):void
    {
        if (_currentChannel != null && _currentChannel.connected)
        {
            // Filter out any commands to trigger connection establishment, and
            // ack them locally unless the agent needs config.
            if ((message is CommandMessage && CommandMessage(message).operation == CommandMessage.TRIGGER_CONNECT_OPERATION)
                && !agent.needsConfig)
            {
                var ack:AcknowledgeMessage = new AcknowledgeMessage();
                ack.clientId = agent.clientId;
                ack.correlationId = message.messageId;
                new AsyncDispatcher(agent.acknowledge, [ack, message], 1);
                return;
            }

            // If this ChannelSet targets a clustered destination, request the
            // endpoint URIs for the cluster.
            if (!_hasRequestedClusterEndpoints && clustered)
            {
                var msg:CommandMessage = new CommandMessage();
                // Fetch failover URIs for the correct destination.
                if (agent is AuthenticationAgent)
                {
                    msg.destination = initialDestinationId;
                }
                else
                {
                    msg.destination = agent.destination;
                }
                msg.operation = CommandMessage.CLUSTER_REQUEST_OPERATION;
                _currentChannel.sendInternalMessage(new ClusterMessageResponder(msg, this));
                _hasRequestedClusterEndpoints = true;
            }
            unscheduleHeartbeat();
            _currentChannel.send(agent, message);
            scheduleHeartbeat();
        }
        else
        {
            // Filter out duplicate messages here while waiting for the underlying Channel to connect.
            if (_pendingMessages[message] == null)
            {
                _pendingMessages[message] = true;
                _pendingSends.push(new PendingSend(agent, message));
            }

            if (!_connecting)
            {
                if ((_currentChannel == null) || (_currentChannelIndex == -1))
                    hunt();

                if (_currentChannel is NetConnectionChannel)
                {
                    // Insert a slight delay in case we've hunted to a
                    // NetConnection channel that doesn't allow a reconnect
                    // within the same frame as a disconnect.
                    if (_reconnectTimer == null)
                    {
                        _reconnectTimer = new Timer(1, 1);
                        _reconnectTimer.addEventListener(TimerEvent.TIMER, reconnectChannel);
                        _reconnectTimer.start();
                    }
                }
                else // No need to wait with other channel types.
                {
                    connectChannel();
                }
            }
        }
    }

    /**
     *  Stores the credentials and passes them through to every connected channel.
     *
     *  @param credentials The credentials for the MessageAgent.
     *  @param agent The MessageAgent that is setting the credentials.
     *  @param charset The character set encoding used while encoding the
     *  credentials. The default is null, which implies the legacy encoding of
     *  ISO-Latin-1.
     *
     *  @throws flash.errors.IllegalOperationError in two situations; if credentials
     *  have already been set and an authentication is in progress with the remote
     *  detination, or if authenticated and the credentials specified don't match
     *  the currently authenticated credentials.
     *
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion BlazeDS 4
     *  @productversion LCDS 3
     */
    public function setCredentials(credentials:String, agent:MessageAgent, charset:String=null):void
    {
        _credentials = credentials;
        var n:int = _channels.length;
        for (var i:int = 0; i < n; i++)
        {
            if (_channels[i] != null)
                _channels[i].setCredentials(_credentials, agent, charset);
        }
    }

    //--------------------------------------------------------------------------
    //
    // Internal Methods
    //
    //--------------------------------------------------------------------------

    /**
     *  @private
     *  Handles a successful login or logout operation for the ChannelSet.
     */
    mx_internal function authenticationSuccess(agent:AuthenticationAgent, token:AsyncToken, ackMessage:AcknowledgeMessage):void
    {
        // Reset authentication state depending on whether a login or logout was successful.
        var command:CommandMessage = CommandMessage(token.message);
        var handlingLogin:Boolean = (command.operation == CommandMessage.LOGIN_OPERATION);
        var creds:String = (handlingLogin) ? String(command.body) : null;
        var delay:Number = 0;

        if (handlingLogin)
        {
            // First, sync everything with the current credentials.
            _credentials = creds;
            var n:int = _messageAgents.length;
            var i:int = 0;
            for (; i < n; i++)
            {
                _messageAgents[i].internalSetCredentials(creds);
            }
            n = _channels.length;
            for (i = 0; i < n; i++)
            {
                if (_channels[i] != null)
                    _channels[i].internalSetCredentials(creds);
            }

            agent.state = AuthenticationAgent.LOGGED_IN_STATE;
            // Flip the currently connected channel to authenticated; this percolates
            // back up through the ChannelSet and agent's authenticated properties.
            currentChannel.setAuthenticated(true);
        }
        else // Logout.
        {
            // Shutdown the current logged out agent.
            agent.state = AuthenticationAgent.SHUTDOWN_STATE;
            _authAgent = null;
            // Slight delay is used to make sure the disconnect message makes it
            // to the server before result is dispatched to avoid duplicate session
            // errors. See Watson 2780176 for details.
            delay = 250;
            disconnect(agent);

            // Flip current channel to *not* authenticated; this percolates
            // back up through the ChannelSet and agent's authenticated properties.
            currentChannel.setAuthenticated(false);
        }

        // Notify.
        var resultEvent:ResultEvent = ResultEvent.createEvent(ackMessage.body, token, ackMessage);
        if (delay > 0)
            new AsyncDispatcher(dispatchRPCEvent, [resultEvent], delay);
        else
            dispatchRPCEvent(resultEvent);
    }

    /**
     *  @private
     *  Handles a failed login or logout operation for the ChannelSet.
     */
    mx_internal function authenticationFailure(agent:AuthenticationAgent, token:AsyncToken, faultMessage:ErrorMessage):void
    {
        var messageFaultEvent:MessageFaultEvent = MessageFaultEvent.createEvent(faultMessage);
        var faultEvent:FaultEvent = FaultEvent.createEventFromMessageFault(messageFaultEvent, token);
        // Leave the ChannelSet in its current auth state and dispose of the auth agent that failed.
        agent.state = AuthenticationAgent.SHUTDOWN_STATE;
        _authAgent = null;
        disconnect(agent);
        // And notify.
        dispatchRPCEvent(faultEvent);
    }

    //--------------------------------------------------------------------------
    //
    // Protected Methods
    //
    //--------------------------------------------------------------------------

    /**
     *  @private
     *  Helper method to fault pending messages.
     *  The ErrorMessage is tagged with a __retryable__ header to indicate that
     *  the error was due to connectivity problems on the client as opposed to
     *  a server error response and the message can be retried (resent).
     *
     *  @param event A ChannelEvent.DISCONNECT or a ChannelFaultEvent that is the root cause
     *               for faulting these pending sends.
     */
    protected function faultPendingSends(event:ChannelEvent):void
    {
        while (_pendingSends.length > 0)
        {
            var ps:PendingSend = _pendingSends.shift() as PendingSend;
            var pendingMsg:IMessage = ps.message;
            delete _pendingMessages[pendingMsg];
            // Fault the message to its agent.
            var errorMsg:ErrorMessage = new ErrorMessage();
            errorMsg.correlationId = pendingMsg.messageId;
            errorMsg.headers[ErrorMessage.RETRYABLE_HINT_HEADER] = true;
            errorMsg.faultCode = "Client.Error.MessageSend";
            errorMsg.faultString = resourceManager.getString(
                "messaging", "sendFailed");
            if (event is ChannelFaultEvent)
            {
                var faultEvent:ChannelFaultEvent = event as ChannelFaultEvent;
                errorMsg.faultDetail = faultEvent.faultCode + " " +
                                   faultEvent.faultString + " " +
                                   faultEvent.faultDetail;
                // This is to make streaming channels report authentication fault
                // codes correctly as they don't report connected until streaming
                // connection is established and hence end up here.
                if (faultEvent.faultCode == "Channel.Authentication.Error")
                    errorMsg.faultCode = faultEvent.faultCode;
            }
            // ChannelEvent.DISCONNECT is treated the same as never
            // being able to connect at all.
            else
            {
                errorMsg.faultDetail = resourceManager.getString(
                    "messaging", "cannotConnectToDestination");
            }
            errorMsg.rootCause = event;
            ps.agent.fault(errorMsg, pendingMsg);
        }
    }

    /**
     *  Redispatches message events from the currently connected Channel.
     *
     *  @param event The MessageEvent from the Channel.
     */
    protected function messageHandler(event:MessageEvent):void
    {
        dispatchEvent(event);
    }

    /**
     *  @private
     *  Schedules a heartbeat to be sent in heartbeatInterval milliseconds.
     */
    protected function scheduleHeartbeat():void
    {
        if (_heartbeatTimer == null && heartbeatInterval > 0)
        {
            _heartbeatTimer = new Timer(heartbeatInterval, 1);
            _heartbeatTimer.addEventListener(TimerEvent.TIMER, sendHeartbeatHandler);
            _heartbeatTimer.start();
        }
    }

    /**
     *  @private
     *  Handles a heartbeat timer event by conditionally sending a heartbeat
     *  and scheduling the next.
     */
    protected function sendHeartbeatHandler(event:TimerEvent):void
    {
        unscheduleHeartbeat();
        if (currentChannel != null)
        {
            sendHeartbeat();
            scheduleHeartbeat();
        }
    }

    /**
     *  @private
     *  Sends a heartbeat request.
     */
    protected function sendHeartbeat():void
    {
        // Current channel may be actively polling, which suppresses explicit heartbeats.
        var pollingChannel:PollingChannel = currentChannel as PollingChannel;
        if (pollingChannel != null && pollingChannel._shouldPoll) return;
        // Issue an explicit heartbeat and schedule the next.
        var heartbeat:CommandMessage = new CommandMessage();
        heartbeat.operation = CommandMessage.CLIENT_PING_OPERATION;
        heartbeat.headers[CommandMessage.HEARTBEAT_HEADER] = true;
        currentChannel.sendInternalMessage(new MessageResponder(null /* no agent */, heartbeat));
    }

    /**
     *  @private
     *  Unschedules any currently scheduled pending heartbeat.
     */
    protected function unscheduleHeartbeat():void
    {
        if (_heartbeatTimer != null)
        {
            _heartbeatTimer.stop();
            _heartbeatTimer.removeEventListener(TimerEvent.TIMER, sendHeartbeatHandler);
            _heartbeatTimer = null;
        }
    }

    //--------------------------------------------------------------------------
    //
    // Private Methods
    //
    //--------------------------------------------------------------------------

    /**
     *  @private
     *  Helper method to connect the current internal Channel.
     */
    private function connectChannel():void
    {
        _connecting = true;
        _currentChannel.connect(this);
        // Listen for any server pushed messages on the Channel.
        _currentChannel.addEventListener(MessageEvent.MESSAGE, messageHandler);
    }

    /**
     *  @private
     *  Helper method to disconnect the current internal Channel.
     */
    private function disconnectChannel():void
    {
        _connecting = false;
        // Stop listening for server pushed messages on the Channel.
        _currentChannel.removeEventListener(MessageEvent.MESSAGE, messageHandler);
        _currentChannel.disconnect(this);
    }

    /**
     *  @private
     *  Helper method to dispatch authentication-related RPC events.
     *
     *  @param event The event to dispatch.
     */
    private function dispatchRPCEvent(event:AbstractEvent):void
    {
        event.callTokenResponders();
        dispatchEvent(event);
    }

    /**
     *  @private
     *  Helper method to hunt to the next available internal Channel for the
     *  ChannelSet.
     *
     *  @return True if hunting to the next available Channel was successful; false if hunting
     *          exhausted available channels and has reset to the beginning of the set.
     *
     *  @throws mx.messaging.errors.NoChannelAvailableError If the ChannelSet has no internal
     *                                  Channels to use.
     */
    private function hunt():Boolean
    {
        if (_channels.length == 0)
        {
            var message:String = resourceManager.getString(
                "messaging", "noAvailableChannels");
            throw new NoChannelAvailableError(message);
        }

        // Unwire from the current channel.
        if (_currentChannel != null)
            disconnectChannel();

        // Advance to next channel, and reset to beginning if all Channels in the set
        // have been attempted.
        if (++_currentChannelIndex >= _channels.length)
        {
            _currentChannelIndex = -1;
            return false;
        }

        // If we've advanced past the first channel, indicate that we're hunting.
        if (_currentChannelIndex > 0)
            _hunting = true;

        // Set current channel.
        if (configured)
        {
            if (_channels[_currentChannelIndex] != null)
            {
                _currentChannel = _channels[_currentChannelIndex];
            }
            else
            {
                _currentChannel = ServerConfig.getChannel(_channelIds[
                                        _currentChannelIndex], _clustered);
                _currentChannel.setCredentials(_credentials);
                _channels[_currentChannelIndex] = _currentChannel;
            }
        }
        else
        {
            _currentChannel = _channels[_currentChannelIndex];
        }

        // Ensure that the current channel is assigned failover URIs it if was lazily instantiated.
        if ((_channelFailoverURIs != null) && (_channelFailoverURIs[_currentChannel.id] != null))
            _currentChannel.failoverURIs = _channelFailoverURIs[_currentChannel.id];

        return true;
    }

    /**
     *  @private
     *  This method is invoked by a timer and it works around a reconnect issue
     *  with NetConnection based channels within a single frame by reconnecting after a slight delay.
     */
    private function reconnectChannel(event:TimerEvent):void
    {
        _reconnectTimer.stop();
        _reconnectTimer.removeEventListener(TimerEvent.TIMER, reconnectChannel);
        _reconnectTimer = null;
        connectChannel();
    }
}

}

//------------------------------------------------------------------------------
//
// Private Classes
//
//------------------------------------------------------------------------------

import mx.core.mx_internal;
import mx.logging.Log;
import mx.messaging.ChannelSet;
import mx.messaging.MessageAgent;
import mx.messaging.MessageResponder;
import mx.messaging.events.ChannelEvent;
import mx.messaging.messages.IMessage;
import mx.messaging.messages.AcknowledgeMessage;
import mx.messaging.messages.CommandMessage;
import mx.messaging.messages.ErrorMessage;
import mx.rpc.AsyncToken;
import mx.collections.ArrayCollection;

use namespace mx_internal;

/**
 *  @private
 *  Clustered ChannelSets need to request the clustered channel endpoints for
 *  the channels they contain upon a successful connect. However, Channels
 *  require that all outbound messages be sent by a MessageAgent that their
 *  internal MessageResponder implementations can callback to upon a response
 *  or fault. The ChannelSet is not a MessageAgent, so in this case, it
 *  circumvents the regular Channel.send() by passing its own custom responder
 *  to Channel.sendUsingCustomResponder().
 *
 *  This is the custom responder.
 */
class ClusterMessageResponder extends MessageResponder
{
    //--------------------------------------------------------------------------
    //
    // Constructor
    //
    //--------------------------------------------------------------------------

    /**
     *  Constructor.
     *
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion BlazeDS 4
     *  @productversion LCDS 3
     */
    public function ClusterMessageResponder(message:IMessage, channelSet:ChannelSet)
    {
        super(null, message);
        _channelSet = channelSet;
    }

    //--------------------------------------------------------------------------
    //
    // Variables
    //
    //--------------------------------------------------------------------------

    /**
     *  @private
     *  Gives the responder access to this ChannelSet, to pass it failover URIs for
     *  its channels.
     */
    private var _channelSet:ChannelSet;

    //--------------------------------------------------------------------------
    //
    // Methods
    //
    //--------------------------------------------------------------------------

    /**
     *  Handles a cluster message response.
     *
     *  @param message The response Message.
     *
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion BlazeDS 4
     *  @productversion LCDS 3
     */
    override protected function resultHandler(message:IMessage):void
    {
        if ((message.body != null) && (message.body is Array || message.body is ArrayCollection))
        {
            var channelFailoverURIs:Object = {};
            var mappings:Array = message.body is Array? message.body as Array : (message.body as ArrayCollection).toArray();
            var n:int = mappings.length;
            for (var i:int = 0; i < n; i++)
            {
                var channelToEndpointMap:Object = mappings[i];
                for (var channelId:Object in channelToEndpointMap)
                {
                    if (channelFailoverURIs[channelId] == null)
                        channelFailoverURIs[channelId] = [];

                    channelFailoverURIs[channelId].push(channelToEndpointMap[channelId]);
                }
            }
            _channelSet.channelFailoverURIs = channelFailoverURIs;
        }
    }
}

/**
 *  @private
 *  Stores a pending message to send when the ChannelSet does not have a
 *  connected Channel to use immediately.
 */
class PendingSend
{
    //--------------------------------------------------------------------------
    //
    // Constructor
    //
    //--------------------------------------------------------------------------

    /**
     *  @private
     *  Constructor.
     *
     *  @param agent The MessageAgent sending the message.
     *
     *  @param msg The Message to send.
     */
    public function PendingSend(agent:MessageAgent, message:IMessage)
    {
        super();
        this.agent = agent;
        this.message = message;
    }

    //--------------------------------------------------------------------------
    //
    // Properties
    //
    //--------------------------------------------------------------------------

    /**
     *  @private
     *  The MessageAgent.
     */
    public var agent:MessageAgent;

    /**
     *  @private
     *  The Message to send.
     */
    public var message:IMessage;

}

/**
 *  @private
 *  Helper class for handling and redispatching login and logout results or faults.
 */
class AuthenticationAgent extends MessageAgent
{
    //--------------------------------------------------------------------------
    //
    // Public Static Constants
    //
    //--------------------------------------------------------------------------

    // State constants.
    public static const LOGGED_OUT_STATE:int = 0;
    public static const LOGGING_IN_STATE:int = 1;
    public static const LOGGED_IN_STATE:int = 2;
    public static const LOGGING_OUT_STATE:int = 3;
    public static const SHUTDOWN_STATE:int = 4;

    //--------------------------------------------------------------------------
    //
    // Constructor
    //
    //--------------------------------------------------------------------------

    /**
     *  Constructor.
     *
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion BlazeDS 4
     *  @productversion LCDS 3
     */
    public function AuthenticationAgent(channelSet:ChannelSet)
    {
        _log = Log.getLogger("ChannelSet.AuthenticationAgent");
        _agentType = "authentication agent";
        // Must set log and agent type before assigning channelSet.
        this.channelSet = channelSet;
    }

    //--------------------------------------------------------------------------
    //
    // Variables
    //
    //--------------------------------------------------------------------------

    /**
     * Map of login/logout message Ids to associated tokens.
     *
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion BlazeDS 4
     *  @productversion LCDS 3
     */
    private var tokens:Object = {};

    //--------------------------------------------------------------------------
    //
    // Properties
    //
    //--------------------------------------------------------------------------

    private var _state:int = LOGGED_OUT_STATE;

    /**
     * Returns the current state for the agent.
     * See the static state constants defined by this class.
     *
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion BlazeDS 4
     *  @productversion LCDS 3
     */
    public function get state():int
    {
        return _state;
    }

    public function set state(value:int):void
    {
        _state = value;
        if (value == SHUTDOWN_STATE)
            tokens = null;
    }

    //--------------------------------------------------------------------------
    //
    // Public Methods
    //
    //--------------------------------------------------------------------------

    /**
     * Registers an outbound login/logout message and its associated token for response/fault handling.
     *
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion BlazeDS 4
     *  @productversion LCDS 3
     */
    public function registerToken(token:AsyncToken):void
    {
        tokens[token.message.messageId] = token;
    }

    /**
     * Acknowledge message callback.
     *
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion BlazeDS 4
     *  @productversion LCDS 3
     */
    override public function acknowledge(ackMsg:AcknowledgeMessage, msg:IMessage):void
    {
        if (state == SHUTDOWN_STATE)
            return;

        var error:Boolean = ackMsg.headers[AcknowledgeMessage.ERROR_HINT_HEADER];
        // Super will clean the error hint from the message.
        super.acknowledge(ackMsg, msg);
        // If acknowledge is *not* for a message that caused an error
        // dispatch a result event.
        if (!error)
        {
            var token:AsyncToken = tokens[msg.messageId];
            delete tokens[msg.messageId];
            channelSet.authenticationSuccess(this, token, ackMsg as AcknowledgeMessage);
        }
    }

    /**
     * Fault callback.
     *
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion BlazeDS 4
     *  @productversion LCDS 3
     */
    override public function fault(errMsg:ErrorMessage, msg:IMessage):void
    {
        if (state == SHUTDOWN_STATE)
            return;

        // For some channel impls, when a logout request is processed the session at the remote host host
        // is invalidated which may trigger a disconnection/drop of the channel connection.
        // This channel disconnect may mask the logout ack. If the root cause for this error is a channel disconnect,
        // assume logout succeeded and locally acknowledge it.
        if (errMsg.rootCause is ChannelEvent && (errMsg.rootCause as ChannelEvent).type == ChannelEvent.DISCONNECT)
        {
            var ackMsg:AcknowledgeMessage = new AcknowledgeMessage();
            ackMsg.clientId = clientId;
            ackMsg.correlationId = msg.messageId;
            acknowledge(ackMsg, msg);
            return;
        }

        super.fault(errMsg, msg);

        var token:AsyncToken = tokens[msg.messageId];
        delete tokens[msg.messageId];
        channelSet.authenticationFailure(this, token, errMsg as ErrorMessage);
    }
}