/// <summary>
        /// Read any incoming TorReply instances. Will block if no data is currently available and 'blocking' is set to 'true'
        /// </summary>
        /// <param name="blocking">When set to true, will block when no data is available. When false, it'll return an empty array in when no data is available.</param>
        /// <returns>An array of TorReply instances.</returns>
        public TorReply[] Read(bool blocking)
        {
            if (_socket == null || !_socket.IsBound)
            {
                throw new InvalidOperationException("Not connected.");
            }

            if (!blocking && !_socket.IsDataAvailable())
            {
                return new TorReply[0];
            }

            var replies = new List<TorReply>();

            while (true)
            {
                string line = _reader.ReadLine();

                var torReply = new TorReply(line, replies.Count > 0 && replies[0].Type == CommandReplyType.MultiLineValue);

                // Notification - trigger the event if registered
                if (torReply.Type == CommandReplyType.Notification)
                {
                    if (OnNotification != null)
                    {
                        OnNotification(this, torReply);
                    }

                    continue;
                }

                // Add the reply to the list
                replies.Add(torReply);

                // If we receive a 'Status' reply, we're done receiving
                if (torReply.Type == CommandReplyType.Status)
                {
                    return replies.ToArray();
                }
            }
        }
        /// <summary>
        /// Connect and authenticate using the specified passwords. Throws if 
        /// <remarks>Throws an exception if connecting or authentication failed.</remarks>
        /// </summary>
        /// <param name="password"></param>
        public bool Connect(string password)
        {
            try
            {
                if (_socket == null || !_socket.IsBound)
                {
                    _socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                    _socket.Connect(Address, Port);
                    _socket.Send((byte[])new AuthenticateCommand(password));
                    _stream = new NetworkStream(_socket, FileAccess.ReadWrite, false);
                    _reader = new StreamReader(_stream, Encoding.ASCII);

                    var reply = new TorReply(_reader.ReadLine(), false);

                    if (reply.Code != 250 && reply.Code != 251) // Not 'Ok' or 'Not Needed'
                    {
                        throw new ConnectFailedException(reply, "Unable to authenticate.");
                    }

                    // Success
                    return true;
                }
            }
            catch
            {
                // If we have a socket
                if (_socket != null)
                {
                    try
                    {
                        // Attempt to close it
                        _socket.Close();
                    }
                    catch
                    {
                        // Ignore any exception as it might already be closed
                    }

                    // Unset the field
                    _socket = null;
                }

                throw;
            }

            return false;
        }
 /// <summary>
 /// Initialize a new ConnectFailedException instance.
 /// </summary>
 public ConnectFailedException(TorReply reply, string message)
     : base(message)
 {
     Reply = reply;
 }
 /// <summary>
 /// Initialize a new ConnectFailedException instance.
 /// </summary>
 public ConnectFailedException(TorReply reply, string message, Exception innerException)
     : base(message, innerException)
 {
     Reply = reply;
 }
 /// <summary>
 /// Initialize a new ConnectFailedException instance.
 /// </summary>
 public ConnectFailedException(TorReply reply)
 {
     Reply = reply;
 }