//// <summary>
		/// Reads line by line from the asterisk server, sets the protocol identifier as soon as it is
		/// received and dispatches the received events and responses via the associated dispatcher.
		/// </summary>
		/// <seealso cref="ManagerConnection.DispatchEvent(ManagerEvent)" />
		/// <seealso cref="ManagerConnection.DispatchResponse(Response.ManagerResponse)" />
		/// <seealso cref="ManagerConnection.setProtocolIdentifier(String)" />
		internal void Run()
		{
			if (mrSocket == null)
				throw new SystemException("Unable to run: socket is null.");

			string line;

			while (true)
			{
				try
				{
					while (!die)
					{
						#region check line from *

						if (!is_logoff)
						{
							if (mrSocket != null && mrSocket.Initial)
							{
								Reinitialize();
							}
							else if (disconnect)
							{
								disconnect = false;
								mrConnector.DispatchEvent(new DisconnectEvent(mrConnector));
							}
						}
						if (lineQueue.Count == 0)
						{
							if (lastPacketTime.AddMilliseconds(mrConnector.PingInterval) < DateTime.Now
								&& mrConnector.PingInterval > 0
								&& mrSocket != null
								&& !wait4identiier
								&& !is_logoff
								)
							{
								if (pingHandler != null)
								{
									if (pingHandler.Response == null)
									{
										// If one PingInterval from Ping without Pong then send Disconnect event
										mrConnector.RemoveResponseHandler(pingHandler);
										mrConnector.DispatchEvent(new DisconnectEvent(mrConnector));
									}
									pingHandler.Free();
									pingHandler = null;
								}
								else
								{
									// Send PING to *
									try
									{
										pingHandler = new ResponseHandler(new PingAction(), null);
										mrConnector.SendAction(pingHandler.Action, pingHandler);
									}
									catch
									{
										disconnect = true;
										mrSocket = null;
									}
								}
								lastPacketTime = DateTime.Now;
							}
							Thread.Sleep(50);

							continue;
						}

						#endregion

						lastPacketTime = DateTime.Now;
						lock (((ICollection) lineQueue).SyncRoot)
							line = lineQueue.Dequeue().Trim();
#if LOGGER
						logger.Debug(line);
#endif

						#region processing Response: Follows

						if (processingCommandResult)
						{
							if (line == "--END COMMAND--")
							{
								var commandResponse = new CommandResponse();
								Helper.SetAttributes(commandResponse, packet);
								commandResponse.Result = commandList;
								processingCommandResult = false;
								packet.Clear();
								mrConnector.DispatchResponse(commandResponse);
							}
							string lineLower = line.ToLower(Helper.CultureInfo);
							if (lineLower.StartsWith("privilege: ")
								|| lineLower.StartsWith("actionid: ")
								|| lineLower.StartsWith("timestamp: ")
								|| lineLower.StartsWith("server: ")
								)
								Helper.AddKeyValue(packet, line);
							else
								commandList.Add(line);
							continue;
						}

						#endregion

						#region collect key: value and ProtocolIdentifier

						if (!string.IsNullOrEmpty(line))
						{
							if (wait4identiier && line.StartsWith("Asterisk Call Manager"))
							{
								wait4identiier = false;
								var connectEvent = new ConnectEvent(mrConnector);
								connectEvent.ProtocolIdentifier = line;
								mrConnector.DispatchEvent(connectEvent);
								continue;
							}
							if (line.Trim().ToLower(Helper.CultureInfo) == "response: follows")
							{
								// Switch to wait "--END COMMAND--" mode
								processingCommandResult = true;
								packet.Clear();
								commandList.Clear();
								Helper.AddKeyValue(packet, line);
								continue;
							}
							Helper.AddKeyValue(packet, line);
							continue;
						}

						#endregion

						#region process events and responses

						if (packet.ContainsKey("event"))
							mrConnector.DispatchEvent(packet);

						else if (packet.ContainsKey("response"))
							mrConnector.DispatchResponse(packet);

						#endregion

						packet.Clear();
					}
					if (mrSocket != null)
						mrSocket.Close();
					break;
				}
#if LOGGER
				catch (Exception ex)
				{
					logger.Info("Exception : {0}", ex.Message);
#else
				catch
				{
#endif
				}

				if (die)
					break;

#if LOGGER
				logger.Info("No die, any error - send disconnect.");
#endif
				mrConnector.DispatchEvent(new DisconnectEvent(mrConnector));
			}
		}
		public int SendAction(ManagerAction action, ResponseHandler responseHandler)
		{
			if (action == null)
				throw new ArgumentException("Unable to send action: action is null.");

			if (mrSocket == null)
				throw new SystemException("Unable to send " + action.Action + " action: not connected.");

			// if the responseHandler is null the user is obviously not interested in the response, thats fine.
			string internalActionId = string.Empty;
			if (responseHandler != null)
			{
				internalActionId = createInternalActionId();
				responseHandler.Hash = internalActionId.GetHashCode();
				AddResponseHandler(responseHandler);
			}

			SendToAsterisk(action, internalActionId);

			return responseHandler != null ? responseHandler.Hash : 0;
		}
		/// <summary>
		/// Send action ans with timeout (milliseconds)
		/// </summary>
		/// <param name="action">action to send</param>
		/// <param name="timeout">timeout in milliseconds</param>
		/// <returns></returns>
		public Response.ManagerResponse SendAction(ManagerAction action, int timeOut)
		{
			AutoResetEvent autoEvent = new AutoResetEvent(false);
			ResponseHandler handler = new ResponseHandler(action, autoEvent);

			int hash = SendAction(action, handler);
			bool result = autoEvent.WaitOne(timeOut <= 0 ? -1 : timeOut, true);

			RemoveResponseHandler(handler);

			if (result)
				return handler.Response;
			throw new TimeoutException("Timeout waiting for response to " + action.Action);
		}
        //// <summary>
        /// Reads line by line from the asterisk server, sets the protocol identifier as soon as it is
        /// received and dispatches the received events and responses via the associated dispatcher.
        /// </summary>
        /// <seealso cref="ManagerConnection.DispatchEvent(ManagerEvent)" />
        /// <seealso cref="ManagerConnection.DispatchResponse(Response.ManagerResponse)" />
        /// <seealso cref="ManagerConnection.setProtocolIdentifier(String)" />
        internal void Run()
        {
            if (mrSocket == null)
            {
                throw new SystemException("Unable to run: socket is null.");
            }

            string line;

            while (true)
            {
                try
                {
                    while (!die)
                    {
                        #region check line from *

                        if (!is_logoff)
                        {
                            if (mrSocket != null && mrSocket.Initial)
                            {
                                Reinitialize();
                            }
                            else if (disconnect)
                            {
                                disconnect = false;
                                mrConnector.DispatchEvent(new DisconnectEvent(mrConnector));
                            }
                        }
                        if (lineQueue.Count == 0)
                        {
                            if (lastPacketTime.AddMilliseconds(mrConnector.PingInterval) < DateTime.Now &&
                                mrConnector.PingInterval > 0 &&
                                mrSocket != null &&
                                !wait4identiier &&
                                !is_logoff
                                )
                            {
                                if (pingHandler != null)
                                {
                                    if (pingHandler.Response == null)
                                    {
                                        // If one PingInterval from Ping without Pong then send Disconnect event
                                        mrConnector.RemoveResponseHandler(pingHandler);
                                        mrConnector.DispatchEvent(new DisconnectEvent(mrConnector));
                                    }
                                    pingHandler.Free();
                                    pingHandler = null;
                                }
                                else
                                {
                                    // Send PING to *
                                    try
                                    {
                                        pingHandler = new ResponseHandler(new PingAction(), null);
                                        mrConnector.SendAction(pingHandler.Action, pingHandler);
                                    }
                                    catch
                                    {
                                        disconnect = true;
                                        mrSocket   = null;
                                    }
                                }
                                lastPacketTime = DateTime.Now;
                            }
                            Thread.Sleep(50);

                            continue;
                        }

                        #endregion

                        lastPacketTime = DateTime.Now;
                        lock (((ICollection)lineQueue).SyncRoot)
                            line = lineQueue.Dequeue().Trim();
#if LOGGER
                        logger.Debug(line);
#endif

                        #region processing Response: Follows

                        if (processingCommandResult)
                        {
                            if (line == "--END COMMAND--")
                            {
                                var commandResponse = new CommandResponse();
                                Helper.SetAttributes(commandResponse, packet);
                                commandResponse.Result  = commandList;
                                processingCommandResult = false;
                                packet.Clear();
                                mrConnector.DispatchResponse(commandResponse);
                            }
                            string lineLower = line.ToLower(Helper.CultureInfo);
                            if (lineLower.StartsWith("privilege: ") ||
                                lineLower.StartsWith("actionid: ") ||
                                lineLower.StartsWith("timestamp: ") ||
                                lineLower.StartsWith("server: ")
                                )
                            {
                                Helper.AddKeyValue(packet, line);
                            }
                            else
                            {
                                commandList.Add(line);
                            }
                            continue;
                        }

                        #endregion

                        #region collect key: value and ProtocolIdentifier

                        if (!string.IsNullOrEmpty(line))
                        {
                            if (wait4identiier && line.StartsWith("Asterisk Call Manager"))
                            {
                                wait4identiier = false;
                                var connectEvent = new ConnectEvent(mrConnector);
                                connectEvent.ProtocolIdentifier = line;
                                mrConnector.DispatchEvent(connectEvent);
                                continue;
                            }
                            if (line.Trim().ToLower(Helper.CultureInfo) == "response: follows")
                            {
                                // Switch to wait "--END COMMAND--" mode
                                processingCommandResult = true;
                                packet.Clear();
                                commandList.Clear();
                                Helper.AddKeyValue(packet, line);
                                continue;
                            }
                            Helper.AddKeyValue(packet, line);
                            continue;
                        }

                        #endregion

                        #region process events and responses

                        if (packet.ContainsKey("event"))
                        {
                            mrConnector.DispatchEvent(packet);
                        }

                        else if (packet.ContainsKey("response"))
                        {
                            mrConnector.DispatchResponse(packet);
                        }

                        #endregion

                        packet.Clear();
                    }
                    if (mrSocket != null)
                    {
                        mrSocket.Close();
                    }
                    break;
                }
#if LOGGER
                catch (Exception ex)
                {
                    logger.Info("Exception : {0}", ex.Message);
#else
                catch
                {
#endif
                }

                if (die)
                {
                    break;
                }

#if LOGGER
                logger.Info("No die, any error - send disconnect.");
#endif
                mrConnector.DispatchEvent(new DisconnectEvent(mrConnector));
            }
        }