////////////////////////////////////////////////////////////////////////////////
//
//  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.Timer;
import flash.utils.getDefinitionByName;

import mx.collections.ArrayCollection;
import mx.core.IMXMLObject;
import mx.core.mx_internal;
import mx.events.PropertyChangeEvent;
import mx.logging.ILogger;
import mx.logging.Log;
import mx.messaging.config.LoaderConfig;
import mx.messaging.config.ServerConfig;
import mx.messaging.errors.InvalidChannelError;
import mx.messaging.errors.InvalidDestinationError;
import mx.messaging.events.ChannelEvent;
import mx.messaging.events.ChannelFaultEvent;
import mx.messaging.messages.AbstractMessage;
import mx.messaging.messages.CommandMessage;
import mx.messaging.messages.IMessage;
import mx.resources.IResourceManager;
import mx.resources.ResourceManager;
import mx.rpc.AsyncDispatcher;
import mx.utils.URLUtil;

use namespace mx_internal;

/**
 *  Dispatched after the channel has connected to its endpoint.
 * <p>Channel and its subclasses issue a Channel.Connect.Failed code whenever there is an issue in a channel's  connect attempts to a remote destination. An AMFChannel object issues Channel.Call.Failed code when the channel is already connected but it gets a Call.Failed code from its underlying NetConnection.</p>
 *
 *  @eventType mx.messaging.events.ChannelEvent.CONNECT
 */
[Event(name="channelConnect", type="mx.messaging.events.ChannelEvent")]

/**
 *  Dispatched after the channel 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 the channel 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")]

/**
 *  Dispatched when a channel receives a message from its endpoint.
 * 
 *  @eventType mx.messaging.events.MessageEvent.MESSAGE
 *
 *  @langversion 3.0
 *  @playerversion Flash 9
 *  @playerversion AIR 1.1
 *  @productversion BlazeDS 4
 *  @productversion LCDS 3  
 */
[Event(name="message", type="mx.messaging.events.MessageEvent")]

/**
 *  Dispatched when a property of the channel 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 Channel class is the base message channel class that all channels in the messaging
 *  system must extend.
 *
 *  <p>Channels are specific protocol-based conduits for messages sent between 
 *  MessageAgents and remote destinations.
 *  Preconfigured channels are obtained within the framework using the
 *  <code>ServerConfig.getChannel()</code> method.
 *  You can create a Channel directly using the <code>new</code> operator and
 *  add it to a ChannelSet directly.</p>
 * 
 *  <p>
 *  Channels represent a physical connection to a remote endpoint.
 *  Channels are shared across destinations by default.
 *  This means that a client targetting different destinations may use
 *  the same Channel to communicate with these destinations.
 *  </p>
 *
 *  <p><b>Note:</b> This class is for advanced use only.
 *  Use this class for creating custom channels like the existing RTMPChannel,
 *  AMFChannel, and HTTPChannel.</p>
 *
 *  @langversion 3.0
 *  @playerversion Flash 9
 *  @playerversion AIR 1.1
 *  @productversion BlazeDS 4
 *  @productversion LCDS 3 
 */
public class Channel extends EventDispatcher implements IMXMLObject
{
    //--------------------------------------------------------------------------
    //
    // Protected Static Constants
    //
    //--------------------------------------------------------------------------

    /**
     *  @private
     *  Channel config parsing constants. 
     */
    protected static const CLIENT_LOAD_BALANCING:String = "client-load-balancing"
    protected static const CONNECT_TIMEOUT_SECONDS:String = "connect-timeout-seconds";
    protected static const ENABLE_SMALL_MESSAGES:String = "enable-small-messages";
    protected static const FALSE:String = "false";
    protected static const RECORD_MESSAGE_TIMES:String = "record-message-times";
    protected static const RECORD_MESSAGE_SIZES:String = "record-message-sizes";
    protected static const REQUEST_TIMEOUT_SECONDS:String = "request-timeout-seconds";
    protected static const SERIALIZATION:String = "serialization";
    protected static const TRUE:String = "true";

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

    /**
     *  Constructs an instance of a generic Channel that connects to the
     *  specified endpoint URI.
     *
     *  <b>Note</b>: The Channel type should not be constructed directly. Instead
     *  create instances of protocol specific subclasses such as RTMPChannel or
     *  AMFChannel.
     *
     *  @param id The id of this channel.
     * 
     *  @param uri The endpoint URI for this channel.
     *
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion BlazeDS 4
     *  @productversion LCDS 3      
     */
    public function Channel(id:String = null, uri:String = null)
    {
        super();

        _log = Log.getLogger("mx.messaging.Channel");
        _failoverIndex = -1;
        this.id = id;
        _primaryURI = uri;
        this.uri = uri; // Current URI
    }

    /**
     * @private
     */
    public function initialized(document:Object, id:String):void
    {
        this.id = id;
    }
        
    //--------------------------------------------------------------------------
    //
    // Variables
    // 
    //--------------------------------------------------------------------------

    /**
     *  @private
     *  Used to prevent multiple logouts.
     */
    mx_internal var authenticating:Boolean;
    
    /**
     *  @private
     *  The credentials string that is passed via a CommandMessage to the server when the
     *  Channel connects. Channels inherit the credentials of connected ChannelSets that
     *  inherit their credentials from connected MessageAgents. 
     *  <code>MessageAgent.setCredentials(username, password)</code> is generally used
     *  to set credentials.
     */
    protected var credentials:String;

    /**
     * @private
     * A channel specific override to determine whether small messages should
     * be used. If set to false, small messages will not be used even if they
     * are supported by an endpoint.
     */
    public var enableSmallMessages:Boolean = true;

    /**
     *  @private
     *  Provides access to a logger for this channel.
     */
    protected var _log:ILogger;
    
    /**
     *  @private
     *  Flag indicating whether the Channel is in the process of connecting.
     */
    protected var _connecting:Boolean;

    /**
     *  @private
     *  Timer to track connect timeouts.
     */
    private var _connectTimer:Timer;   

    /**
     *  @private
     *  Current index into failover URIs during a failover attempt.
     *  When not failing over, this variable is reset to a sentinal
     *  value of -1.
     */
    private var _failoverIndex:int; 

    /**
     * @private
     * Flag indicating whether the endpoint has been calculated from the uri.
     */   
    private var _isEndpointCalculated:Boolean;

    /**
     * @private
     * The messaging version implies which features are enabled on this client
     * channel. Channel endpoints exchange this information through headers on
     * the ping CommandMessage exchanged during the connection handshake.
     */
    protected var messagingVersion:Number = 1.0;

    /**
     *  @private
     *  Flag indicating whether this Channel owns the wait guard for managing initial connect attempts.
     */
    private var _ownsWaitGuard:Boolean;
    
    /**
     *  @private
     *  Indicates whether the Channel was previously connected successfully. Used for pinned reconnect
     *  attempts before trying failover options.
     */
    private var _previouslyConnected:Boolean;
    
    /**
     *  @private
     *  Primary URI; the initial URI for this channel.
     */
    private var _primaryURI:String
    
    /**
     *  @private
     *  Used for pinned reconnect attempts.
     */
    mx_internal var reliableReconnectDuration:int = -1;
    private var _reliableReconnectBeginTimestamp:Number;
    private var _reliableReconnectLastTimestamp:Number;
    private var _reliableReconnectAttempts:int;

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

    //----------------------------------
    //  channelSets
    //----------------------------------
    
    /**
     *  @private
     */
    private var _channelSets:Array = [];
    
    /**
     *  Provides access to the ChannelSets connected to the Channel.
     *
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion BlazeDS 4
     *  @productversion LCDS 3 
     */
    public function get channelSets():Array
    {
        return _channelSets;   
    }    

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

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

    [Bindable(event="propertyChange")]
    /**
     *  Indicates whether this channel has established a connection to the 
     *  remote destination.
     *
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion BlazeDS 4
     *  @productversion LCDS 3      
     */
    public function get connected():Boolean
    {
        return _connected;
    }
    
    /**
     *  @private
     */
    protected function setConnected(value:Boolean):void
    {
        if (_connected != value)
        {
            if (_connected)
               _previouslyConnected = true;
            
            var event:PropertyChangeEvent = PropertyChangeEvent.createUpdateEvent(this, "connected", _connected, value)
            _connected = value;
            dispatchEvent(event);
            if (!value)
                setAuthenticated(false);
        }
    }
    
    //----------------------------------
    //  connectTimeout
    //----------------------------------
    
    /**
     *  @private
     */
    private var _connectTimeout:int = -1;   
    
    /**
     *  Provides access to the connect timeout in seconds for the channel. 
     *  A value of 0 or below indicates that a connect attempt will never 
     *  be timed out on the client.
     *  For channels that are configured to failover, this value is the total
     *  time to wait for a connection to be established.
     *  It is not reset for each failover URI that the channel may attempt 
     *  to connect to.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion BlazeDS 4
     *  @productversion LCDS 3 
     */ 
    public function get connectTimeout():int
    {
        return _connectTimeout;
    }
    
    /**
     *  @private
     */
    public function set connectTimeout(value:int):void
    {
        _connectTimeout = value;
    }   
    
    //----------------------------------
    //  endpoint
    //----------------------------------    

    /**
     *  @private
     */ 
    private var _endpoint:String;   
    
    /**
     *  Provides access to the endpoint for this channel.
     *  This value is calculated based on the value of the <code>uri</code>
     *  property.
     */
    public function get endpoint():String
    {
        if (!_isEndpointCalculated)
            calculateEndpoint();
        return _endpoint;
    }

    //----------------------------------
    //  recordMessageTimes
    //----------------------------------
        
    /**
     * @private
     */
    protected var _recordMessageTimes:Boolean = false;

    /**
     * Channel property determines the level of performance information injection - whether
     * we inject timestamps or not. 
     *
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion BlazeDS 4
     *  @productversion LCDS 3 
     */
    public function get recordMessageTimes():Boolean
    {
        return _recordMessageTimes;
    }   

    //----------------------------------    
    //  recordMessageSizes
    //----------------------------------
        
    /**
     * @private
     */
    protected var _recordMessageSizes:Boolean = false;

    /**
     * Channel property determines the level of performance information injection - whether
     * we inject message sizes or not.
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion BlazeDS 4
     *  @productversion LCDS 3      
     */   
    public function get recordMessageSizes():Boolean
    {
        return _recordMessageSizes;
    }         
    
    //----------------------------------
    //  reconnecting
    //----------------------------------

    /**
     *  @private
     */
    private var _reconnecting:Boolean = false;

    [Bindable(event="propertyChange")]
    /**
     *  Indicates whether this channel is in the process of reconnecting to an
     *  alternate endpoint.
     */
    public function get reconnecting():Boolean
    {
        return _reconnecting;
    }
    
    private function setReconnecting(value:Boolean):void
    {
        if (_reconnecting != value)
        {
            var event:PropertyChangeEvent = PropertyChangeEvent.createUpdateEvent(this, "reconnecting", _reconnecting, value);
            _reconnecting = value;
            dispatchEvent(event);
        }
    }
    
    //----------------------------------
    //  failoverURIs
    //----------------------------------    
    
    /**
     *  @private
     */
    private var _failoverURIs:Array;    
    
    /**
     *  Provides access to the set of endpoint URIs that this channel can
     *  attempt to failover to if the endpoint is clustered.
     *
     *  <p>This property is automatically populated when clustering is enabled.
     *  If you don't use clustering, you can set your own values.</p>
     */ 
    public function get failoverURIs():Array
    {
        return (_failoverURIs != null) ? _failoverURIs : [];
    }
    
    /**
     *  @private
     */
    public function set failoverURIs(value:Array):void
    {
        if (value != null)
        {
            _failoverURIs = value;
            _failoverIndex = -1; // Reset the index, because URIs have changed
        }
    }   

    //----------------------------------
    //  id
    //----------------------------------
    
    /**
     *  @private
     */
    private var _id:String; 
    
    /**
     *  Provides access to the id of this channel.
     */
    public function get id():String
    {
        return _id;
    }
    
    public function set id(value:String):void
    {
        if (_id != value)
            _id = value;
    }

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

    private var _authenticated:Boolean = false;
    
    [Bindable(event="propertyChange")]
    /**
     *  Indicates if this channel is authenticated.
     */
    public function get authenticated():Boolean
    {
        return _authenticated;
    }
    
    mx_internal function setAuthenticated(value:Boolean):void
    {
        if (value != _authenticated)
        {
            var event:PropertyChangeEvent = PropertyChangeEvent.createUpdateEvent(this, "authenticated", _authenticated, value);
            _authenticated = value;

            var cs:ChannelSet;
            for (var i:int = 0; i < _channelSets.length; i++)
            {
                cs = ChannelSet(_channelSets[i]);
                cs.mx_internal::setAuthenticated(authenticated, credentials)
            }
                
            dispatchEvent(event);
        }
    }   

    //----------------------------------
    //  protocol
    //----------------------------------

    /**
     *  Provides access to the protocol that the channel uses.
     *
     *  <p><b>Note:</b> Subclasses of Channel must override this method and return 
     *  a string that represents their supported protocol.
     *  Examples of supported protocol strings are "rtmp", "http" or "https".
     * </p>
     */
    public function get protocol():String
    {
        throw new IllegalOperationError("Channel subclasses must override "
            + "the get function for 'protocol' to return the proper protocol "
            + "string.");     
    }

    //----------------------------------
    //  realtime
    //----------------------------------

    /**
     *  @private
     *  Returns true if the channel supports realtime behavior via server push or client poll.
     */
    mx_internal function get realtime():Boolean
    {
        return false;
    }
    
    //----------------------------------
    //  requestTimeout
    //----------------------------------
    
    /**
     *  @private
     */
    private var _requestTimeout:int = -1;   
    
    /**
     *  Provides access to the default request timeout in seconds for the 
     *  channel. A value of 0 or below indicates that outbound requests will 
     *  never be timed out on the client.
     *  <p>Request timeouts are most useful for RPC style messaging that 
     *  requires a response from the remote destination.</p>
     */ 
    public function get requestTimeout():int
    {
        return _requestTimeout;
    }
    
    /**
     *  @private
     */
    public function set requestTimeout(value:int):void
    {
        _requestTimeout = value;
    }

    //----------------------------------
    //  shouldBeConnected
    //----------------------------------
    
    /**
     *  @private  
     */
    private var _shouldBeConnected:Boolean;
    
    /**
     *  Indicates whether this channel should be connected to its endpoint.
     *  This flag is used to control when fail over should be attempted and when disconnect
     *  notification is sent to the remote endpoint upon disconnect or fault.
     */
    protected function get shouldBeConnected():Boolean
    {
        return _shouldBeConnected;
    }

    //----------------------------------
    //  uri
    //----------------------------------

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

    /**
     *  Provides access to the URI used to create the whole endpoint URI for this channel. 
     *  The URI can be a partial path, in which case the full endpoint URI is computed as necessary.
     */
    public function get uri():String
    {
        return _uri;
    } 

    public function set uri(value:String):void
    {
        if (value != null)
        {
            _uri = value;
            calculateEndpoint(); 
        }
    }

    /**
     * @private
     * This alternate property for an endpoint URL is provided to match the
     * endpoint configuration attribute &quot;url&quot;. This property is
     * equivalent to the <code>uri</code> property.
     */
    public function get url():String
    {
        return uri;
    } 

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

    //----------------------------------
    //  useSmallMessages
    //----------------------------------

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

    /**
     * This flag determines whether small messages should be sent if the
     * alternative is available. This value should only be true if both the
     * client channel and the server endpoint have successfully advertised that
     * they support this feature.
     * @private
     */
    public function get useSmallMessages():Boolean
    {
        return _smallMessagesSupported && enableSmallMessages;
    }

    /**
     * @private
     */
    public function set useSmallMessages(value:Boolean):void
    {
        _smallMessagesSupported = value;
    }

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

    /**
     *  Subclasses should override this method to apply any settings that may be
     *  necessary for an individual channel.
     *  Make sure to call <code>super.applySettings()</code> to apply common settings for the channel. * *  This method is used primarily in Channel subclasses.
     *
     *  @param settings XML fragment of the services-config.xml file for this channel.
       */
    public function applySettings(settings:XML):void
    {
        if (Log.isInfo())
            _log.info("'{0}' channel settings are:\n{1}", id, settings);

        if (settings.properties.length() == 0)
            return;

        var props:XML = settings.properties[0];
        applyClientLoadBalancingSettings(props);
        if (props[CONNECT_TIMEOUT_SECONDS].length() != 0)
            connectTimeout = props[CONNECT_TIMEOUT_SECONDS].toString();
        if (props[RECORD_MESSAGE_TIMES].length() != 0)
            _recordMessageTimes = props[RECORD_MESSAGE_TIMES].toString() == TRUE;
        if (props[RECORD_MESSAGE_SIZES].length() != 0)
            _recordMessageSizes = props[RECORD_MESSAGE_SIZES].toString() == TRUE;
        if (props[REQUEST_TIMEOUT_SECONDS].length() != 0)
            requestTimeout = props[REQUEST_TIMEOUT_SECONDS].toString();
        var serializationProps:XMLList = props[SERIALIZATION];
        if (serializationProps.length() != 0 && serializationProps[ENABLE_SMALL_MESSAGES].toString() == FALSE)
            enableSmallMessages = false;
    }

    /**
     *  Applies the client load balancing urls if they exists. It randomly picks
     *  a url from the set of client load balancing urls and sets it as the channel's
     *  main url; then it assigns the rest of the urls as the <code>failoverURIs</code>
     *  of the channel.
     *
     *  @param props The properties section of the XML fragment of the services-config.xml
     *  file for this channel.
     */
    protected function applyClientLoadBalancingSettings(props:XML):void
    {
        var clientLoadBalancingProps:XMLList = props[CLIENT_LOAD_BALANCING];
        if (clientLoadBalancingProps.length() == 0)
            return;

        var urlCount:int = clientLoadBalancingProps.url.length();
        if (urlCount == 0)
            return;

        // Add urls to an array, so they can be shuffled.
        var urls:Array = [];
        for each (var url:XML in clientLoadBalancingProps.url)
            urls.push(url.toString());

        shuffle(urls);

        // Select the first url as the main url.
        if (Log.isInfo())
            _log.info("'{0}' channel picked {1} as its main url.", id, urls[0]);
        this.url = urls[0];

        // Assign the rest of the urls as failoverUris.
        var failoverURIs:Array = urls.slice(1);
        if (failoverURIs.length > 0)
            this.failoverURIs = failoverURIs;
    }

    /**
     *  Connects the ChannelSet to the Channel. If the Channel has not yet
     *  connected to its endpoint, it attempts to do so.
     *  Channel subclasses must override the <code>internalConnect()</code> 
     *  method, and call the <code>connectSuccess()</code> method once the
     *  underlying connection is established.
     * 
     *  @param channelSet The ChannelSet to connect to the Channel.
     */
    final public function connect(channelSet:ChannelSet):void
    {               
        var exists:Boolean = false;
        var n:int = _channelSets.length;
        for (var i:int = 0; i < _channelSets.length; i++)
        {
            if (_channelSets[i] == channelSet)
            {
                exists = true;
                break;   
            }
        }
        
        _shouldBeConnected = true;
        if (!exists)
        {
            _channelSets.push(channelSet);
            // Wire up ChannelSet's channel event listeners.
            addEventListener(ChannelEvent.CONNECT, channelSet.channelConnectHandler);
            addEventListener(ChannelEvent.DISCONNECT, channelSet.channelDisconnectHandler);
            addEventListener(ChannelFaultEvent.FAULT, channelSet.channelFaultHandler);
        }       
        // If we are already connected, notify the ChannelSet. Otherwise connect
        // if necessary.
        if (connected)
        {
            channelSet.channelConnectHandler(ChannelEvent.createEvent(ChannelEvent.CONNECT, this, false, false, connected));
        }
        else if (!_connecting)
        {            
            _connecting = true;
         
            // If a connect timeout is defined, start the corresponding timer.
            if (connectTimeout > 0)
            {
                _connectTimer = new Timer(connectTimeout * 1000, 1);
                _connectTimer.addEventListener(TimerEvent.TIMER, connectTimeoutHandler);
                _connectTimer.start();
            }
            
            // We have to prevent a race between multipe Channel instances attempting to connect concurrently
            // at application startup. We detect this situation by testing whether the FlexClient Id has been assigned or not.
            if (FlexClient.getInstance().id == null)
            {
                var flexClient:FlexClient = FlexClient.getInstance();
                if (!flexClient.waitForFlexClientId)
                {
                    flexClient.waitForFlexClientId = true;
                    // This will cause other Channels to wait to attempt to connect.
                    // This Channel can continue its attempt.
                    _ownsWaitGuard = true;
                    internalConnect();
                }
                else
                {
                    // This Channel should wait to attempt to connect.
                    flexClient.addEventListener(PropertyChangeEvent.PROPERTY_CHANGE, flexClientWaitHandler);
                }                
            }
            else
            {
                // Another Channel has connected and we have an assigned FlexClient Id.
                internalConnect();
            }
        }
    }

    /**
     *  Disconnects the ChannelSet from the Channel. If the Channel is connected
     *  to its endpoint and it has no more connected ChannelSets it will 
     *  internally disconnect.
     *
     *  <p>Channel subclasses need to override the 
     *  <code>internalDisconnect()</code> method, and call the
     *  <code>disconnectSuccess()</code> method when the underlying connection
     *  has been terminated.</p>
     * 
     *  @param channelSet The ChannelSet to disconnect from the Channel.
     */
    final public function disconnect(channelSet:ChannelSet):void
    {
        // If we own the wait guard for initial Channel connects release it.
        // This will only be true if this Channel is the first to attempt to connect
        // but its connect attempt is still pending when disconnect() is invoked.
        if (_ownsWaitGuard)
        {
            _ownsWaitGuard = false;
            FlexClient.getInstance().waitForFlexClientId = false; // Allow other Channels to connect.
        }
        
        // Disconnect the channelSet.
        var i:int = channelSet != null ? _channelSets.indexOf(channelSet) : -1;
        if (i != -1)
        {
            _channelSets.splice(i, 1);
            // Remove the ChannelSet as a listener to this Channel.
            removeEventListener(ChannelEvent.CONNECT, channelSet.channelConnectHandler, false);
            removeEventListener(ChannelEvent.DISCONNECT, channelSet.channelDisconnectHandler, false);                
            removeEventListener(ChannelFaultEvent.FAULT, channelSet.channelFaultHandler, false);
            
            // Notify the ChannelSet of the disconnect.                
            if (connected) 
            {    
                channelSet.channelDisconnectHandler(ChannelEvent.createEvent(ChannelEvent.DISCONNECT, this, false));
            }
        
            // Shut down the underlying connection if this Channel has no more 
            // ChannelSets using it.
            if (_channelSets.length == 0)
            {
                _shouldBeConnected = false;
                if (connected)
                    internalDisconnect();
            }
        }
    }
    
    /**
     *  Sends a CommandMessage to the server to logout if the Channel is connected.
     *  Current credentials are cleared.
     * 
     *  @param agent The MessageAgent to logout.
     */
    public function logout(agent:MessageAgent):void
    {
        if ((connected && authenticated && credentials) || (authenticating && credentials))
        {       
            var msg:CommandMessage = new CommandMessage();
            msg.operation = CommandMessage.LOGOUT_OPERATION;
            internalSend(new AuthenticationMessageResponder(agent, msg, this, _log));
            authenticating = true;
        }
        credentials = null;
    }

    /**
     *  Sends the specified message to its target destination.
     *  Subclasses must override the <code>internalSend()</code> method to
     *  perform the actual send.
     *
     *  @param agent The MessageAgent that is sending the message.
     * 
     *  @param message The Message to send.
     * 
     *  @throws mx.messaging.errors.InvalidDestinationError If neither the MessageAgent nor the
     *                                  message specify a destination.
     */
    public function send(agent:MessageAgent, message:IMessage):void
    {
        // Set the destination header of the message if it is not already set.
        if (message.destination.length == 0)
        {
            if (agent.destination.length == 0)
            {
                var msg:String = resourceManager.getString(
                    "messaging", "noDestinationSpecified");
                throw new InvalidDestinationError(msg);
            }
            message.destination = agent.destination;
        }

        if (Log.isDebug())
            _log.debug("'{0}' channel sending message:\n{1}", id, message.toString());

        // Tag the message with a header indicating the Channel/Endpoint used for transport.    
        message.headers[AbstractMessage.ENDPOINT_HEADER] = id;

        var responder:MessageResponder = getMessageResponder(agent, message);
        initializeRequestTimeout(responder);
        internalSend(responder);
    }

    /**
     *  Sets the credentials to the specified value. 
     *  If the credentials are non-null and the Channel is connected, this method also
     *  sends a CommandMessage to the server to login using the credentials.
     * 
     *  @param credentials The credentials string.
     *  @param agent The MessageAgent to login, that will handle the login result.
     *  @param charset The character set encoding used while encoding the
     *  credentials. The default is null, which implies the legacy charset 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.
     */
    public function setCredentials(credentials:String, agent:MessageAgent=null, charset:String=null):void
    {
        var changedCreds:Boolean = this.credentials !== credentials;

        if (authenticating && changedCreds)
            throw new IllegalOperationError("Credentials cannot be set while authenticating or logging out.");

        if (authenticated && changedCreds)
            throw new IllegalOperationError("Credentials cannot be set when already authenticated. Logout must be performed before changing credentials.");
        
        this.credentials = credentials;
        if (connected && changedCreds && credentials != null)
        {
            authenticating = true;
            var msg:CommandMessage = new CommandMessage();
            msg.operation = CommandMessage.LOGIN_OPERATION;
            msg.body = credentials;
            if (charset != null)
                msg.headers[CommandMessage.CREDENTIALS_CHARSET_HEADER] = charset;
            internalSend(new AuthenticationMessageResponder(agent, msg, this, _log));  
        }
    }
    
    /**
     * @private     
     * Should we record any performance metrics
     */       
    public function get mpiEnabled():Boolean
    {
        return _recordMessageSizes || _recordMessageTimes;
    }       

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

    /**
     *  @private
     *  Internal hook for ChannelSet to assign credentials when it has authenticated
     *  successfully via a direct <code>login(...)</code> call to the server.
     */
    mx_internal function internalSetCredentials(credentials:String):void
    {
        this.credentials = credentials;
    }

    /**
     *  @private
     *  This is a hook for ChannelSet (not a MessageAgent) to send internal messages. 
     *  This is used for fetching info on clustered endpoints for a clustered destination
     *  as well as for optional heartbeats, etc.
     * 
     *  @param msgResp The message responder to use for the internal message.
     */
    mx_internal function sendInternalMessage(msgResp:MessageResponder):void
    {
        internalSend(msgResp);
    }

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

    /**
     *  Processes a failed internal connect and dispatches the 
     *  <code>FAULT</code> event for the channel.
     *  If the Channel has <code>failoverURI</code> values, it will
     *  attempt to reconnect automatically by trying these URI values in order until 
     *  a connection is established or the available values are exhausted.
     * 
     *  @param event The ChannelFaultEvent for the failed connect.
     */
    protected function connectFailed(event:ChannelFaultEvent):void
    {            
        shutdownConnectTimer();
        setConnected(false);
        
        if (Log.isError())
            _log.error("'{0}' channel connect failed.", id);
            
        if (!event.rejected && shouldAttemptFailover())
        {
            _connecting = true;
            failover();            
        }
        else // Not attempting failover.
        {
            connectCleanup();
        }
        
        if (reconnecting)
            event.reconnecting = true;
        dispatchEvent(event);
    }

    /**
     *  Processes a successful internal connect and dispatches the 
     *  <code>CONNECT</code> event for the Channel.
     */
    protected function connectSuccess():void
    {
        shutdownConnectTimer();
        
        // If there were any attached agents that needed configuration they
        // should be reset.
        if (ServerConfig.fetchedConfig(endpoint))
        {
            for (var i:int = 0; i < channelSets.length; i++)
            {
                var messageAgents:Array = ChannelSet(channelSets[i]).messageAgents;
                for (var j:int = 0; j < messageAgents.length; j++)
                {
                    messageAgents[j].needsConfig = false;
                }
            }
        }
            
        setConnected(true);
        _failoverIndex = -1;
        
        if (Log.isInfo())
            _log.info("'{0}' channel is connected.", id);
              
        dispatchEvent(ChannelEvent.createEvent(ChannelEvent.CONNECT, this, reconnecting));
                                                                
        connectCleanup();
    }
    
    /**
     *  Handles a connect timeout by dispatching a ChannelFaultEvent. 
     *  Subtypes may overide this to shutdown the current connect attempt but must 
     *  call <code>super.connectTimeoutHandler(event)</code>.
     * 
     *  @param event The timer event indicating that the connect timeout has been reached.
     */
    protected function connectTimeoutHandler(event:TimerEvent):void
    {
        shutdownConnectTimer();
        if (!connected)
        {
            _shouldBeConnected = false;
            var errorText:String = resourceManager.getString(
                "messaging", "connectTimedOut");
            var faultEvent:ChannelFaultEvent = ChannelFaultEvent.createEvent(this, false, "Channel.Connect.Failed", "error", errorText);
            connectFailed(faultEvent);
        }                
    }

    /**
     *  Processes a successful internal disconnect and dispatches the 
     *  <code>DISCONNECT</code> event for the Channel.
     *  If the disconnect is due to a network failure and the Channel has 
     *  <code>failoverURI</code> values, it will attempt to reconnect automatically 
     *  by trying these URI values in order until a connection is established or the 
     *  available values are exhausted.
     *  
     *  @param rejected True if the disconnect should skip any
     *         failover processing that would otherwise be attempted; false
     *         if failover processing should be allowed to run.
     */
    protected function disconnectSuccess(rejected:Boolean = false):void
    {             
        setConnected(false);
        
        if (Log.isInfo())
            _log.info("'{0}' channel disconnected.", id);
        
        if (!rejected && shouldAttemptFailover())
        {
            _connecting = true;
            failover();
        }
        else
        {
            connectCleanup();
        }
        
        dispatchEvent(ChannelEvent.createEvent(ChannelEvent.DISCONNECT, this, 
                                            reconnecting, rejected));
    }

    /**
     *  Processes a failed internal disconnect and dispatches the
     *  <code>FAULT</code> event for the channel.
     * 
     *  @param event The ChannelFaultEvent for the failed disconnect.
     */
    protected function disconnectFailed(event:ChannelFaultEvent):void
    {
        _connecting = false;  
        setConnected(false);

        if (Log.isError())
            _log.error("'{0}' channel disconnect failed.", id);
        
        if (reconnecting)
        {
            resetToPrimaryURI();
            event.reconnecting = false;
        }       
        dispatchEvent(event);
    }
    
    /**
     *  Handles a change to the guard condition for managing initial Channel connect for the application.
     *  When this is invoked it means that this Channel is waiting to attempt to connect.
     * 
     *  @param event The PropertyChangeEvent dispatched by the FlexClient singleton.
     */
    protected function flexClientWaitHandler(event:PropertyChangeEvent):void
    {
        if (event.property == "waitForFlexClientId")
        {
            var flexClient:FlexClient = event.source as FlexClient;
            if (flexClient.waitForFlexClientId == false) // The wait is over, claim it and attempt to connect.
            {               
                flexClient.removeEventListener(PropertyChangeEvent.PROPERTY_CHANGE, flexClientWaitHandler);
                flexClient.waitForFlexClientId = true;
                // This will cause other Channels to wait to attempt to connect.
                // This Channel can continue its attempt.
                _ownsWaitGuard = true;
                internalConnect();
            }
        }
    }

    /**
     *  Returns the appropriate MessageResponder for the Channel's
     *  <code>send()</code> method.
     *  Must be overridden.
     *
     *  @param agent The MessageAgent sending the message.
     * 
     *  @param message The Message to send.
     * 
     *  @return The MessageResponder to handle the result or fault.
     * 
     *  @throws flash.errors.IllegalOperationError If the Channel subclass does not override
     *                                this method.
     */
    protected function getMessageResponder(agent:MessageAgent, 
                                            message:IMessage):MessageResponder
    {
        throw new IllegalOperationError("Channel subclasses must override "
                                                + " getMessageResponder().");
    }

    /**
     *  Connects the Channel to its endpoint.
     *  Must be overridden.
     */
    protected function internalConnect():void {}

    /**
     *  Disconnects the Channel from its endpoint. 
     *  Must be overridden.
     * 
     *  @param rejected True if the disconnect was due to a connection rejection or timeout
     *                  and reconnection should not be attempted automatically; otherwise false. 
     */
    protected function internalDisconnect(rejected:Boolean = false):void {}
    
    /**
     *  Sends the Message out over the Channel and routes the response to the
     *  responder.
     *  Must be overridden.
     * 
     *  @param messageResponder The MessageResponder to handle the response.
     */
    protected function internalSend(messageResponder:MessageResponder):void {}

    /**
     * @private
     * Utility method to examine the reported server messaging version and
     * thus determine which features are available.
     */
    protected function handleServerMessagingVersion(version:Number):void
    {
        useSmallMessages = version >= messagingVersion;
    }

    /**
     *  @private
     *  Utility method used to assign the FlexClient Id value to outbound messages.
     * 
     *  @param message The message to set the FlexClient Id on.
     */
    protected function setFlexClientIdOnMessage(message:IMessage):void
    {
        var id:String = FlexClient.getInstance().id;
        message.headers[AbstractMessage.FLEX_CLIENT_ID_HEADER] = (id != null) ? id : FlexClient.NULL_FLEXCLIENT_ID;
    }


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

    /**
     *  @private   
     *  This method calculates the endpoint value based on the current
     *  <code>uri</code>.
     */
    private function calculateEndpoint():void
    {
        if (uri == null)
        {
            var message:String = resourceManager.getString(
                "messaging", "noURLSpecified");
            throw new InvalidChannelError(message);
        }

        var uriCopy:String = uri;
        var proto:String = URLUtil.getProtocol(uriCopy);

        if (proto.length == 0)
            uriCopy = URLUtil.getFullURL(LoaderConfig.url, uriCopy);

        if (URLUtil.hasTokens(uriCopy) && !URLUtil.hasUnresolvableTokens())
        {
            _isEndpointCalculated = false;
            return;
        }

        uriCopy = URLUtil.replaceTokens(uriCopy);
        
        // Now, check for a final protocol after relative URLs and tokens
        // have been replaced
        proto = URLUtil.getProtocol(uriCopy);

        if (proto.length > 0)
            _endpoint = URLUtil.replaceProtocol(uriCopy, protocol);
        else
            _endpoint = protocol + ":" + uriCopy;

        _isEndpointCalculated = true;
        
        if (Log.isInfo())
            _log.info("'{0}' channel endpoint set to {1}", id, _endpoint);            
    }
    
    /**
     *  @private
     *  Initializes the request timeout for this message if the outbound message 
     *  defines a REQUEST_TIMEOUT_HEADER value. 
     *  If this header is not set and the default requestTimeout for the 
     *  channel is greater than 0, the channel default is used. 
     *  Otherwise, no request timeout is enforced on the client.
     * 
     *  @param messageResponder The MessageResponder to handle the response and monitor the outbound
     *                          request for a timeout.
     */
    private function initializeRequestTimeout(messageResponder:MessageResponder):void
    {
        var message:IMessage = messageResponder.message;
        // Turn on request timeout machinery if the message defines it.
        if (message.headers[AbstractMessage.REQUEST_TIMEOUT_HEADER] != null)
        {
            messageResponder.startRequestTimeout(message.headers[AbstractMessage.REQUEST_TIMEOUT_HEADER]);
        }
        else if (requestTimeout > 0) // Use the channel default.
        {
            messageResponder.startRequestTimeout(requestTimeout);    
        }
    }    
    
    /**
     *  @private
     *  Convenience method to test whether the Channel should attempt to
     *  failover.
     * 
     *  @return <code>true</code> if the Channel should try to failover;
     *          otherwise <code>false</code>.
     */
    private function shouldAttemptFailover():Boolean
    {
        return (_shouldBeConnected && 
                   (_previouslyConnected ||
                   (reliableReconnectDuration != -1) || 
                   ((_failoverURIs != null) &&  (_failoverURIs.length > 0))));  
    } 
    
    /**
     *  @private
     *  This method attempts to fail the Channel over to the next available URI.
     */
    private function failover():void
    {
        // Potentially enter reliable reconnect loop.
        if (_previouslyConnected)
        {
            _previouslyConnected = false;              
                      
            var acs:Class = null;
            try
            {
                acs = getDefinitionByName("mx.messaging.AdvancedChannelSet") as Class;
            } 
            catch (ignore:Error) {}
            var duration:int = -1;                      
            if (acs != null)
            {                
                for each (var channelSet:ChannelSet in channelSets)
                {
                    if (channelSet is acs)
                    {
                        var d:int = (channelSet as acs)["reliableReconnectDuration"];
                        if (d > duration)
                            duration = d;
                    }                     
                }
            }
                       
            if (duration != -1)
            {
                setReconnecting(true);
                reliableReconnectDuration = duration;
                _reliableReconnectBeginTimestamp = new Date().valueOf();
                new AsyncDispatcher(reconnect, null, 1);
                return; // Exit early.
            }
        }
        
        // Potentially continue reliable reconnect loop.
        if (reliableReconnectDuration != -1)
        {
            _reliableReconnectLastTimestamp = new Date().valueOf();
            var remaining:Number = reliableReconnectDuration - (_reliableReconnectLastTimestamp - _reliableReconnectBeginTimestamp);            
            if (remaining > 0)
            {                                
                // Apply exponential backoff.
                var delay:int = 1000; // 1 second.
                delay << ++_reliableReconnectAttempts;
                if (delay < remaining)
                {
                    new AsyncDispatcher(reconnect, null, delay);
                    return; // Exit early. 
                }
            }
            // At this point the reliable reconnect duration has been exhausted.
            reliableReconnectCleanup();
        }
        
        // General failover handling.
        ++_failoverIndex;
        if ((_failoverIndex + 1) <= failoverURIs.length)
        {
            setReconnecting(true);
            uri = failoverURIs[_failoverIndex];
            
            if (Log.isInfo())
            {
                _log.info("'{0}' channel attempting to connect to {1}.", id, endpoint);
            }
            // NetConnection based channels may have their underlying resources
            // GC'ed at the end of the execution of the handler that has
            // invoked this method, which means that the results of a call to 
            // internalConnect() for these channels may magically vanish once 
            // the handler exits. 
            // A timer introduces a slight delay in the reconnect attempt to
            // give the handler time to finish executing, at which point the 
            // internals of a NetConnection channel will be stable and we can 
            // attempt to connect successfully.
            // This timer is applied to all channels but the impact is small 
            // enough and the failover scenario rare enough that special casing 
            // this for only NetConnection channels is more trouble than it's 
            // worth. 
            new AsyncDispatcher(reconnect, null, 1);          
        }
        else
        {
            if (Log.isInfo())
            {
                _log.info("'{0}' channel has exhausted failover options and has reset to its primary endpoint.", id);
            }
            // Nothing left to failover to; reset to primary.
            resetToPrimaryURI();         
        }
    }
    
    /**
     *  @private
     *  Cleanup following a connect or failover attempt.
     */
    private function connectCleanup():void
    {
        // If we own the wait guard for initial Channel connects release it.
        if (_ownsWaitGuard)
        {
            _ownsWaitGuard = false;
            FlexClient.getInstance().waitForFlexClientId = false; // Allow other Channels to connect.
        }
        
        _connecting = false;
        
        setReconnecting(false); // Ensure the reconnecting flag is turned off; failover is not being attempted.
        
        reliableReconnectCleanup();
    }
    
    /**
     *  @private
     *  This method is invoked by a timer from failover() and it works around a 
     *  reconnect issue with NetConnection based channels by invoking 
     *  internalConnect() after a slight delay.
     */
    private function reconnect(event:TimerEvent=null):void
    {
        internalConnect();
    }

    /**
     *  @private
     *  Cleanup following a reliable reconnect attempt.
     */
    private function reliableReconnectCleanup():void
    {
        reliableReconnectDuration = -1;
        _reliableReconnectBeginTimestamp = 0;
        _reliableReconnectLastTimestamp = 0;
        _reliableReconnectAttempts = 0;
    }
    
    /**
     *  @private
     *  This method resets the channel back to its primary URI after
     *  exhausting all failover URIs.
     */
    private function resetToPrimaryURI():void
    {
        _connecting = false;
        setReconnecting(false);
        uri = _primaryURI;
        _failoverIndex = -1;
    }
    
    /**
     *  @private
     *  Shuffles the array.
     */
    private function shuffle(elements:Array):void
    {
        var length:int = elements.length;
        for(var i:int=0; i < length; i++)
        {
            var index:int = Math.floor(Math.random()* length);
            if (index != i)
            {
                var temp:Object = elements[i];
                elements[i] = elements[index];
                elements[index] = temp;
            }
        }
    }

    /**
     *  @private
     *  Shuts down and nulls out the connect timer.
     */
    private function shutdownConnectTimer():void
    {
        if (_connectTimer != null)
        {
            _connectTimer.stop();
            _connectTimer.removeEventListener(TimerEvent.TIMER, connectTimeoutHandler);
            _connectTimer = null;
        }
    }

    //--------------------------------------------------------------------------
    //
    // Static Constants
    // 
    //--------------------------------------------------------------------------

    /**
     * @private
     */
    public static const SMALL_MESSAGES_FEATURE:String = "small_messages";
    
    /**
     *  @private
     *  Creates a compile time dependency on ArrayCollection to ensure
     *  it is present for response data containing collections.
     */ 
    private static const dep:ArrayCollection = null;
}

}

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

import mx.core.mx_internal;
import mx.logging.ILogger;
import mx.logging.Log;
import mx.messaging.Channel;
import mx.messaging.MessageAgent;
import mx.messaging.MessageResponder;
import mx.messaging.events.ChannelEvent;
import mx.messaging.events.ChannelFaultEvent;
import mx.messaging.messages.CommandMessage;
import mx.messaging.messages.ErrorMessage;
import mx.messaging.messages.IMessage;
import mx.events.PropertyChangeEvent;

/**
 *  @private
 *  Responder for processing channel authentication responses.
 */
class AuthenticationMessageResponder extends MessageResponder
{
    //--------------------------------------------------------------------------
    //
    // Constructor
    // 
    //--------------------------------------------------------------------------

    public function AuthenticationMessageResponder(agent:MessageAgent,
                                message:IMessage, channel:Channel, log:ILogger)
    {
        super(agent, message, channel);
        _log = log;
    }

    //--------------------------------------------------------------------------
    //
    // Variables
    // 
    //--------------------------------------------------------------------------
    
    /**
     *  @private
     *  Reference to the logger for the associated Channel.
     */
    private var _log:ILogger;
    
    //--------------------------------------------------------------------------
    //
    // Methods
    // 
    //--------------------------------------------------------------------------

    /**
     *  Handles an authentication result.
     * 
     *  @param msg The result Message.
     */
    override protected function resultHandler(msg:IMessage):void
    {
        var cmd:CommandMessage = message as CommandMessage;
        channel.mx_internal::authenticating = false;
        if (cmd.operation == CommandMessage.LOGIN_OPERATION)
        {
            if (Log.isDebug())
                _log.debug("Login successful");    

            // we want to set the authenticated property last as it will dispatch
            // an event in this case and handler code shouldn't get called
            // util the system is stable.
            channel.mx_internal::setAuthenticated(true);
        }
        else // Logout operation.
        {
            if (Log.isDebug())
                _log.debug("Logout successful");
                
            channel.mx_internal::setAuthenticated(false);
        }
    }

    /**
     *  Handles an authentication failure.
     * 
     *  @param msg The failure Message.
     */
    override protected function statusHandler(msg:IMessage):void
    {
        var cmd:CommandMessage = CommandMessage(message);
        
        if (Log.isDebug())
        {
            _log.debug("{1} failure: {0}", msg.toString(), 
                        cmd.operation == CommandMessage.LOGIN_OPERATION ? "Login" : "Logout");    
        }

        channel.mx_internal::authenticating = false;
        channel.mx_internal::setAuthenticated(false);

        if (agent != null && agent.hasPendingRequestForMessage(message))
        {
            agent.fault(ErrorMessage(msg), message);
        }
        else
        {
            var errMsg:ErrorMessage = ErrorMessage(msg);
            var channelFault:ChannelFaultEvent = 
                                        ChannelFaultEvent.createEvent(channel, false, 
                                        "Channel.Authentication.Error", "warn", 
                                        errMsg.faultString);
            channelFault.rootCause = errMsg;                        
            channel.dispatchEvent(channelFault);
        }
    }
}
