/// <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,
			HttpMessageProgressEventHandler onSendProgress,
			HttpMessageProgressEventHandler onRecvProgress,
			object stateObject)
		{
			try
			{
				// send the request
				this.SendRequest(request, onSendProgress, stateObject);			

				// lock the reader
				HttpResponse response = null;
				lock(_messageReader)
				{
					// receive the 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));
				}

				return response;
			}
			catch(Exception 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)
			{
				throw new Exception(ex.Message, ex);
			}

			/*
			 * the following demonstrates a bug in the binary writer, or else some encoding issues with the message class' ToByteArray(.,.) method
			 * */
			// sending it all at once works...
//			_socket.Send(response.ToByteArray());

//			byte[] all = response.ToByteArray(true, true);
//			byte[] headers = response.ToByteArray(true, false);
//			byte[] body = response.ToByteArray(false, true);
//			byte[] none = response.ToByteArray(false, false);
////
//			Debug.WriteLine(string.Format("Sending message... All '{0}', Combined '{1}', Headers '{2}', Body '{3}'", all.Length, headers.Length + body.Length, headers.Length, body.Length));
//            Debug.WriteLine(string.Format("\t...A diference of '{0}'", (headers.Length + body.Length) - all.Length));
//			
////			_socket.Send(all);
//			_socket.Send(headers);
//			_socket.Send(body);
		}
		/// <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 RazorServerProtocolVersion().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);
		}
		/// <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>
		/// 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;
		}