/// <summary>
        /// Release resources.
        /// </summary>
        /// <param name = "disposing">
        /// If disposing equals true, Managed and unmanaged resources are disposed. if false, Only unmanaged resources
        /// can be disposed.
        /// </param>
        protected virtual void Dispose(bool disposing)
        {
            if (!this.disposed)
            {
                // If disposing equals true, dispose all managed and unmanaged resources.
                if (disposing)
                {
                    // Free managed resources & other reference types:
                    if (this.transportStack != null)
                    {
                        this.transportStack.Dispose();
                        this.transportStack = null;
                    }
                    if (this.security != null)
                    {
                        this.security.Dispose();
                        this.security = null;
                    }
                    this.config  = null;
                    this.encoder = null;
                    this.decoder = null;
                }

                // Call the appropriate methods to clean up unmanaged resources.
                // If disposing is false, only the following code is executed:

                this.disposed = true;
            }
        }
        /// <summary>
        /// Release resources. 
        /// </summary>
        /// <param name = "disposing">
        /// If disposing equals true, Managed and unmanaged resources are disposed. if false, Only unmanaged resources 
        /// can be disposed. 
        /// </param>
        protected virtual void Dispose(bool disposing)
        {
            if (!this.disposed)
            {
                // If disposing equals true, dispose all managed and unmanaged resources.
                if (disposing)
                {
                    // Free managed resources & other reference types:
                    if (this.transportStack != null)
                    {
                        this.transportStack.Dispose();
                        this.transportStack = null;
                    }
                    if (this.security != null)
                    {
                        this.security.Dispose();
                        this.security = null;
                    }
                    this.config = null;
                    this.encoder = null;
                    this.decoder = null;
                }

                // Call the appropriate methods to clean up unmanaged resources.
                // If disposing is false, only the following code is executed:

                this.disposed = true;
            }
        }
        /// <summary>
        /// Connects to server.
        /// </summary>
        /// <param name="config">Transport configurations.</param>
        /// <exception cref="InvalidOperationException">
        /// thrown when TransportConifg is null!
        /// </exception>
        /// <exception cref="NotSupportedException">
        /// thrown when TransportConfig is not SocketTransportConfig,
        /// ADTS-LDAP supports socket transport only!
        /// </exception>
        /// <exception cref="NotSupportedException">
        /// thrown when Type of TransportConfig is not TCP/UDP.
        /// Only TCP and UDP are supported for StackTransportType
        /// </exception>
        public virtual void Connect()
        {
            if (this.config == null)
            {
                throw new InvalidOperationException("TransportConfig is null!");
            }

            SocketTransportConfig socketConfig = this.config as SocketTransportConfig;
            if (socketConfig == null)
            {
                throw new NotSupportedException("ADTS-LDAP supports socket transport only!");
            }

            // initialize IsTcp.
            if (socketConfig.Type == StackTransportType.Tcp)
            {
                this.isTcp = true;
            }
            else if (socketConfig.Type == StackTransportType.Udp)
            {
                this.isTcp = false;
            }
            else
            {
                throw new NotSupportedException("Only TCP and UDP are supported for StackTransportType");
            }

            // initialize context.
            if (this.context == null)
            {
                IPEndPoint remoteAddress = new IPEndPoint(socketConfig.RemoteIpAddress, socketConfig.RemoteIpPort);
                this.context = new AdtsLdapContext(ldapVersion, remoteAddress);
            }

            // initialize decorder.
            if (this.decoder == null)
            {
                this.decoder = new AdtsLdapClientDecoder(this);
            }

            // initialize transport stack.
            if (this.transportStack == null)
            {
                this.transportStack = new TransportStack(config, this.decoder.DecodeLdapPacketCallBack);
            }

            #region Transport Connect

            // TCP and UDP differs here. Connect method cannot be used for UDP connections.
            if (this.isTcp)
            {
                this.transportStack.Connect();
            }
            else
            {
                this.transportStack.Start();
            }

            #endregion
        }
        /// <summary>
        /// Connects to server.
        /// </summary>
        /// <param name="config">Transport configurations.</param>
        /// <exception cref="InvalidOperationException">
        /// thrown when TransportConifg is null!
        /// </exception>
        /// <exception cref="NotSupportedException">
        /// thrown when TransportConfig is not SocketTransportConfig,
        /// ADTS-LDAP supports socket transport only!
        /// </exception>
        /// <exception cref="NotSupportedException">
        /// thrown when Type of TransportConfig is not TCP/UDP.
        /// Only TCP and UDP are supported for StackTransportType
        /// </exception>
        public virtual void Connect()
        {
            if (this.config == null)
            {
                throw new InvalidOperationException("TransportConfig is null!");
            }

            SocketTransportConfig socketConfig = this.config as SocketTransportConfig;

            if (socketConfig == null)
            {
                throw new NotSupportedException("ADTS-LDAP supports socket transport only!");
            }

            // initialize IsTcp.
            if (socketConfig.Type == StackTransportType.Tcp)
            {
                this.isTcp = true;
            }
            else if (socketConfig.Type == StackTransportType.Udp)
            {
                this.isTcp = false;
            }
            else
            {
                throw new NotSupportedException("Only TCP and UDP are supported for StackTransportType");
            }

            // initialize context.
            if (this.context == null)
            {
                IPEndPoint remoteAddress = new IPEndPoint(socketConfig.RemoteIpAddress, socketConfig.RemoteIpPort);
                this.context = new AdtsLdapContext(ldapVersion, remoteAddress);
            }

            // initialize decorder.
            if (this.decoder == null)
            {
                this.decoder = new AdtsLdapClientDecoder(this);
            }

            // initialize transport stack.
            if (this.transportStack == null)
            {
                this.transportStack = new TransportStack(config, this.decoder.DecodeLdapPacketCallBack);
            }

            #region Transport Connect

            // TCP and UDP differs here. Connect method cannot be used for UDP connections.
            if (this.isTcp)
            {
                this.transportStack.Connect();
            }
            else
            {
                this.transportStack.Start();
            }

            #endregion
        }