public void ReceiveResponseAsync(Http.Request request)
        {
            if (!IsConnected)
                throw new HttpConnectionException("A network connection is not established.");

            long bytesReceived = 0;
            Tcp.TcpConnection.ProgressDelegate onProgress;
            ResponseBuilder.AsyncCallback callback;

            if (_responseBuilder == null)
                _responseBuilder = new ResponseBuilder(request);


            onProgress = delegate(Tcp.TcpConnection sender, Tcp.DirectionType direction, int packetSize)
            {
                bytesReceived += packetSize;
                Logger.Network.Debug("HttpConnection ID: " + this.GetHashCode().ToString() +
                    "\r\nTcpConnection ID: " + _tcpConnection.GetHashCode().ToString() +
                    "\r\nBytes Received: " + bytesReceived.ToString() +
                    "\r\nResponse Size: " + _responseBuilder.MessageSize.ToString() +
                    "\r\nPacket Size: " + packetSize.ToString() +
                    "\r\nHttpConnection reporting progress receiving from remote host.");
                if (OnProgress != null) OnProgress(this, direction, packetSize, 100, ((decimal)bytesReceived / (decimal)_responseBuilder.MessageSize));
            };

            _tcpConnection.OnProgress += onProgress;
            _tcpConnection.OnError += new Tcp.TcpConnection.ErrorDelegate(ReceiveResponseAsync_OnError);
            _tcpConnection.OnTimeout += new Tcp.TcpConnection.ConnectionDelegate(ReceiveResponseAsync_OnTimeout);

            callback = delegate(MessageBuilder sender, Message.Base message)
            {
                Logger.Network.Debug("HttpConnection ID: " + this.GetHashCode().ToString() + "\r\nTcpConnection ID: " + _tcpConnection.GetHashCode().ToString() + "\r\nHttpConnection receiving data from remote host completed.");
                if (OnComplete != null) OnComplete(this, (Response)message);
            };

            Logger.Network.Debug("HttpConnection ID: " + this.GetHashCode().ToString() + "\r\nTcpConnection ID: " + _tcpConnection.GetHashCode().ToString() + "\r\nHttpConnection beginning receiving of data from remote host.");
            _responseBuilder.ParseAndAttachToBody(_tcpConnection, callback);
        }
        public void SendRequestAsync(Request request)
        {
            if (!IsConnected)
                throw new HttpConnectionException("A network connection is not established.");

            Tcp.TcpConnection.ProgressDelegate onProgress;
            Tcp.TcpConnection.AsyncCallback callback;
            Stream stream;
            long requestSize = 0;
            long bytesSent = 0;

            // Make the RequestLine and Headers into a stream
            if (request.Body.SendStream != null)
                stream = request.MakeRequestLineAndHeadersStream();
            else
                stream = request.MakeRequestLineAndHeadersStream("\r\n");

            requestSize += stream.Length;

            if (stream != null)
                requestSize += stream.Length;
            
            onProgress = delegate(Tcp.TcpConnection sender, Tcp.DirectionType direction, int packetSize)
            {
                bytesSent += packetSize;
                Logger.Network.Debug("HttpConnection ID: " + this.GetHashCode().ToString() + 
                    "\r\nTcpConnection ID: " + _tcpConnection.GetHashCode().ToString() +
                    "\r\nBytes Sent: " + bytesSent.ToString() + 
                    "\r\nRequest Size: " + requestSize.ToString() + 
                    "\r\nPacket Size: " + packetSize.ToString() +
                    "\r\nHttpConnection reporting progress sending to remote host.");
                if (OnProgress != null) OnProgress(this, direction, packetSize, ((decimal)((decimal)bytesSent / (decimal)requestSize)), 0);
            };

            _tcpConnection.OnProgress += onProgress;
            _tcpConnection.OnError += new Tcp.TcpConnection.ErrorDelegate(SendRequest_OnError);
            _tcpConnection.OnTimeout += new Tcp.TcpConnection.ConnectionDelegate(SendRequest_OnTimeout);

            callback = delegate(Tcp.TcpConnection sender, Tcp.TcpConnectionAsyncEventArgs e)
            {
                // Do not yet disconnect the error and timeout event handlers as they will continue to function for the
                // Check100Continue
                //_tcpConnection.OnError -= onError;
                //_tcpConnection.OnTimeout -= onTimeout;

                Tcp.TcpConnection.AsyncCallback c100Callback, contentSendCallback;

                Logger.Network.Debug("HttpConnection ID: " + this.GetHashCode().ToString() + "\r\nTcpConnection ID: " + _tcpConnection.GetHashCode().ToString() + "\r\nHttpConnection sent the stream.");

                contentSendCallback = delegate(Tcp.TcpConnection sender3, Tcp.TcpConnectionAsyncEventArgs e3)
                { // Called when all the content is sent, need to receive
                    // Now we can unhook onError, onTimeout and onProgress because ReceiveResponseAsync will rehook
                    // for when it is called individually, so we don't want to risk double hooking

                    _tcpConnection.OnError -= SendRequest_OnError;
                    _tcpConnection.OnTimeout -= SendRequest_OnTimeout;
                    _tcpConnection.OnProgress -= onProgress;

                    ReceiveResponseAsync(request);
                };

                c100Callback = delegate(Tcp.TcpConnection sender2, Tcp.TcpConnectionAsyncEventArgs e2)
                {
                    _responseBuilder = new ResponseBuilder(request);

                    _responseBuilder.AppendAndParse(e2.Buffer, 0, e2.BytesTransferred);

                    if (_responseBuilder.Response == null)
                    {
                        Logger.Network.Debug("HttpConnection ID: " + this.GetHashCode().ToString() + "\r\nTcpConnection ID: " + _tcpConnection.GetHashCode().ToString() + "\r\nHttpConnection did not receive the expected 100-Continue response.");
                        throw new HttpNetworkStreamException("Status 100 Continue not received.");
                    }

                    Logger.Network.Debug("HttpConnection ID: " + this.GetHashCode().ToString() + "\r\nTcpConnection ID: " + _tcpConnection.GetHashCode().ToString() + "\r\nHttpConnection received the expected 100-Continue response.");

                    if (request.Body.SendStream != null)
                    {
                        Logger.Network.Debug("HttpConnection ID: " + this.GetHashCode().ToString() + "\r\nTcpConnection ID: " + _tcpConnection.GetHashCode().ToString() + "\r\nHttpConnection requesting TcpConnection to send the body content.");
                        _tcpConnection.SendAsync(request.Body.SendStream, contentSendCallback);
                    }
                };

                if (request.Headers.ContainsKey(new Message.Expect100ContinueHeader()))
                {
                    Logger.Network.Debug("HttpConnection ID: " + this.GetHashCode().ToString() + "\r\nTcpConnection ID: " + _tcpConnection.GetHashCode().ToString() + "\r\nThe request was sent with a Expect: 100-Continue header, now checking for the 100-Continue response.");

                    Check100Continue(c100Callback);
                }
                else
                {
                    if (request.Body.SendStream != null)
                    {
                        Logger.Network.Debug("HttpConnection ID: " + this.GetHashCode().ToString() + "\r\nTcpConnection ID: " + _tcpConnection.GetHashCode().ToString() + "\r\nHttpConnection requesting TcpConnection to send the body content.");
                        _tcpConnection.SendAsync(request.Body.SendStream, contentSendCallback);
                    }
                    else
                    {
                        _tcpConnection.OnError -= SendRequest_OnError;
                        _tcpConnection.OnTimeout -= SendRequest_OnTimeout;
                        _tcpConnection.OnProgress -= onProgress;

                        ReceiveResponseAsync(request);
                    }
                }
            };

            Logger.Network.Debug("HttpConnection ID: " + this.GetHashCode().ToString() + "\r\nTcpConnection ID: " + _tcpConnection.GetHashCode().ToString() + "\r\nHttpConnection requesting TcpConnection to send a stream.");
            _tcpConnection.SendAsync(stream, callback);
        }