Example #1
0
        /// <summary>
        ///     Pipeline step: tunnel the request from the client to the remove
        ///     server, and schedule the next step to be <c>ReadResponse</c>
        /// </summary>
        protected virtual void SendRequest()
        {
            // Transmit the request to the server
            RequestLine.SendTo(RemoteSocket);
            RequestHeaders.SendTo(RemoteSocket);
            if (State.RequestHasMessage)
            {
                // Tunnel the request message
                if (State.RequestMessageChunked)
                {
                    BrowserSocket.TunnelChunkedDataTo(RemoteSocket);
                }
                else
                {
                    Debug.Assert(State.RequestMessageLength > 0);
                    BrowserSocket.TunnelDataTo(TunnelRemoteSocket, State.RequestMessageLength);
                }
            }

            State.NextStep = ReadResponse;
        }
Example #2
0
        /// <summary>
        ///     Pipeline: tunnel the HTTP response from the remote server to the
        ///     local client, and end the request processing
        /// </summary>
        protected virtual void SendResponse()
        {
            if ((ResponseHeaders.TransferEncoding == null && ResponseHeaders.ContentLength == null) == false)
            {
                // Transmit the response header to the client
                SendResponseStatusAndHeaders();
            }

            // Find out if there is a message body
            // (RFC 2616, section 4.4)
            int sc = ResponseStatusLine.StatusCode;

            if (RequestLine.Method.Equals("HEAD") ||
                sc == 204 || sc == 304 || (sc >= 100 && sc <= 199))
            {
                SendResponseStatusAndHeaders();
                CallOnReceiveResponse(ResponseHeaders.ContentEncoding);
                return;
            }

            bool responseMessageChunked = false;
            uint responseMessageLength  = 0;

            if (ResponseHeaders.TransferEncoding != null)
            {
                responseMessageChunked = Array.IndexOf(ResponseHeaders.TransferEncoding, "chunked") >= 0;
                Debug.Assert(responseMessageChunked);
            }
            else if (ResponseHeaders.ContentLength != null)
            {
                responseMessageLength = (uint)ResponseHeaders.ContentLength;
                if (responseMessageLength == 0)
                {
                    CallOnReceiveResponse(ResponseHeaders.ContentEncoding);
                    return;
                }
            }
            else
            {
                // We really should have been given a response
                // length. It appears that some popular websites
                // send small files without a transfer-encoding
                // or length.

                // It seems that all of the browsers handle this
                // case so we need to as well.

                var buffer = new byte[512];
                RemoteSocket.TunnelDataTo(ref buffer);

                // Transmit the response header to the client
                ResponseHeaders.ContentLength = (uint)buffer.Length;
                ResponseStatusLine.SendTo(BrowserSocket);
                ResponseHeaders.SendTo(BrowserSocket);

                BrowserSocket.TunnelDataTo(TunnelBrowserSocket, buffer);
                State.NextStep = null;
                return;
            }

            if (State.OnResponseMessagePacket != null)
            {
                if (State.PersistConnectionRemoteSocket == false)
                {
                    // Pipeline until the connection is closed
                    RemoteSocket.TunnelDataTo(State.OnResponseMessagePacket);
                }
                else
                {
                    if (responseMessageChunked)
                    {
                        RemoteSocket.TunnelChunkedDataTo(State.OnResponseMessagePacket);
                    }
                    else
                    {
                        RemoteSocket.TunnelDataTo(State.OnResponseMessagePacket, responseMessageLength);
                    }
                }
                State.OnResponseMessagePacket(null, 0, 0);
            }
            else
            {
                if (State.PersistConnectionRemoteSocket == false)
                {
                    // Pipeline until the connection is closed
                    RemoteSocket.TunnelDataTo(TunnelBrowserSocket);
                }
                else
                {
                    if (responseMessageChunked)
                    {
                        RemoteSocket.TunnelChunkedDataTo(BrowserSocket);
                    }
                    else
                    {
                        RemoteSocket.TunnelDataTo(TunnelBrowserSocket, responseMessageLength);
                    }
                }
            }

            CallOnReceiveResponse(ResponseHeaders.ContentEncoding);
        }