/// <summary>
		/// Sends the request and waits for a response
		/// </summary>
		/// <param name="request">The request to be processed by the server and for which we want a response.</param>
		/// <returns></returns>
		public virtual HttpResponse GetResponse(
			HttpRequest request,
			EventHandler<HttpMessageProgressEventArgs> onSendProgress,
            EventHandler<HttpMessageProgressEventArgs> onRecvProgress,
			object stateObject)
		{
			try
			{
				// send the request
				this.SendRequest(request, onSendProgress, stateObject);
				
				HttpResponse response = null;
				bool recievedContinue = false;
				do
				{
					recievedContinue = false;
					
					lock (_messageReader)
					{
						// receive a response
						HttpMessage message = _messageReader.Read(_socket, null, onRecvProgress, stateObject);
						if (message.Type == HttpMessageTypes.HttpResponse)
							response = new HttpResponse(message);
					}

					if (response != null)
					{
						Debug.WriteLineIf(_verbose, "Logging response...", MY_TRACE_CATEGORY);
						Debug.WriteIf(_verbose, response.ToString(false));

						if (response.Status.Code == HttpStatusCode.Continue)
						{
							recievedContinue = true;
							response = null;
						}
					}
				}
				while (recievedContinue);

				return response;
			}
			catch(Exception ex) 
			{
                Debug.WriteLine(ex);

				// notify that this connection has encountered an exception				
				this.OnException(this, new ExceptionEventArgs(ex));
				this.Close();
			}
			return null;
		}
		/// <summary>
		/// Sends the specified response using the connection's socket
		/// </summary>
		/// <param name="response"></param>
		public virtual void SendResponseToRequest(ref HttpRequest request, ref HttpResponse response)
		{
			try
			{
				// if the request has asked that the connection be kept-alive, we'll abide by the request
				if (HttpUtils.Contains(request.Connection, HttpConnections.KeepAlive))
					// so instruct the response to notify the user-agent that the connection will be kept alive
					response.Connection = HttpConnections.KeepAlive;

				Debug.WriteLineIf(_verbose, "Sending response...", MY_TRACE_CATEGORY);			
				Debug.WriteIf(_verbose, response.ToString(false));
				
				// lock the writer
				lock(_messageWriter)
				{
					// send the message
					_messageWriter.Write(_socket, null, response);
				}
				
				// next check the request to see if the connection should be closed after the response was sent
				if (HttpUtils.Contains(request.Connection, HttpConnections.Close))
				{
					// yup, they wanted us to close the connection automatically so lets do that now
					this.Close();
					return;
				}
			}
			catch(ThreadAbortException)
			{

			}
			catch(Exception ex)
			{
                this.OnException(this, new ExceptionEventArgs(ex));
				// throw new Exception(ex.Message, ex);
			}
		}
 /// <summary>
 /// Initializes a new instance of the HttpRequestCancelEventArgs class.
 /// </summary>
 /// <param name="request"></param>
 /// <param name="response"></param>
 /// <param name="cancel"></param>
 public HttpRequestCancelEventArgs(HttpRequest request, HttpResponse response, bool cancel)
     : base((HttpMessage)request, cancel)
 {
     _response = response;
 }
		/// <summary>
		/// Determines if the request succeeded based on the status code of the response
		/// </summary>
		/// <param name="response"></param>
		/// <returns></returns>
		public static bool Succeeded(HttpResponse response)
		{
			if (response == null)
				return false;

			if (response.Status.Code == new OkStatus().Code)
				return true;

			return false;
		}
		/// <summary>
		/// Initializes a new instance of the HttpResponseEventArgs class
		/// </summary>
		/// <param name="response">The message response context</param>
		public HttpResponseEventArgs(HttpResponse response) : base((HttpMessage)response)
		{
			
		}
		/// <summary>
		/// Checks the headers of a response message
		/// </summary>
		/// <param name="response"></param>
		internal protected void CheckRequiredResponseHeaders(HttpResponse response)
		{
			// make sure the server header is filled in
			if (HttpUtils.IsEmptryString(response.Server))
				response.Server = new CarbonServerProtocolVersion().ToString();

			// if there is no body, or that body is zero length we are finished
			if (response.Body == null)
				return;	
		
			// if the body is zero length no problem
			if (response.Body.Length == 0)
				return;

			// however if there is a body with X length, we must ensure that the response's content-length header is filled in properly
			if (response.ContentLength != response.Body.Length)
				response.ContentLength = response.Body.Length;	
			
			// lastly, warn if we are going to send a response with no content-type, it's just not cool
			if (HttpUtils.IsEmptryString(response.ContentType))
				Debug.WriteLine(string.Format("The response '{0}' contains a body, but does not contain a valid 'content-type'. Please set the 'content-type' header field, or use the SetBody(XXX) methods of the HttpMessage class when setting the message body.", response.FirstLine), MY_TRACE_CATEGORY);
		}