1/* 2 * Copyright 2022 Haiku Inc. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 */ 5 6#ifndef _B_HTTP_PARSER_H_ 7#define _B_HTTP_PARSER_H_ 8 9 10#include <functional> 11#include <optional> 12 13#include <HttpResult.h> 14 15#include "HttpBuffer.h" 16 17class BMallocIO; 18 19namespace BPrivate { 20 21namespace Network { 22 23using HttpTransferFunction = std::function<size_t(const std::byte*, size_t)>; 24 25 26enum class HttpInputStreamState { StatusLine, Fields, Body, Done }; 27 28 29enum class HttpBodyType { NoContent, Chunked, FixedSize, VariableSize }; 30 31 32struct BodyParseResult { 33 size_t bytesParsed; 34 size_t bytesWritten; 35 bool complete; 36}; 37 38 39class HttpBodyParser; 40 41 42class HttpParser 43{ 44public: 45 HttpParser(){}; 46 47 // Explicitly mark request as having no content 48 void SetNoContent() noexcept; 49 50 // Parse data from response 51 bool ParseStatus(HttpBuffer& buffer, BHttpStatus& status); 52 bool ParseFields(HttpBuffer& buffer, BHttpFields& fields); 53 size_t ParseBody(HttpBuffer& buffer, HttpTransferFunction writeToBody, 54 bool readEnd); 55 HttpInputStreamState State() const noexcept { return fStreamState; } 56 57 // Details on the body status 58 bool HasContent() const noexcept; 59 std::optional<off_t> BodyBytesTotal() const noexcept; 60 off_t BodyBytesTransferred() const noexcept; 61 bool Complete() const noexcept; 62 63private: 64 off_t fHeaderBytes = 0; 65 BHttpStatus fStatus; 66 HttpInputStreamState fStreamState = HttpInputStreamState::StatusLine; 67 68 // Body 69 HttpBodyType fBodyType = HttpBodyType::VariableSize; 70 std::unique_ptr<HttpBodyParser> fBodyParser = nullptr; 71}; 72 73 74class HttpBodyParser 75{ 76public: 77 virtual BodyParseResult ParseBody(HttpBuffer& buffer, 78 HttpTransferFunction writeToBody, bool readEnd) = 0; 79 80 virtual std::optional<off_t> TotalBodySize() const noexcept; 81 82 off_t TransferredBodySize() const noexcept; 83 84protected: 85 off_t fTransferredBodySize = 0; 86}; 87 88 89class HttpRawBodyParser : public HttpBodyParser 90{ 91public: 92 HttpRawBodyParser(); 93 HttpRawBodyParser(off_t bodyBytesTotal); 94 virtual BodyParseResult ParseBody(HttpBuffer& buffer, HttpTransferFunction writeToBody, 95 bool readEnd) override; 96 virtual std::optional<off_t> TotalBodySize() const noexcept override; 97 98private: 99 std::optional<off_t> fBodyBytesTotal; 100}; 101 102 103class HttpChunkedBodyParser : public HttpBodyParser 104{ 105public: 106 virtual BodyParseResult ParseBody( 107 HttpBuffer& buffer, HttpTransferFunction writeToBody, bool readEnd) override; 108 109private: 110 enum { ChunkSize, ChunkEnd, Chunk, Trailers, Complete } fChunkParserState = ChunkSize; 111 off_t fRemainingChunkSize = 0; 112 bool fLastChunk = false; 113}; 114 115 116class HttpBodyDecompression : public HttpBodyParser 117{ 118public: 119 HttpBodyDecompression(std::unique_ptr<HttpBodyParser> bodyParser); 120 virtual BodyParseResult ParseBody(HttpBuffer& buffer, HttpTransferFunction writeToBody, 121 bool readEnd) override; 122 123 virtual std::optional<off_t> TotalBodySize() const noexcept; 124 125private: 126 std::unique_ptr<HttpBodyParser> fBodyParser; 127 std::unique_ptr<BMallocIO> fDecompressorStorage; 128 std::unique_ptr<BDataIO> fDecompressingStream; 129}; 130 131 132} // namespace Network 133 134} // namespace BPrivate 135 136#endif // _B_HTTP_PARSER_H_ 137