1e6828456SNiels Sascha Reedijk /* 2e6828456SNiels Sascha Reedijk * Copyright 2022 Haiku Inc. All rights reserved. 3e6828456SNiels Sascha Reedijk * Distributed under the terms of the MIT License. 4e6828456SNiels Sascha Reedijk */ 5e6828456SNiels Sascha Reedijk 6e6828456SNiels Sascha Reedijk #ifndef _B_HTTP_PARSER_H_ 7e6828456SNiels Sascha Reedijk #define _B_HTTP_PARSER_H_ 8e6828456SNiels Sascha Reedijk 9e6828456SNiels Sascha Reedijk 10e6828456SNiels Sascha Reedijk #include <functional> 11e6828456SNiels Sascha Reedijk #include <optional> 12e6828456SNiels Sascha Reedijk 13e6828456SNiels Sascha Reedijk #include <HttpResult.h> 14e6828456SNiels Sascha Reedijk 15e6828456SNiels Sascha Reedijk #include "HttpBuffer.h" 16e6828456SNiels Sascha Reedijk 17e6828456SNiels Sascha Reedijk class BMallocIO; 18e6828456SNiels Sascha Reedijk 19e6828456SNiels Sascha Reedijk namespace BPrivate { 20e6828456SNiels Sascha Reedijk 21e6828456SNiels Sascha Reedijk namespace Network { 22e6828456SNiels Sascha Reedijk 23e6828456SNiels Sascha Reedijk using HttpTransferFunction = std::function<size_t(const std::byte*, size_t)>; 24e6828456SNiels Sascha Reedijk 25e6828456SNiels Sascha Reedijk 26*71e29bbeSNiels Sascha Reedijk enum class HttpInputStreamState { StatusLine, Fields, Body, Done }; 27e6828456SNiels Sascha Reedijk 28e6828456SNiels Sascha Reedijk 29*71e29bbeSNiels Sascha Reedijk enum class HttpBodyType { NoContent, Chunked, FixedSize, VariableSize }; 307b1d966cSNiels Sascha Reedijk 317b1d966cSNiels Sascha Reedijk 323c9045fbSNiels Sascha Reedijk struct BodyParseResult { 333c9045fbSNiels Sascha Reedijk size_t bytesParsed; 343c9045fbSNiels Sascha Reedijk size_t bytesWritten; 353c9045fbSNiels Sascha Reedijk bool complete; 363c9045fbSNiels Sascha Reedijk }; 373c9045fbSNiels Sascha Reedijk 383c9045fbSNiels Sascha Reedijk 393c9045fbSNiels Sascha Reedijk class HttpBodyParser; 403c9045fbSNiels Sascha Reedijk 413c9045fbSNiels Sascha Reedijk 42*71e29bbeSNiels Sascha Reedijk class HttpParser 43*71e29bbeSNiels Sascha Reedijk { 44e6828456SNiels Sascha Reedijk public: HttpParser()45e6828456SNiels Sascha Reedijk HttpParser(){}; 46e6828456SNiels Sascha Reedijk 477b1d966cSNiels Sascha Reedijk // Explicitly mark request as having no content 483c9045fbSNiels Sascha Reedijk void SetNoContent() noexcept; 497b1d966cSNiels Sascha Reedijk 503c9045fbSNiels Sascha Reedijk // Parse data from response 51e6828456SNiels Sascha Reedijk bool ParseStatus(HttpBuffer& buffer, BHttpStatus& status); 52e6828456SNiels Sascha Reedijk bool ParseFields(HttpBuffer& buffer, BHttpFields& fields); 533c9045fbSNiels Sascha Reedijk size_t ParseBody(HttpBuffer& buffer, HttpTransferFunction writeToBody, 543c9045fbSNiels Sascha Reedijk bool readEnd); State()553c9045fbSNiels Sascha Reedijk HttpInputStreamState State() const noexcept { return fStreamState; } 567b1d966cSNiels Sascha Reedijk 577b1d966cSNiels Sascha Reedijk // Details on the body status 583c9045fbSNiels Sascha Reedijk bool HasContent() const noexcept; 593c9045fbSNiels Sascha Reedijk std::optional<off_t> BodyBytesTotal() const noexcept; 603c9045fbSNiels Sascha Reedijk off_t BodyBytesTransferred() const noexcept; 61e6828456SNiels Sascha Reedijk bool Complete() const noexcept; 62e6828456SNiels Sascha Reedijk 63e6828456SNiels Sascha Reedijk private: 64e6828456SNiels Sascha Reedijk off_t fHeaderBytes = 0; 657b1d966cSNiels Sascha Reedijk BHttpStatus fStatus; 663c9045fbSNiels Sascha Reedijk HttpInputStreamState fStreamState = HttpInputStreamState::StatusLine; 677b1d966cSNiels Sascha Reedijk 683c9045fbSNiels Sascha Reedijk // Body 697b1d966cSNiels Sascha Reedijk HttpBodyType fBodyType = HttpBodyType::VariableSize; 703c9045fbSNiels Sascha Reedijk std::unique_ptr<HttpBodyParser> fBodyParser = nullptr; 713c9045fbSNiels Sascha Reedijk }; 72e6828456SNiels Sascha Reedijk 733c9045fbSNiels Sascha Reedijk 74*71e29bbeSNiels Sascha Reedijk class HttpBodyParser 75*71e29bbeSNiels Sascha Reedijk { 763c9045fbSNiels Sascha Reedijk public: 773c9045fbSNiels Sascha Reedijk virtual BodyParseResult ParseBody(HttpBuffer& buffer, 783c9045fbSNiels Sascha Reedijk HttpTransferFunction writeToBody, bool readEnd) = 0; 793c9045fbSNiels Sascha Reedijk 803c9045fbSNiels Sascha Reedijk virtual std::optional<off_t> TotalBodySize() const noexcept; 813c9045fbSNiels Sascha Reedijk 823c9045fbSNiels Sascha Reedijk off_t TransferredBodySize() const noexcept; 833c9045fbSNiels Sascha Reedijk 843c9045fbSNiels Sascha Reedijk protected: 853c9045fbSNiels Sascha Reedijk off_t fTransferredBodySize = 0; 863c9045fbSNiels Sascha Reedijk }; 873c9045fbSNiels Sascha Reedijk 883c9045fbSNiels Sascha Reedijk 89*71e29bbeSNiels Sascha Reedijk class HttpRawBodyParser : public HttpBodyParser 90*71e29bbeSNiels Sascha Reedijk { 913c9045fbSNiels Sascha Reedijk public: 923c9045fbSNiels Sascha Reedijk HttpRawBodyParser(); 933c9045fbSNiels Sascha Reedijk HttpRawBodyParser(off_t bodyBytesTotal); 94*71e29bbeSNiels Sascha Reedijk virtual BodyParseResult ParseBody(HttpBuffer& buffer, HttpTransferFunction writeToBody, 95*71e29bbeSNiels Sascha Reedijk bool readEnd) override; 963c9045fbSNiels Sascha Reedijk virtual std::optional<off_t> TotalBodySize() const noexcept override; 973c9045fbSNiels Sascha Reedijk 983c9045fbSNiels Sascha Reedijk private: 993c9045fbSNiels Sascha Reedijk std::optional<off_t> fBodyBytesTotal; 1003c9045fbSNiels Sascha Reedijk }; 1013c9045fbSNiels Sascha Reedijk 1023c9045fbSNiels Sascha Reedijk 103*71e29bbeSNiels Sascha Reedijk class HttpChunkedBodyParser : public HttpBodyParser 104*71e29bbeSNiels Sascha Reedijk { 1053c9045fbSNiels Sascha Reedijk public: 106*71e29bbeSNiels Sascha Reedijk virtual BodyParseResult ParseBody( 107*71e29bbeSNiels Sascha Reedijk HttpBuffer& buffer, HttpTransferFunction writeToBody, bool readEnd) override; 1083c9045fbSNiels Sascha Reedijk 1093c9045fbSNiels Sascha Reedijk private: 110*71e29bbeSNiels Sascha Reedijk enum { ChunkSize, ChunkEnd, Chunk, Trailers, Complete } fChunkParserState = ChunkSize; 111e6828456SNiels Sascha Reedijk off_t fRemainingChunkSize = 0; 112e6828456SNiels Sascha Reedijk bool fLastChunk = false; 1133c9045fbSNiels Sascha Reedijk }; 114e6828456SNiels Sascha Reedijk 115e6828456SNiels Sascha Reedijk 116*71e29bbeSNiels Sascha Reedijk class HttpBodyDecompression : public HttpBodyParser 117*71e29bbeSNiels Sascha Reedijk { 1183c9045fbSNiels Sascha Reedijk public: 119*71e29bbeSNiels Sascha Reedijk HttpBodyDecompression(std::unique_ptr<HttpBodyParser> bodyParser); 120*71e29bbeSNiels Sascha Reedijk virtual BodyParseResult ParseBody(HttpBuffer& buffer, HttpTransferFunction writeToBody, 121*71e29bbeSNiels Sascha Reedijk bool readEnd) override; 122e6828456SNiels Sascha Reedijk 1233c9045fbSNiels Sascha Reedijk virtual std::optional<off_t> TotalBodySize() const noexcept; 1243c9045fbSNiels Sascha Reedijk 1253c9045fbSNiels Sascha Reedijk private: 1263c9045fbSNiels Sascha Reedijk std::unique_ptr<HttpBodyParser> fBodyParser; 1273c9045fbSNiels Sascha Reedijk std::unique_ptr<BMallocIO> fDecompressorStorage; 1283c9045fbSNiels Sascha Reedijk std::unique_ptr<BDataIO> fDecompressingStream; 129e6828456SNiels Sascha Reedijk }; 130e6828456SNiels Sascha Reedijk 131e6828456SNiels Sascha Reedijk 132e6828456SNiels Sascha Reedijk } // namespace Network 133e6828456SNiels Sascha Reedijk 134e6828456SNiels Sascha Reedijk } // namespace BPrivate 135e6828456SNiels Sascha Reedijk 136e6828456SNiels Sascha Reedijk #endif // _B_HTTP_PARSER_H_ 137