private IConnection OpenConnection(ConnectionKey key, RabbitMQUri uri, IProtocol protocol)
        {
            ConnectionFactory connFactory = new ConnectionFactory
                {
                    HostName = key.Host,
                    Port = key.Port,
                    Protocol = protocol
                };

            if (uri.Username != null)
            {
                connFactory.UserName = uri.Username;
            }
            if (uri.Password != null)
            {
                connFactory.Password = uri.Password;
            }
            if (uri.VirtualHost != null)
            {
                connFactory.VirtualHost = uri.VirtualHost;
            }

            IConnection connection = connFactory.CreateConnection();

            connection.ConnectionShutdown += OnConnectionShutdown;

            return connection;
        }
        public override void Open(TimeSpan timeout)
        {
            if (State != CommunicationState.Created && State != CommunicationState.Closed)
                throw new InvalidOperationException(string.Format("Cannot open the channel from the {0} state.",
                                                                  base.State));

            OnOpening();
            #if VERBOSE
            DebugHelper.Start();
            #endif
            RabbitMQUri uri = new RabbitMQUri(LocalAddress.Uri);

            m_model = ConnectionManager.Instance.OpenModel(uri, m_bindingElement.BrokerProtocol, timeout);

            string queue = uri.Endpoint;

            IDictionary args = new Dictionary<String, Object>();

            int ttl;
            if (!string.IsNullOrEmpty(m_bindingElement.TTL) && int.TryParse(m_bindingElement.TTL, out ttl))
            {
                args.Add("x-message-ttl", ttl);
            }

            //Create a queue for messages destined to this service, bind it to the service URI routing key
            queue = m_model.QueueDeclare(queue, true, false, m_autoDelete, args);

            if (!string.IsNullOrEmpty(m_bindToExchange))
            {
                m_model.QueueBind(queue, m_bindToExchange, uri.RoutingKey);
            }

            QueueingBasicConsumerBase queueingBasicConsumer;

            // Create queue
            if (m_bindingElement.TransactedReceiveEnabled)
            {
                queueingBasicConsumer = new TransactionalQueueConsumer(m_model);
            }
            else
            {
                queueingBasicConsumer = new QueueingBasicConsumer(m_model);
            }

            m_messageQueue = queueingBasicConsumer;

            //Listen to the queue
            bool noAck = !m_bindingElement.TransactedReceiveEnabled;

            m_model.BasicConsume(queue, noAck, queueingBasicConsumer);

            #if VERBOSE
            DebugHelper.Stop(" ## In.Channel.Open {{\n\tAddress={1}, \n\tTime={0}ms}}.", LocalAddress.Uri.PathAndQuery);
            #endif
            OnOpened();
        }
        public IModel OpenModel(RabbitMQUri uri, IProtocol protocol, TimeSpan timeout)
        {
            string host = uri.Host;
            int port = uri.Port.HasValue ? uri.Port.Value : protocol.DefaultPort;

            ConnectionKey key = new ConnectionKey(host, port);

            lock (m_connections)
            {
                IConnection connection;

                if (m_connections.ContainsKey(key))
                {
                    connection = m_connections[key];
                }
                else
                {
                    connection = OpenConnection(key, uri, protocol);

                    m_connections.Add(key, connection);
                }

                IModel model = connection.CreateModel();

                connection.AutoClose = true;

                return model;
            }
        }
        public override void Send(Message message, TimeSpan timeout)
        {
            if (State == CommunicationState.Opened && !message.IsFault)
            {
            #if VERBOSE
                DebugHelper.Start();
            #endif
                byte[] body;

                IBasicProperties basicProperties = m_model.CreateBasicProperties();

                // Set message properties
                basicProperties.Timestamp = new AmqpTimestamp(DateTime.Now);
                basicProperties.ContentType = "SOAP";
                basicProperties.DeliveryMode = m_bindingElement.PersistentDelivery ? (byte)2 : (byte)1;
                if (!string.IsNullOrEmpty(m_bindingElement.TTL))
                {
                    basicProperties.Expiration = m_bindingElement.TTL;
                }

                // TODO: read custom headers and put it into the message properties
                //foreach (MessageHeaderInfo messageHeaderInfo in message.Headers)
                //{
                //    basicProperties.Headers.Add(messageHeaderInfo.Name, "");
                //}

                if (m_bindingElement.ReplyToExchange != null)
                {
                    message.Headers.ReplyTo = new EndpointAddress(m_bindingElement.ReplyToExchange);
                }

                using (MemoryStream str = new MemoryStream())
                {
                    m_encoder.WriteMessage(message, str);
                    body = str.ToArray();
                }

                RabbitMQUri uri = new RabbitMQUri(RemoteAddress.Uri);

                m_model.BasicPublish(uri.Endpoint,
                                     uri.RoutingKey,
                                     basicProperties,
                                     body);

            #if VERBOSE
                DebugHelper.Stop(" #### Message.Send {{\n\tAction={2}, \n\tBytes={1}, \n\tTime={0}ms}}.",
                    body.Length,
                    message.Headers.Action.Remove(0, message.Headers.Action.LastIndexOf('/')));
            #endif
            }
        }