Ejemplo n.º 1
0
        private bool RequestReceived()
        {
#if WINDOWS_UWP
            HttpRequest Request = new HttpRequest(this.header, this.dataStream, this.outputStream,
                                                  this.client.Information.RemoteAddress.ToString() + ":" + this.client.Information.RemotePort);
#else
            HttpRequest Request = new HttpRequest(this.header, this.dataStream, this.stream, this.client.Client.RemoteEndPoint.ToString());
#endif
            Request.clientConnection = this;

            bool?Queued = this.QueueRequest(Request);

            if (Queued.HasValue)
            {
                if (!Queued.Value && this.dataStream != null)
                {
                    this.dataStream.Dispose();
                }

                this.header           = null;
                this.dataStream       = null;
                this.transferEncoding = null;

                return(Queued.Value);
            }
            else
            {
                return(true);
            }
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Represets a response of an HTTP client request.
        /// </summary>
        /// <param name="TransferEncoding">Transfer encoding to use for transfering content to client.</param>
        /// <param name="HttpServer">HTTP Server serving the request.</param>
        /// <param name="Request">Request being served.</param>
        public HttpResponse(TransferEncoding TransferEncoding, HttpServer HttpServer, HttpRequest Request)
            : base()
        {
            this.responseStream          = null;
            this.clientConnection        = null;
            this.desiredTransferEncoding = TransferEncoding;
            this.httpServer  = HttpServer;
            this.httpRequest = Request;

            if (Request != null && Request.Header.TryGetHeaderField("Connection", out HttpField Field) && Field.Value == "close")
            {
                this.closeAfterResponse = true;
                this.SetHeader("Connection", "close");
            }
        }
Ejemplo n.º 3
0
        private async Task <bool> BinaryDataReceived(byte[] Data, int Offset, int NrRead)
        {
            if (this.dataStream is null)
            {
                HttpFieldTransferEncoding TransferEncoding = this.header.TransferEncoding;
                if (!(TransferEncoding is null))
                {
                    if (TransferEncoding.Value == "chunked")
                    {
                        this.dataStream       = new TemporaryStream();
                        this.transferEncoding = new ChunkedTransferEncoding(new BinaryOutputStream(this.dataStream), null);
                    }
                    else
                    {
                        await this.SendResponse(null, null, new HttpException(501, "Not Implemented", "Transfer encoding not implemented."), false);

                        return(true);
                    }
                }
                else
                {
                    HttpFieldContentLength ContentLength = this.header.ContentLength;
                    if (!(ContentLength is null))
                    {
                        long l = ContentLength.ContentLength;
                        if (l < 0)
                        {
                            await this.SendResponse(null, null, new HttpException(400, "Bad Request", "Negative content lengths invalid."), false);

                            return(true);
                        }

                        if (l <= MaxInmemoryMessageSize)
                        {
                            this.dataStream = new MemoryStream((int)l);
                        }
                        else
                        {
                            this.dataStream = new TemporaryStream();
                        }

                        this.transferEncoding = new ContentLengthEncoding(new BinaryOutputStream(this.dataStream), l, null);
                    }
Ejemplo n.º 4
0
        private void StartSendResponse(bool ExpectContent)
        {
            if (this.transferEncoding == null)
            {
                if (this.desiredTransferEncoding == null)
                {
                    StringBuilder Output = new StringBuilder();

                    Output.Append("HTTP/1.1 ");
                    Output.Append(this.statusCode.ToString());
                    Output.Append(' ');
                    Output.Append(this.statusMessage);

                    Output.Append("\r\nDate: ");
                    Output.Append(CommonTypes.EncodeRfc822(this.date));

                    if (this.expires.HasValue)
                    {
                        Output.Append("\r\nExpires: ");
                        Output.Append(CommonTypes.EncodeRfc822(this.expires.Value));
                    }

                    Output.Append("\r\nServer: ");
                    if (string.IsNullOrEmpty(this.server))
                    {
                        Output.Append("Waher.Networking.HTTP");
                    }
                    else
                    {
                        Output.Append(this.server + " (Waher.Networking.HTTP)");
                    }

                    if (!string.IsNullOrEmpty(this.contentLanguage))
                    {
                        Output.Append("\r\nContent-Language: ");
                        Output.Append(this.contentLanguage);
                    }

                    if (!string.IsNullOrEmpty(this.contentType))
                    {
                        Output.Append("\r\nContent-Type: ");
                        Output.Append(this.contentType);

                        if (this.contentType.StartsWith("text/") && !this.contentType.Contains("charset="))
                        {
                            Output.Append("; charset=");
                            Output.Append(this.encoding.WebName);
                        }
                    }

                    if ((ExpectContent || this.contentLength.HasValue) &&
                        ((this.statusCode >= 100 && this.statusCode <= 199) || this.statusCode == 204 || this.statusCode == 304))
                    {
                        throw new Exception("Content not allowed for status codes " + this.statusCode.ToString());

                        // When message bodies are required:
                        // http://stackoverflow.com/questions/299628/is-an-entity-body-allowed-for-an-http-delete-request
                    }

                    if (this.contentLength.HasValue)
                    {
                        Output.Append("\r\nContent-Length: ");
                        Output.Append(this.contentLength.Value.ToString());

                        this.transferEncoding = new ContentLengthEncoding(this.onlyHeader ? Stream.Null : this.responseStream, this.contentLength.Value, this.clientConnection);
                    }
                    else if (ExpectContent)
                    {
                        Output.Append("\r\nTransfer-Encoding: chunked");
                        this.transferEncoding = new ChunkedTransferEncoding(this.onlyHeader ? Stream.Null : this.responseStream, DefaultChunkSize, this.clientConnection);
                    }
                    else
                    {
                        if ((this.statusCode < 100 || this.statusCode > 199) && this.statusCode != 204 && this.statusCode != 304)
                        {
                            Output.Append("\r\nContent-Length: 0");
                        }

                        this.transferEncoding = new ContentLengthEncoding(this.onlyHeader ? Stream.Null : this.responseStream, 0, this.clientConnection);
                    }

                    if (this.customHeaders != null)
                    {
                        foreach (KeyValuePair <string, string> P in this.customHeaders)
                        {
                            Output.Append("\r\n");
                            Output.Append(P.Key);
                            Output.Append(": ");
                            Output.Append(P.Value);
                        }
                    }

                    if (this.cookies != null)
                    {
                        foreach (Cookie Cookie in this.cookies)
                        {
                            Output.Append("\r\nSet-Cookie: ");
                            Output.Append(Cookie.ToString());
                        }
                    }

                    Output.Append("\r\n\r\n");

                    string Header    = Output.ToString();
                    byte[] HeaderBin = InternetContent.ISO_8859_1.GetBytes(Header);

                    if (this.responseStream == null || this.clientConnection.Disposed)
                    {
                        return;
                    }

                    this.responseStream.Write(HeaderBin, 0, HeaderBin.Length);
                    this.clientConnection.Server.DataTransmitted(HeaderBin.Length);
                    this.clientConnection.TransmitText(Header);
                }
                else
                {
                    this.transferEncoding = this.desiredTransferEncoding;
                    this.transferEncoding.BeforeContent(this, ExpectContent);
                }
            }
        }
Ejemplo n.º 5
0
        private bool BinaryDataReceived(byte[] Data, int Offset, int NrRead)
        {
            if (this.dataStream == null)
            {
                HttpFieldTransferEncoding TransferEncoding = this.header.TransferEncoding;
                if (TransferEncoding != null)
                {
                    if (TransferEncoding.Value == "chunked")
                    {
                        this.dataStream       = new TemporaryFile();
                        this.transferEncoding = new ChunkedTransferEncoding(this.dataStream, null);
                    }
                    else
                    {
                        this.SendResponse(null, 501, "Not Implemented", false);
                        return(true);
                    }
                }
                else
                {
                    HttpFieldContentLength ContentLength = this.header.ContentLength;
                    if (ContentLength != null)
                    {
                        long l = ContentLength.ContentLength;
                        if (l < 0)
                        {
                            this.SendResponse(null, 400, "Bad Request", false);
                            return(true);
                        }

                        if (l <= MaxInmemoryMessageSize)
                        {
                            this.dataStream = new MemoryStream((int)l);
                        }
                        else
                        {
                            this.dataStream = new TemporaryFile();
                        }

                        this.transferEncoding = new ContentLengthEncoding(this.dataStream, l, null);
                    }
                    else
                    {
                        this.SendResponse(null, 411, "Length Required", true);
                        return(false);
                    }
                }
            }

            bool Complete = this.transferEncoding.Decode(Data, Offset, NrRead, out int NrAccepted);

            if (this.HasSniffers)
            {
                if (Offset == 0 && NrAccepted == Data.Length)
                {
                    this.ReceiveBinary(Data);
                }
                else
                {
                    byte[] Data2 = new byte[NrAccepted];
                    Array.Copy(Data, Offset, Data2, 0, NrAccepted);
                    this.ReceiveBinary(Data2);
                }
            }

            if (Complete)
            {
                if (this.transferEncoding.InvalidEncoding)
                {
                    this.SendResponse(null, 400, "Bad Request", false);
                    return(true);
                }
                else
                {
                    Offset += NrAccepted;
                    NrRead -= NrAccepted;

                    if (!this.RequestReceived())
                    {
                        return(false);
                    }

                    if (NrRead > 0)
                    {
                        return(this.BinaryHeaderReceived(Data, Offset, NrRead));
                    }
                    else
                    {
                        return(true);
                    }
                }
            }
            else if (this.dataStream.Position > MaxEntitySize)
            {
                this.dataStream.Dispose();
                this.dataStream = null;

                this.SendResponse(null, 413, "Request Entity Too Large", true);
                return(false);
            }
            else
            {
                return(true);
            }
        }
Ejemplo n.º 6
0
        private async Task <bool> BinaryDataReceived(byte[] Data, int Offset, int NrRead)
        {
            if (this.dataStream is null)
            {
                HttpFieldTransferEncoding TransferEncoding = this.header.TransferEncoding;
                if (TransferEncoding != null)
                {
                    if (TransferEncoding.Value == "chunked")
                    {
                        this.dataStream       = new TemporaryFile();
                        this.transferEncoding = new ChunkedTransferEncoding(new BinaryOutputStream(this.dataStream), null);
                    }
                    else
                    {
                        await this.SendResponse(null, null, new HttpException(501, "Not Implemented", "Transfer encoding not implemented."), false);

                        return(true);
                    }
                }
                else
                {
                    HttpFieldContentLength ContentLength = this.header.ContentLength;
                    if (ContentLength != null)
                    {
                        long l = ContentLength.ContentLength;
                        if (l < 0)
                        {
                            await this.SendResponse(null, null, new HttpException(400, "Bad Request", "Negative content lengths invalid."), false);

                            return(true);
                        }

                        if (l <= MaxInmemoryMessageSize)
                        {
                            this.dataStream = new MemoryStream((int)l);
                        }
                        else
                        {
                            this.dataStream = new TemporaryFile();
                        }

                        this.transferEncoding = new ContentLengthEncoding(new BinaryOutputStream(this.dataStream), l, null);
                    }
                    else
                    {
                        await this.SendResponse(null, null, new HttpException(411, "Length Required", "Content Length required."), true);

                        return(false);
                    }
                }
            }

            ulong DecodingResponse = await this.transferEncoding.DecodeAsync(Data, Offset, NrRead);

            int  NrAccepted = (int)DecodingResponse;
            bool Complete   = (DecodingResponse & 0x100000000) != 0;

            if (this.HasSniffers)
            {
                if (Offset == 0 && NrAccepted == Data.Length)
                {
                    this.ReceiveBinary(Data);
                }
                else
                {
                    byte[] Data2 = new byte[NrAccepted];
                    Array.Copy(Data, Offset, Data2, 0, NrAccepted);
                    this.ReceiveBinary(Data2);
                }
            }

            if (Complete)
            {
                if (this.transferEncoding.InvalidEncoding)
                {
                    await this.SendResponse(null, null, new HttpException(400, "Bad Request", "Invalid transfer encoding."), false);

                    return(true);
                }
                else if (this.transferEncoding.TransferError)
                {
                    await this.SendResponse(null, null, new HttpException(500, "Internal Server Error", "Unable to transfer content to resource."), false);

                    return(true);
                }
                else
                {
                    Offset += NrAccepted;
                    NrRead -= NrAccepted;

                    if (!await this.RequestReceived())
                    {
                        return(false);
                    }

                    if (NrRead > 0)
                    {
                        return(await this.BinaryHeaderReceived(Data, Offset, NrRead));
                    }
                    else
                    {
                        return(true);
                    }
                }
            }
            else if (this.dataStream.Position > MaxEntitySize)
            {
                this.dataStream.Dispose();
                this.dataStream = null;

                await this.SendResponse(null, null, new HttpException(413, "Request Entity Too Large", "Maximum Entity Size: " + MaxEntitySize.ToString()), true);

                return(false);
            }
            else
            {
                return(true);
            }
        }