/// <summary>
		/// Removes a specified HTTP request from the requests queue (when it is completed).
		/// </summary>
		public virtual bool RemoveRequest(LongPollingRequest exchange)
		{
			if (null != exchange)
			{
				lock (_exchanges)
				{
					if (!_aborted)
						return _exchanges.Remove(exchange);
					// DEBUG
					//Debug.Print("The HTTP request was removed; Exchanges count: {0}", _exchanges.Count);
				}
			}

			return false;
		}
Exemple #2
0
        /// <summary>
        /// Removes a specified HTTP request from the requests queue (when it is completed).
        /// </summary>
        public virtual bool RemoveRequest(LongPollingRequest exchange)
        {
            if (null != exchange)
            {
                lock (_exchanges)
                {
                    if (!_aborted)
                    {
                        return(_exchanges.Remove(exchange));
                    }
                    // DEBUG
                    //Debug.Print("The HTTP request was removed; Exchanges count: {0}", _exchanges.Count);
                }
            }

            return(false);
        }
Exemple #3
0
        /// <summary>
        /// Abort the request if the timer fires.
        /// </summary>
        private static void TimeoutCallback(object state, bool timedOut)
        {
            if (timedOut)
            {
                // DEBUG
                logger.Warn("HTTP Web request Timeout detected!");

                LongPollingRequest exchange = state as LongPollingRequest;
                if (exchange != null)
                {
                    exchange.Abort();

                    if (null != exchange._listener)
                    {
                        exchange._listener.OnExpire(exchange._messages);
                    }
                }
            }
        }
		/// <summary>
		/// Sends the specified messages to a Bayeux server asynchronously.
		/// </summary>
		/// <param name="listener">The listener used to process the request response.</param>
		/// <param name="messages">The list of messages will be sent in one HTTP request.</param>
		public override void Send(ITransportListener listener, params IMutableMessage[] messages)
		{
			if (messages == null || messages.Length == 0 || messages[0] == null)
				throw new ArgumentNullException("messages");

			string url = this.Url;

			if (null == url) url = String.Empty;
			else url = url.Trim();

			// Builds the request URL based on the message channel name
			Match uriMatch = uriRegex.Match(url);
			if (uriMatch.Success)
			{
				string afterPath = (uriMatch.Groups.Count > 7) ? uriMatch.Groups[7].Value : null;
				// Append message type into the URL ?
				if ((afterPath == null || afterPath.Trim().Length == 0)
					&& messages.Length == 1 && messages[0].IsMeta)
				{
					string type = messages[0].Channel.Substring(Channel.Meta.Length);
					url = url.TrimEnd('\\', '/') + "/" + type.Trim('\\', '/');
				}
			}

			try
			{
				// Creates a new HttpWebRequest object
				HttpWebRequest request = WebRequest.Create(new Uri(url, UriKind.RelativeOrAbsolute)) as HttpWebRequest;
				request.Method = WebRequestMethods.Http.Post;
				request.Accept = "application/json";
				request.ContentType = request.Accept + ";charset=" + Encoding.UTF8.WebName;
				request.KeepAlive = true;
				request.AllowWriteStreamBuffering = true;	// Is needed for KeepAlive
				request.AllowAutoRedirect = true;
				request.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;
				request.Proxy = null;	// Skips the proxy auto-detect step (~ 7s)

				// Setups HTTP request headers
				this.ApplyRequestHeaders(request);

				// Setups HTTP request cookies
				this.ApplyRequestCookies(request);

				// Calculates the HTTP request timeout (in milliseconds)
				int maxNetworkDelay = this.GetOption<int>(MaxNetworkDelayOption, request.Timeout);
				if (messages.Length == 1
					&& Channel.MetaConnect.Equals(messages[0].Channel, StringComparison.OrdinalIgnoreCase))
				{
					IDictionary<string, object> advice = messages[0].Advice;
					if (advice == null)
						advice = _advice;

					object val;
					if (advice != null && advice.TryGetValue(Message.TimeoutField, out val))
					{
						long timeout = ObjectConverter.ToPrimitive<long>(val, 0);
						if (timeout != 0)
							maxNetworkDelay += unchecked((int)timeout);
					}
				}
				request.Timeout = maxNetworkDelay;

				//if (null != _customize) _customize(request);

				// Creates a new HTTP Transport Exchange
				LongPollingRequest httpExchange;
				lock (_exchanges)
				{
					if (_aborted)
						throw new InvalidOperationException("The client transport has been aborted.");

					httpExchange = new LongPollingRequest(this, request, listener, messages);
					_exchanges.Add(httpExchange);
				}

				// Processes the HTTP request
				httpExchange.Send();
			}
			catch (Exception ex)
			{
				if (listener != null)
					listener.OnException(ex, messages);
				else
				{
					// DEBUG
					Trace.TraceError("Failed to send messages:{0}{1}{0}--- via transport: {2}{0}{3}",
						Environment.NewLine, ObjectConverter.Serialize(messages), this.ToString(), ex.ToString());
				}
			}
		}
Exemple #5
0
        private static void GetResponseCallback(IAsyncResult asyncResult)
        {
            LongPollingRequest exchange = asyncResult.AsyncState as LongPollingRequest;

            try
            {
                string         responseString;
                HttpStatusCode responseStatus;

                // End the operation
                HttpWebResponse response;
                Exception       error = null;
                try
                {
                    response = exchange._request.EndGetResponse(asyncResult) as HttpWebResponse;
                }
                catch (WebException wex)
                {
                    if (wex.Status == WebExceptionStatus.RequestCanceled)
                    {
                        throw;
                    }

                    response = wex.Response as HttpWebResponse;
                    if (null == response)
                    {
                        throw;
                    }

                    error = wex;
                }

                using (response)
                {
                    responseStatus = response.StatusCode;

                    using (StreamReader streamRead = new StreamReader(response.GetResponseStream(), Encoding.UTF8, true))
                    {
                        responseString = streamRead.ReadToEnd();
                        // DEBUG
                        if (logger.IsDebugEnabled)
                        {
                            logger.DebugFormat(CultureInfo.InvariantCulture, "Received message(s): {0}", responseString);
                        }
                    }

                    // Stores the transport Cookies to use for next requests
                    if (response.Cookies != null && response.Cookies.Count > 0)
                    {
                        foreach (Cookie cookie in response.Cookies)
                        {
                            if (null != cookie && (!cookie.Discard || !cookie.Expired))
                            {
                                exchange._transport.SetCookie(cookie);
                            }
                        }
                    }
                }

                if (responseStatus != HttpStatusCode.OK)                // TODO: error != null
                {
                    if (null != exchange._listener)
                    {
                        exchange._listener.OnProtocolError(String.Format(CultureInfo.InvariantCulture,
                                                                         "Unexpected response {0}: {1}", (int)responseStatus, responseString), error, exchange._messages);
                    }
                    else
                    {
                        // DEBUG
                        logger.Error(String.Format(CultureInfo.InvariantCulture,
                                                   "Unexpected response {0}: {1}", (int)responseStatus, responseString), error);
                    }
                }
                else if (responseString != null && (responseString = responseString.Trim()).Length > 0)
                {
                    // TODO: responseString.Replace('"', '\'')
                    IList <IMutableMessage> messages = DictionaryMessage.ParseMessages(responseString);

                    // Backups the transport Timeout value (in milliseconds) to use for next requests
                    foreach (IMutableMessage message in messages)
                    {
                        if (message != null &&
                            message.IsSuccessful &&
                            Channel.MetaConnect.Equals(message.Channel, StringComparison.OrdinalIgnoreCase))
                        {
                            IDictionary <string, object> advice = message.Advice;
                            object timeout;
                            if (advice != null &&
                                advice.TryGetValue(Message.TimeoutField, out timeout) &&
                                timeout != null && timeout.ToString().Trim().Length > 0)
                            {
                                exchange._transport.Advice = advice;
                            }
                        }
                    }

                    if (null != exchange._listener)
                    {
                        // Fixes the received messages before processing
                        string requestChannel = null;
                        string requestUrl, baseUrl;
                        foreach (IMutableMessage msg in messages)
                        {
                            if (String.IsNullOrEmpty(msg.Channel))
                            {
                                if (null == requestChannel)
                                {
                                    requestUrl = exchange._request.RequestUri.ToString();                                    // Absolute request URI

                                    baseUrl = exchange._transport.Url;
                                    baseUrl = (null == baseUrl) ? String.Empty : baseUrl.Trim();

                                    if (requestUrl.StartsWith(baseUrl, StringComparison.OrdinalIgnoreCase))
                                    {
                                        requestChannel = requestUrl.Substring(baseUrl.Length).Trim('\\', '/');
                                        requestChannel = Channel.Meta.TrimEnd('\\', '/') + "/" + requestChannel;
                                    }
                                    else
                                    {
                                        requestChannel = String.Empty;
                                    }
                                }

                                if (!String.IsNullOrEmpty(requestChannel))
                                {
                                    msg.Channel = requestChannel;
                                }
                            }
                        }

                        exchange._listener.OnMessages(messages);
                    }
                }
                else
                {
                    if (null != exchange._listener)
                    {
                        exchange._listener.OnProtocolError(String.Format(CultureInfo.InvariantCulture,
                                                                         "Empty response (204) from URL: {0}", exchange._request.RequestUri), null, exchange._messages);
                    }
                    else
                    {
                        // DEBUG
                        logger.ErrorFormat(CultureInfo.InvariantCulture, "Empty response (204) from URL: {0}", exchange._request.RequestUri);
                    }
                }
            }
            catch (Exception ex)
            {
                if (null != exchange._listener && !exchange._aborted)
                {
                    exchange._listener.OnException(ex, exchange._messages);
                }
                else
                {
                    logger.Error(ex);                    // DEBUG
                }
            }
            finally
            {
                exchange._isSending = false;
                exchange._transport.RemoveRequest(exchange);
            }
        }
Exemple #6
0
        // From http://msdn.microsoft.com/en-us/library/system.net.httpwebrequest.begingetrequeststream.aspx
        private static void GetRequestStreamCallback(IAsyncResult asyncResult)
        {
            LongPollingRequest exchange = asyncResult.AsyncState as LongPollingRequest;

            try
            {
                string content = ObjectConverter.Serialize(exchange._messages);
                // DEBUG
                //if (logger.IsDebugEnabled)
                //	logger.DebugFormat(CultureInfo.InvariantCulture, "Sending message(s): {0}", content);

                // Convert the string into a byte array
                byte[] buffer = Encoding.UTF8.GetBytes(content);

                // End the operation
                using (Stream postStream = exchange._request.EndGetRequestStream(asyncResult))
                {
                    // Write to the request stream
                    postStream.Write(buffer, 0, buffer.Length);
                }

                // On request committed
                if (null != exchange._listener)
                {
                    exchange._listener.OnSending(exchange._messages);
                }

                int exchangeTimeout = exchange._request.Timeout;
                // TODO: Restore request timeout (default: 100 seconds)
                //exchange._request.Timeout = exchange._transport.GetOption<int>(ClientTransport.MaxNetworkDelayOption, 100000);
                // DEBUG
                if (logger.IsDebugEnabled)
                {
                    logger.DebugFormat(CultureInfo.InvariantCulture,
                                       "Begin get response from URL: '{0}'  with exchange timeout: {1}",
                                       exchange._request.RequestUri, exchangeTimeout);
                }

                // Start the asynchronous operation to get the response
                IAsyncResult result = exchange._request.BeginGetResponse(new AsyncCallback(GetResponseCallback), exchange);

                // This line implements the timeout, if there is a timeout, the callback fires and the request becomes aborted
                ThreadPool.RegisterWaitForSingleObject(result.AsyncWaitHandle,
                                                       new WaitOrTimerCallback(TimeoutCallback), exchange, exchangeTimeout, true);
            }
            catch (Exception ex)
            {
                exchange._isSending = false;

                // TODO: OnConnectException
                if (null != exchange._listener && !exchange._aborted)
                {
                    exchange._listener.OnException(ex, exchange._messages);
                }
                else
                {
                    logger.Error(ex);                    // DEBUG
                }
                exchange._transport.RemoveRequest(exchange);
            }
        }
Exemple #7
0
        /// <summary>
        /// Sends the specified messages to a Bayeux server asynchronously.
        /// </summary>
        /// <param name="listener">The listener used to process the request response.</param>
        /// <param name="messages">The list of messages will be sent in one HTTP request.</param>
        public override void Send(ITransportListener listener, params IMutableMessage[] messages)
        {
            if (messages == null || messages.Length == 0 || messages[0] == null)
            {
                throw new ArgumentNullException("messages");
            }

            string url = this.Url;

            if (null == url)
            {
                url = String.Empty;
            }
            else
            {
                url = url.Trim();
            }

            // Builds the request URL based on the message channel name
            Match uriMatch = uriRegex.Match(url);

            if (uriMatch.Success)
            {
                string afterPath = (uriMatch.Groups.Count > 7) ? uriMatch.Groups[7].Value : null;
                // Append message type into the URL ?
                if ((afterPath == null || afterPath.Trim().Length == 0) &&
                    messages.Length == 1 && messages[0].IsMeta)
                {
                    string type = messages[0].Channel.Substring(Channel.Meta.Length);
                    url = url.TrimEnd('\\', '/') + "/" + type.Trim('\\', '/');
                }
            }

            try
            {
                // Creates a new HttpWebRequest object
                HttpWebRequest request = WebRequest.Create(new Uri(url, UriKind.RelativeOrAbsolute)) as HttpWebRequest;
                request.Method      = WebRequestMethods.Http.Post;
                request.Accept      = "application/json";
                request.ContentType = request.Accept + ";charset=" + Encoding.UTF8.WebName;
                request.KeepAlive   = true;
                request.AllowWriteStreamBuffering = true;                       // Is needed for KeepAlive
                request.AllowAutoRedirect         = true;
                request.AutomaticDecompression    = DecompressionMethods.GZip | DecompressionMethods.Deflate;
                request.Proxy = null;                   // Skips the proxy auto-detect step (~ 7s)

                // Setups HTTP request headers
                this.ApplyRequestHeaders(request);

                // Setups HTTP request cookies
                this.ApplyRequestCookies(request);

                // Calculates the HTTP request timeout (in milliseconds)
                int maxNetworkDelay = this.GetOption <int>(MaxNetworkDelayOption, request.Timeout);
                if (messages.Length == 1 &&
                    Channel.MetaConnect.Equals(messages[0].Channel, StringComparison.OrdinalIgnoreCase))
                {
                    IDictionary <string, object> advice = messages[0].Advice;
                    if (advice == null)
                    {
                        advice = _advice;
                    }

                    object val;
                    if (advice != null && advice.TryGetValue(Message.TimeoutField, out val))
                    {
                        long timeout = ObjectConverter.ToPrimitive <long>(val, 0);
                        if (timeout != 0)
                        {
                            maxNetworkDelay += unchecked ((int)timeout);
                        }
                    }
                }
                request.Timeout = maxNetworkDelay;

                //if (null != _customize) _customize(request);

                // Creates a new HTTP Transport Exchange
                LongPollingRequest httpExchange;
                lock (_exchanges)
                {
                    if (_aborted)
                    {
                        throw new InvalidOperationException("The client transport has been aborted.");
                    }

                    httpExchange = new LongPollingRequest(this, request, listener, messages);
                    _exchanges.Add(httpExchange);
                }

                // Processes the HTTP request
                httpExchange.Send();
            }
            catch (Exception ex)
            {
                if (listener != null)
                {
                    listener.OnException(ex, messages);
                }
                else
                {
                    // DEBUG
                    Trace.TraceError("Failed to send messages:{0}{1}{0}--- via transport: {2}{0}{3}",
                                     Environment.NewLine, ObjectConverter.Serialize(messages), this.ToString(), ex.ToString());
                }
            }
        }