public override void Send(
            ITransportListener listener,
            IList <IMutableMessage> messages,
            int requestTimeout = 1200)
        {
            //Console.WriteLine();
            //Console.WriteLine("send({0} message(s))", messages.Count);
            var url = Url;

            if (_appendMessageType && messages.Count == 1 && messages[0].Meta)
            {
                var type = messages[0].Channel.Substring(ChannelFields.META.Length);
                if (url.EndsWith("/"))
                {
                    url = url.Substring(0, url.Length - 1);
                }

                url += type;
            }

            var request = (HttpWebRequest)WebRequest.Create(url);

            request.Method      = "POST";
            request.ContentType = "application/json;charset=UTF-8";

            if (request.CookieContainer == null)
            {
                request.CookieContainer = new CookieContainer();
            }

            request.CookieContainer.Add(GetCookieCollection());

            if (request.Headers == null)
            {
                request.Headers = new WebHeaderCollection();
            }

            request.Headers.Add(GetHeaderCollection());

            var content = JsonConvert.SerializeObject(ObjectConverter.ToListOfDictionary(messages));

            _logger?.LogDebug($"Send: {content}");

            var longPollingRequest = new LongPollingRequest(listener, messages, request, requestTimeout);

            var exchange = new TransportExchange(this, listener, messages, longPollingRequest)
            {
                Content = content,
                Request = request
            };

            lock (this)
            {
                _exchanges.Add(exchange);
            }

            longPollingRequest.Exchange = exchange;
            AddRequest(longPollingRequest);
        }
        // From http://msdn.microsoft.com/en-us/library/system.net.httpwebrequest.begingetrequeststream.aspx
        private static void GetRequestStreamCallback(IAsyncResult asynchronousResult)
        {
            TransportExchange exchange = (TransportExchange)asynchronousResult.AsyncState;

            try
            {
                // End the operation
                using (Stream postStream = exchange.request.EndGetRequestStream(asynchronousResult))
                {
                    // Convert the string into a byte array.
                    byte[] byteArray = Encoding.UTF8.GetBytes(exchange.content);
                    //Console.WriteLine("Sending message(s): {0}", exchange.content);

                    // Write to the request stream.
                    postStream.Write(byteArray, 0, exchange.content.Length);
                    postStream.Close();
                }

                // Start the asynchronous operation to get the response
                exchange.listener.onSending(ObjectConverter.ToListOfIMessage(exchange.messages));
#if !SILVERLIGHT
                IAsyncResult result = (IAsyncResult)exchange.request.BeginGetResponse(new AsyncCallback(GetResponseCallback), exchange);

                long timeout = 120000;
                ThreadPool.RegisterWaitForSingleObject(result.AsyncWaitHandle, new WaitOrTimerCallback(TimeoutCallback), exchange, timeout, true);
#endif
#if SILVERLIGHT
                AutoResetEvent are = new AutoResetEvent(false);
                exchange.request.BeginGetResponse(new AsyncCallback(asyncResult =>
                {
                    are.Set();
                    GetResponseCallback(asyncResult);
                }), exchange);
                are.WaitOne();
#endif
                exchange.isSending = false;
            }
            catch (Exception e)
            {
                if (exchange.request != null)
                {
                    try
                    {
                        exchange.request.Abort();
                    }
                    catch (ObjectDisposedException) { }
                }
                exchange.Dispose();
                exchange.listener.onException(e, ObjectConverter.ToListOfIMessage(exchange.messages));
            }
        }
        public override void send(ITransportListener listener, IList <IMutableMessage> messages)
        {
            //Console.WriteLine();
            //Console.WriteLine("send({0} message(s))", messages.Count);
            String url = getURL();

            if (_appendMessageType && messages.Count == 1 && messages[0].Meta)
            {
                String type = messages[0].Channel.Substring(Channel_Fields.META.Length);
                if (url.EndsWith("/"))
                {
                    url = url.Substring(0, url.Length - 1);
                }
                url += type;
            }

            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);

            request.Method      = "POST";
            request.ContentType = "application/json;charset=UTF-8";

#if !SILVERLIGHT
            if (request.CookieContainer == null)
            {
                request.CookieContainer = new CookieContainer();
            }
            request.CookieContainer.Add(getCookieCollection());
#endif

#if !SILVERLIGHT
            JavaScriptSerializer jsonParser = new JavaScriptSerializer();
            String content = jsonParser.Serialize(ObjectConverter.ToListOfDictionary(messages));
#endif

#if SILVERLIGHT
            String content = JsonConvert.SerializeObject(ObjectConverter.ToListOfDictionary(messages));
#endif

            LongPollingRequest longPollingRequest = new LongPollingRequest(listener, messages, request);

            TransportExchange exchange = new TransportExchange(this, listener, messages, longPollingRequest);
            exchange.content = content;
            exchange.request = request;
            lock (this)
            {
                _exchanges.Add(exchange);
            }

            longPollingRequest.exchange = exchange;
            addRequest(longPollingRequest);
        }
        // From http://msdn.microsoft.com/en-us/library/system.net.httpwebrequest.begingetresponse.aspx
        // Abort the request if the timer fires.
        private static void TimeoutCallback(object state, bool timedOut)
        {
            if (timedOut)
            {
                Console.WriteLine("Timeout");
                TransportExchange exchange = state as TransportExchange;

                if (exchange.request != null)
                {
                    exchange.request.Abort();
                }
                exchange.Dispose();
            }
        }
        private static void GetResponseCallback(IAsyncResult asynchronousResult)
        {
            TransportExchange exchange = (TransportExchange)asynchronousResult.AsyncState;

            try
            {
                // End the operation
                string responseString;

                using (HttpWebResponse response = (HttpWebResponse)exchange.request.EndGetResponse(asynchronousResult))
                {
                    using (Stream streamResponse = response.GetResponseStream())
                    {
                        using (StreamReader streamRead = new StreamReader(streamResponse))
                            responseString = streamRead.ReadToEnd();
                    }

                    if (response.Cookies != null)
                    {
                        foreach (Cookie cookie in response.Cookies)
                        {
                            exchange.AddCookie(cookie);
                        }
                    }

                    response.Close();
                }
                exchange.messages = DictionaryMessage.parseMessages(responseString);

                exchange.listener.onMessages(exchange.messages);
                exchange.Dispose();
            }
            catch (Exception e)
            {
                if (!e.Message.Contains("operation has timed out")) // Supress timeout messages due to inactivity
                {
                    exchange.listener.onException(e, ObjectConverter.ToListOfIMessage(exchange.messages));
                }
                exchange.Dispose();
            }
        }
        private static void GetResponseCallback(IAsyncResult asynchronousResult)
        {
            TransportExchange exchange = (TransportExchange)asynchronousResult.AsyncState;

            try
            {
                // End the operation
                string responseString;
                using (HttpWebResponse response = (HttpWebResponse)exchange.request.EndGetResponse(asynchronousResult))
                {
                    using (Stream streamResponse = response.GetResponseStream())
                    {
                        using (StreamReader streamRead = new StreamReader(streamResponse))
                            responseString = streamRead.ReadToEnd();
                    }
                    //Console.WriteLine("Received message(s): {0}", responseString);

#if !SILVERLIGHT
                    if (response.Cookies != null)
                    {
                        foreach (Cookie cookie in response.Cookies)
                        {
                            exchange.AddCookie(cookie);
                        }
                    }
#endif
                    response.Close();
                }
                exchange.messages = DictionaryMessage.parseMessages(responseString);

                exchange.listener.onMessages(exchange.messages);
                exchange.Dispose();
            }
            catch (Exception e)
            {
                exchange.listener.onException(e, ObjectConverter.ToListOfIMessage(exchange.messages));
                exchange.Dispose();
            }
        }
        public override void send(ITransportListener listener, IList<IMutableMessage> messages)
        {
            //Console.WriteLine();
            //Console.WriteLine("send({0} message(s))", messages.Count);
            String url = getURL();

            if (_appendMessageType && messages.Count == 1 && messages[0].Meta)
            {
                String type = messages[0].Channel.Substring(Channel_Fields.META.Length);
                if (url.EndsWith("/"))
                    url = url.Substring(0, url.Length - 1);
                url += type;
            }

            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
            request.Method = "POST";
            request.ContentType = "application/json;charset=UTF-8";

            if (request.CookieContainer == null)
                request.CookieContainer = new CookieContainer();
            request.CookieContainer.Add(getCookieCollection());

            JavaScriptSerializer jsonParser = new JavaScriptSerializer();
            String content = jsonParser.Serialize(ObjectConverter.ToListOfDictionary(messages));

            LongPollingRequest longPollingRequest = new LongPollingRequest(listener, messages, request);

            TransportExchange exchange = new TransportExchange(this, listener, messages, longPollingRequest);
            exchange.content = content;
            exchange.request = request;
            lock (this)
            {
                _exchanges.Add(exchange);
            }

            longPollingRequest.exchange = exchange;
            addRequest(longPollingRequest);
        }