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 26e6828456SNiels Sascha Reedijk enum class HttpBodyInputStreamState { 27e6828456SNiels Sascha Reedijk ChunkSize, 28e6828456SNiels Sascha Reedijk ChunkEnd, 29e6828456SNiels Sascha Reedijk Chunk, 30e6828456SNiels Sascha Reedijk Trailers, 31e6828456SNiels Sascha Reedijk Done 32e6828456SNiels Sascha Reedijk }; 33e6828456SNiels Sascha Reedijk 34e6828456SNiels Sascha Reedijk 35*7b1d966cSNiels Sascha Reedijk enum class HttpBodyType { 36*7b1d966cSNiels Sascha Reedijk NoContent, 37*7b1d966cSNiels Sascha Reedijk Chunked, 38*7b1d966cSNiels Sascha Reedijk FixedSize, 39*7b1d966cSNiels Sascha Reedijk VariableSize 40*7b1d966cSNiels Sascha Reedijk }; 41*7b1d966cSNiels Sascha Reedijk 42*7b1d966cSNiels Sascha Reedijk 43e6828456SNiels Sascha Reedijk class HttpParser { 44e6828456SNiels Sascha Reedijk public: 45e6828456SNiels Sascha Reedijk HttpParser() {}; 46e6828456SNiels Sascha Reedijk 47*7b1d966cSNiels Sascha Reedijk // Explicitly mark request as having no content 48*7b1d966cSNiels Sascha Reedijk void SetNoContent() { fBodyType = HttpBodyType::NoContent; }; 49*7b1d966cSNiels Sascha Reedijk 50e6828456SNiels Sascha Reedijk // HTTP Header 51e6828456SNiels Sascha Reedijk bool ParseStatus(HttpBuffer& buffer, BHttpStatus& status); 52e6828456SNiels Sascha Reedijk bool ParseFields(HttpBuffer& buffer, BHttpFields& fields); 53e6828456SNiels Sascha Reedijk 54e6828456SNiels Sascha Reedijk // HTTP Body 55e6828456SNiels Sascha Reedijk size_t ParseBody(HttpBuffer& buffer, HttpTransferFunction writeToBody); 56*7b1d966cSNiels Sascha Reedijk void SetConnectionClosed(); 57*7b1d966cSNiels Sascha Reedijk 58*7b1d966cSNiels Sascha Reedijk // Details on the body status 59*7b1d966cSNiels Sascha Reedijk bool HasContent() const noexcept { return fBodyType != HttpBodyType::NoContent; }; 60e6828456SNiels Sascha Reedijk std::optional<off_t> BodyBytesTotal() const noexcept { return fBodyBytesTotal; }; 61e6828456SNiels Sascha Reedijk off_t BodyBytesTransferred() const noexcept { return fTransferredBodySize; }; 62e6828456SNiels Sascha Reedijk bool Complete() const noexcept; 63e6828456SNiels Sascha Reedijk 64e6828456SNiels Sascha Reedijk private: 65*7b1d966cSNiels Sascha Reedijk void _SetGzipCompression(); 66e6828456SNiels Sascha Reedijk size_t _ParseBodyRaw(HttpBuffer& buffer, HttpTransferFunction writeToBody); 67e6828456SNiels Sascha Reedijk size_t _ParseBodyChunked(HttpBuffer& buffer, HttpTransferFunction writeToBody); 68e6828456SNiels Sascha Reedijk size_t _ReadChunk(HttpBuffer& buffer, HttpTransferFunction writeToBody, 69e6828456SNiels Sascha Reedijk size_t maxSize, bool flush); 70e6828456SNiels Sascha Reedijk 71e6828456SNiels Sascha Reedijk private: 72e6828456SNiels Sascha Reedijk off_t fHeaderBytes = 0; 73*7b1d966cSNiels Sascha Reedijk BHttpStatus fStatus; 74*7b1d966cSNiels Sascha Reedijk 75*7b1d966cSNiels Sascha Reedijk // Body type 76*7b1d966cSNiels Sascha Reedijk HttpBodyType fBodyType = HttpBodyType::VariableSize; 77e6828456SNiels Sascha Reedijk 78e6828456SNiels Sascha Reedijk // Support for chunked transfers 79e6828456SNiels Sascha Reedijk HttpBodyInputStreamState fBodyState = HttpBodyInputStreamState::ChunkSize; 80e6828456SNiels Sascha Reedijk off_t fRemainingChunkSize = 0; 81e6828456SNiels Sascha Reedijk bool fLastChunk = false; 82e6828456SNiels Sascha Reedijk 83e6828456SNiels Sascha Reedijk // Receive stats 84e6828456SNiels Sascha Reedijk std::optional<off_t> fBodyBytesTotal = 0; 85e6828456SNiels Sascha Reedijk off_t fTransferredBodySize = 0; 86e6828456SNiels Sascha Reedijk 87e6828456SNiels Sascha Reedijk // Optional decompression 88e6828456SNiels Sascha Reedijk std::unique_ptr<BMallocIO> fDecompressorStorage = nullptr; 89e6828456SNiels Sascha Reedijk std::unique_ptr<BDataIO> fDecompressingStream = nullptr; 90e6828456SNiels Sascha Reedijk 91e6828456SNiels Sascha Reedijk }; 92e6828456SNiels Sascha Reedijk 93e6828456SNiels Sascha Reedijk 94e6828456SNiels Sascha Reedijk } // namespace Network 95e6828456SNiels Sascha Reedijk 96e6828456SNiels Sascha Reedijk } // namespace BPrivate 97e6828456SNiels Sascha Reedijk 98e6828456SNiels Sascha Reedijk #endif // _B_HTTP_PARSER_H_ 99