xref: /haiku/src/kits/network/libnetservices2/HttpParser.h (revision 7b1d966cf27635973aa04ebcad1c8b167003a692)
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