Beispiel #1
0
        /// <summary>
        /// TODO: Implement chunking
        /// </summary>
        /// <returns>An enumerable list of chunks</returns>
        public IEnumerable <HttpResponseDataChunk> ReadChunks(HttpParserConfig config)
        {
            if (ConnectRequest)
            {
                return(ReadChunksConnect(config));
            }
            else if (HasBody && !Is100Continue && ResponseCode != 304)
            {
                if (config.StreamBody)
                {
                    if (!ChunkedEncoding)
                    {
                        return(ReadChunksStreamedLength(config));
                    }
                    else
                    {
                        return(ReadChunksStreamedChunked(config));
                    }
                }
                else
                {
                    return(ReadChunksBuffered(config));
                }
            }
            else
            {
                // No body, then just return the chunk as headers
                HttpResponseDataChunk chunk = new HttpResponseDataChunk(this);
                chunk.ChunkNumber = 0;
                chunk.FinalChunk  = true;

                return(new HttpResponseDataChunk[] { chunk });
            }
        }
Beispiel #2
0
        private HttpResponseDataChunk CreateChunk(byte[] body, int chunkNumber, bool finalChunk, bool convertToChunked)
        {
            HttpResponseDataChunk ret = new HttpResponseDataChunk(this);

            ret.ChunkNumber = chunkNumber;
            ret.FinalChunk  = finalChunk;
            ret.Body        = body;

            if (convertToChunked)
            {
                ret.ChunkedEncoding = true;
                List <KeyDataPair <string> > headers = new List <KeyDataPair <string> >();

                // Remove any content-length and existing Transfer-Encoding chunked
                foreach (KeyDataPair <string> pair in ret.Headers)
                {
                    if (!(pair.Name.Equals("Content-Length", StringComparison.OrdinalIgnoreCase) ||
                          (pair.Name.Equals("Transfer-Encoding", StringComparison.OrdinalIgnoreCase) &&
                           pair.Value.Equals("chunked", StringComparison.OrdinalIgnoreCase))))
                    {
                        headers.Add(pair);
                    }
                }

                headers.Add(new KeyDataPair <string>("Transfer-Encoding", "chunked"));
                ret.Headers = headers.ToArray();
            }


            return(ret);
        }
Beispiel #3
0
        private IEnumerable <HttpResponseDataChunk> ReadChunksConnect(HttpParserConfig config)
        {
            int chunkNumber = 0;

            while (true)
            {
                byte[] data = _reader.ReadBytes(HttpDataChunk.DEFAULT_CHUNK_SIZE, false);

                if (data.Length == 0)
                {
                    throw new EndOfStreamException();
                }

                HttpResponseDataChunk chunk = new HttpResponseDataChunk(this);

                chunk.ChunkNumber = chunkNumber;

                if (chunkNumber < int.MaxValue)
                {
                    chunkNumber++;
                }

                // Cast to length, really should just ignore any data set greater than a set amount
                chunk.Body = data;

                yield return(chunk);
            }
        }
Beispiel #4
0
        private IEnumerable <HttpResponseDataChunk> ReadChunksBuffered(HttpParserConfig config)
        {
            HttpResponseDataChunk chunk = new HttpResponseDataChunk(this);

            chunk.ChunkNumber = 0;
            chunk.FinalChunk  = true;

            if (!ChunkedEncoding)
            {
                if (ReadToEnd)
                {
                    if (_initialData != null)
                    {
                        List <byte> data = new List <byte>(BinaryEncoding.Instance.GetBytes(_initialData));
                        if (!_reader.Eof)
                        {
                            data.AddRange(_reader.ReadToEnd());
                        }

                        chunk.Body = data.ToArray();
                    }
                    else
                    {
                        chunk.Body = _reader.ReadToEnd();
                    }
                }
                else
                {
                    long length = ContentLength;

                    if (length > 0)
                    {
                        chunk.Body = _reader.ReadBytes((int)length);
                    }
                    else
                    {
                        chunk.Body = new byte[0];
                    }
                }
            }
            else
            {
                List <byte> body      = new List <byte>();
                string      extension = null;
                byte[]      ret       = ReadChunkedEncoding(_reader, out extension);

                while (ret.Length > 0)
                {
                    body.AddRange(ret);

                    ret = ReadChunkedEncoding(_reader, out extension);
                }

                chunk.ChunkedEncoding = true;
                chunk.Body            = body.ToArray();
            }

            return(new HttpResponseDataChunk[] { chunk });
        }
Beispiel #5
0
        private IEnumerable <HttpResponseDataChunk> ReadChunksStreamedChunked(HttpParserConfig config)
        {
            string extension;
            int    chunkNumber = 0;

            List <KeyDataPair <string> > headers = new List <KeyDataPair <string> >(Headers);

            if (config.DowngradeChunkedToHttp10)
            {
                int i = 0;
                while (i < headers.Count)
                {
                    if (headers[i].Name.Equals("transfer-encoding", StringComparison.OrdinalIgnoreCase) &&
                        headers[i].Value.Equals("chunked", StringComparison.OrdinalIgnoreCase))
                    {
                        headers.RemoveAt(i);
                    }
                    else
                    {
                        i++;
                    }
                }
            }

            byte[] ret = ReadChunkedEncoding(_reader, out extension);

            do
            {
                HttpResponseDataChunk chunk = new HttpResponseDataChunk(this);
                chunk.ChunkNumber = chunkNumber++;
                chunk.Body        = ret;

                if (config.DowngradeChunkedToHttp10)
                {
                    chunk.Headers = headers.ToArray();
                    chunk.Version = HttpVersion.Version10;
                }
                else
                {
                    chunk.ChunkedEncoding = true;
                }

                chunk.ChunkExtension = extension;
                ret = ReadChunkedEncoding(_reader, out extension);
                chunk.FinalChunk = ret.Length == 0;

                yield return(chunk);
            }while (ret.Length > 0);
        }
Beispiel #6
0
            private void Write(HttpResponseDataChunk chunk)
            {
                // Add proxy specific headers
                if (chunk.ChunkNumber == 0)
                {
                    ProcessProxyResponseHeaders(chunk);
                    lock (_requestQueue)
                    {
                        HttpRequestHeader request = _requestQueue.Dequeue();

                        // Fix up version to match the request
                        if (_server._config.Version10Proxy && !request.Version.IsVersionUnknown)
                        {
                            chunk.Version = HttpVersion.Version10;
                        }
                        else
                        {
                            chunk.Version = request.Version;
                        }

                        if (!chunk.Version.IsVersion11)
                        {
                            // Remove chunked encoding for sending back 1.0
                            _removeChunked = true;
                            _closeConnection = true;
                        }
                        else
                        {
                            // If not chunk encoding and no content-length then set close of end
                            if (!chunk.ChunkedEncoding)
                            {
                                bool hasContentLength = false;

                                foreach (KeyDataPair<string> header in chunk.Headers)
                                {
                                    if (header.Name.Equals("content-length", StringComparison.OrdinalIgnoreCase))
                                    {
                                        hasContentLength = true;
                                        break;
                                    }
                                }

                                if (!hasContentLength)
                                {
                                    List<KeyDataPair<string>> headers = new List<KeyDataPair<string>>(chunk.Headers);
                                    headers.Add(new KeyDataPair<string>("Connection", "close"));
                                    chunk.Headers = headers.ToArray();
                                    _closeConnection = true;
                                }
                            }
                        }
                    }
                }

                if (_removeChunked)
                {
                    chunk.ChunkedEncoding = false;
                }

                chunk.WriteChunk(_writer);

                if (chunk.FinalChunk)
                {
                    if (_closeConnection)
                    {
                        Close();
                    }
                }
            }
        private void ReturnResponse(HttpRequestHeader request, int responseCode, string message, string method, HttpVersion version, IEnumerable<KeyDataPair<string>> sendHeaders, DataAdapterToStream stm)
        {
            if (request != null)
            {
                FlushRequest(request);
            }

            HttpResponseDataChunk response = new HttpResponseDataChunk();

            if (_config.Version10Proxy && !version.IsVersionUnknown)
            {
                response.Version = HttpVersion.Version10;
            }
            else
            {
                response.Version = version;
            }

            response.ResponseCode = responseCode;
            response.Message = message;
            response.FinalChunk = true;
            response.Body = new byte[0];

            List<KeyDataPair<string>> headers = new List<KeyDataPair<string>>(sendHeaders);

            headers.Add(new KeyDataPair<string>("X-Proxy-Server", "CANAPE"));

            if (response.Body.Length > 0)
            {
                headers.Add(new KeyDataPair<string>("Content-Type", "text/html"));
            }

            response.Headers = headers.ToArray();

            if (method.Equals("HEAD", StringComparison.OrdinalIgnoreCase))
            {
                response.HeadResponse = true;
            }
            else if (method.Equals("CONNECT", StringComparison.OrdinalIgnoreCase))
            {
                response.ConnectResponse = true;
            }

            response.WriteChunk(new DataWriter(stm));
        }
Beispiel #8
0
            private HttpResponseDataChunk BuildError(int error, string message, string method, HttpVersion version)
            {
                HttpResponseDataChunk response = new HttpResponseDataChunk();

                response.Version = version;
                response.ResponseCode = error;
                response.Message = message;
                response.FinalChunk = true;
                response.Body = new byte[0];

                List<KeyDataPair<string>> headers = new List<KeyDataPair<string>>();

                headers.Add(new KeyDataPair<string>("X-Proxy-Server", "CANAPE"));
                response.Headers = headers.ToArray();

                if (method.Equals("HEAD", StringComparison.OrdinalIgnoreCase))
                {
                    response.HeadResponse = true;
                }
                else if (method.Equals("CONNECT", StringComparison.OrdinalIgnoreCase))
                {
                    response.ConnectResponse = true;
                }

                return response;
            }
Beispiel #9
0
            private void ProcessProxyResponseHeaders(HttpResponseDataChunk response)
            {
                List<KeyDataPair<string>> headers = new List<KeyDataPair<string>>(response.Headers);

                int i = 0;

                while (i < headers.Count)
                {
                    KeyDataPair<string> pair = headers[i];

                    // We don't send connection headers
                    if (pair.Name.Equals("Connection", StringComparison.OrdinalIgnoreCase) || pair.Name.Equals("Proxy-Connection"))
                    {
                        headers.RemoveAt(i);
                    }
                    else
                    {
                        ++i;
                    }
                }
            }
Beispiel #10
0
        private IEnumerable<HttpResponseDataChunk> ReadChunksStreamedChunked(HttpParserConfig config)
        {
            string extension;
            int chunkNumber = 0;

            List<KeyDataPair<string>> headers = new List<KeyDataPair<string>>(Headers);

            if (config.DowngradeChunkedToHttp10)
            {
                int i = 0;
                while(i < headers.Count)
                {
                    if (headers[i].Name.Equals("transfer-encoding", StringComparison.OrdinalIgnoreCase)
                        && headers[i].Value.Equals("chunked", StringComparison.OrdinalIgnoreCase))
                    {
                        headers.RemoveAt(i);
                    }
                    else
                    {
                        i++;
                    }
                }
            }

            byte[] ret = ReadChunkedEncoding(_reader, out extension);

            do
            {
                HttpResponseDataChunk chunk = new HttpResponseDataChunk(this);
                chunk.ChunkNumber = chunkNumber++;
                chunk.Body = ret;

                if (config.DowngradeChunkedToHttp10)
                {
                    chunk.Headers = headers.ToArray();
                    chunk.Version = HttpVersion.Version10;
                }
                else
                {
                    chunk.ChunkedEncoding = true;
                }

                chunk.ChunkExtension = extension;
                ret = ReadChunkedEncoding(_reader, out extension);
                chunk.FinalChunk = ret.Length == 0;

                yield return chunk;
            }
            while (ret.Length > 0);
        }
Beispiel #11
0
        private IEnumerable<HttpResponseDataChunk> ReadChunksConnect(HttpParserConfig config)
        {
            int chunkNumber = 0;

            while (true)
            {
                byte[] data = _reader.ReadBytes(HttpDataChunk.DEFAULT_CHUNK_SIZE, false);

                if (data.Length == 0)
                {
                    throw new EndOfStreamException();
                }

                HttpResponseDataChunk chunk = new HttpResponseDataChunk(this);

                chunk.ChunkNumber = chunkNumber;

                if (chunkNumber < int.MaxValue)
                {
                    chunkNumber++;
                }

                // Cast to length, really should just ignore any data set greater than a set amount
                chunk.Body = data;

                yield return chunk;
            }
        }
Beispiel #12
0
        private IEnumerable<HttpResponseDataChunk> ReadChunksBuffered(HttpParserConfig config)
        {
            HttpResponseDataChunk chunk = new HttpResponseDataChunk(this);
            chunk.ChunkNumber = 0;
            chunk.FinalChunk = true;

            if (!ChunkedEncoding)
            {
                if (ReadToEnd)
                {
                    if (_initialData != null)
                    {
                        List<byte> data = new List<byte>(BinaryEncoding.Instance.GetBytes(_initialData));
                        if (!_reader.Eof)
                        {
                            data.AddRange(_reader.ReadToEnd());
                        }

                        chunk.Body = data.ToArray();
                    }
                    else
                    {
                        chunk.Body = _reader.ReadToEnd();
                    }
                }
                else
                {
                    long length = ContentLength;

                    if (length > 0)
                    {
                        chunk.Body = _reader.ReadBytes((int)length);
                    }
                    else
                    {
                        chunk.Body = new byte[0];
                    }
                }
            }
            else
            {
                List<byte> body = new List<byte>();
                string extension = null;
                byte[] ret = ReadChunkedEncoding(_reader, out extension);

                while (ret.Length > 0)
                {
                    body.AddRange(ret);

                    ret = ReadChunkedEncoding(_reader, out extension);
                }

                chunk.ChunkedEncoding = true;
                chunk.Body = body.ToArray();
            }

            return new HttpResponseDataChunk[] { chunk };
        }
Beispiel #13
0
        private HttpResponseDataChunk CreateChunk(byte[] body, int chunkNumber, bool finalChunk, bool convertToChunked)
        {
            HttpResponseDataChunk ret = new HttpResponseDataChunk(this);

            ret.ChunkNumber = chunkNumber;
            ret.FinalChunk = finalChunk;
            ret.Body = body;

            if (convertToChunked)
            {
                ret.ChunkedEncoding = true;
                List<KeyDataPair<string>> headers = new List<KeyDataPair<string>>();

                // Remove any content-length and existing Transfer-Encoding chunked
                foreach (KeyDataPair<string> pair in ret.Headers)
                {
                    if (!(pair.Name.Equals("Content-Length", StringComparison.OrdinalIgnoreCase)
                        || (pair.Name.Equals("Transfer-Encoding", StringComparison.OrdinalIgnoreCase)
                        && pair.Value.Equals("chunked", StringComparison.OrdinalIgnoreCase))))
                    {
                        headers.Add(pair);
                    }
                }

                headers.Add(new KeyDataPair<string>("Transfer-Encoding", "chunked"));
                ret.Headers = headers.ToArray();
            }

            return ret;
        }
Beispiel #14
0
        /// <summary>
        /// TODO: Implement chunking
        /// </summary>        
        /// <returns>An enumerable list of chunks</returns>
        public IEnumerable<HttpResponseDataChunk> ReadChunks(HttpParserConfig config)
        {
            if (ConnectRequest)
            {
                return ReadChunksConnect(config);
            }
            else if (HasBody && !Is100Continue && ResponseCode != 304)
            {
                if (config.StreamBody)
                {
                    if (!ChunkedEncoding)
                    {
                        return ReadChunksStreamedLength(config);
                    }
                    else
                    {
                        return ReadChunksStreamedChunked(config);
                    }
                }
                else
                {
                    return ReadChunksBuffered(config);
                }
            }
            else
            {
                // No body, then just return the chunk as headers
                HttpResponseDataChunk chunk = new HttpResponseDataChunk(this);
                chunk.ChunkNumber = 0;
                chunk.FinalChunk = true;

                return new HttpResponseDataChunk[] { chunk };
            }
        }