Skip to content

Commit 22a8df8

Browse files
committed
feat: rework interface and reading
- remove the body_buffer_ - add a read_whole function to ready the whole body within the current buffer - It means that the request can point on the old header, so any change in capacity must trigger a parsing of the header - remove char* for string_view and update accordingly ragel parser
1 parent acfbb0f commit 22a8df8

File tree

16 files changed

+1239
-2097
lines changed

16 files changed

+1239
-2097
lines changed

CMakeLists.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,8 @@ option(BUILD_SHARED_LIBS "Build shared lib instead of static ones")
5454

5555
# Setting vars #################################################################
5656
set(HTTPP_VERSION_MAJOR "0")
57-
set(HTTPP_VERSION_MINOR "8")
58-
set(HTTPP_VERSION_PATCH "0")
57+
set(HTTPP_VERSION_MINOR "9")
58+
set(HTTPP_VERSION_PATCH "0~pre-alpha")
5959

6060
set(CPACK_PACKAGE_VERSION_MAJOR ${HTTPP_VERSION_MAJOR})
6161
set(CPACK_PACKAGE_VERSION_MINOR ${HTTPP_VERSION_MINOR})

include/httpp/http/Connection.hpp

Lines changed: 99 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -90,29 +90,31 @@ class Connection
9090
throw std::logic_error("Invalid connection state");
9191
}
9292

93-
size_t offset = 0;
94-
95-
if (not body_buffer_.empty())
93+
auto already_read = request_buffer_.size() - offset_body_start_;
94+
if (already_read)
9695
{
97-
if (size <= body_buffer_.size())
96+
if (size <= already_read)
9897
{
99-
std::copy(begin(body_buffer_), begin(body_buffer_) + size, buffer);
100-
body_buffer_.erase(begin(body_buffer_), begin(body_buffer_) + size);
98+
offset_body_end_ = offset_body_start_ + size;
99+
std::copy(
100+
request_buffer_.begin() + offset_body_start_,
101+
request_buffer_.begin() + offset_body_end_,
102+
buffer
103+
);
101104
disown();
102105
callable(boost::system::error_code());
103106
return;
104107
}
105-
else
106-
{
107-
std::copy(begin(body_buffer_), end(body_buffer_), buffer);
108-
size -= body_buffer_.size();
109-
offset += body_buffer_.size();
110-
body_buffer_.clear();
111-
}
108+
std::copy(
109+
request_buffer_.begin() + offset_body_start_, request_buffer_.end(), buffer
110+
);
111+
size -= already_read;
112+
request_buffer_.resize(offset_body_start_);
112113
}
113114

115+
offset_body_end_ = offset_body_start_;
114116
async_read(
115-
boost::asio::buffer(buffer + offset, size),
117+
boost::asio::buffer(buffer + already_read, size),
116118
[callable = std::move(callable), this](const boost::system::error_code& ec, size_t) mutable
117119
{
118120
disown();
@@ -138,23 +140,20 @@ class Connection
138140
throw std::logic_error("Invalid connection state");
139141
}
140142

141-
if (not body_buffer_.empty())
143+
auto already_read = request_buffer_.size() - offset_body_start_;
144+
if (already_read)
142145
{
143-
if (body_size <= body_buffer_.size())
146+
auto body_start = request_buffer_.data() + offset_body_start_;
147+
if (body_size <= already_read)
144148
{
145-
callable(boost::system::error_code(), body_buffer_.data(), body_size);
146-
body_buffer_.erase(begin(body_buffer_), begin(body_buffer_) + body_size);
149+
offset_body_end_ = offset_body_start_ + body_size;
150+
callable(boost::system::error_code(), body_start, already_read);
147151
body_size = 0;
148152
}
149153
else
150154
{
151-
callable(
152-
boost::system::error_code(),
153-
body_buffer_.data(),
154-
body_buffer_.size()
155-
);
156-
body_size -= body_buffer_.size();
157-
body_buffer_.clear();
155+
callable(boost::system::error_code(), body_start, already_read);
156+
body_size -= already_read;
158157
}
159158
}
160159

@@ -165,12 +164,19 @@ class Connection
165164
return;
166165
}
167166

167+
offset_body_end_ = offset_body_start_;
168168
auto buf_size = std::min(BUFFER_SIZE, body_size);
169169

170-
body_buffer_.resize(buf_size);
170+
auto capacity = request_buffer_.capacity() - offset_body_start_;
171+
if (capacity < buf_size)
172+
{
173+
request_buffer_.reserve(offset_body_start_ + buf_size + 1);
174+
reparse();
175+
}
171176

177+
request_buffer_.resize(offset_body_start_ + buf_size);
172178
async_read_some(
173-
boost::asio::buffer(body_buffer_),
179+
boost::asio::buffer(request_buffer_.data() + offset_body_start_, buf_size),
174180
[body_size,
175181
callable = std::move(callable),
176182
this](const boost::system::error_code& ec, size_t size) mutable
@@ -185,14 +191,77 @@ class Connection
185191
return;
186192
}
187193

188-
body_buffer_.resize(size);
194+
request_buffer_.resize(offset_body_start_ + size);
189195
read(body_size, std::move(callable));
190196
}
191197
);
192198
}
193199

200+
template <typename Callable>
201+
void read_whole(size_t body_size, Callable callable)
202+
{
203+
if (!own())
204+
{
205+
throw std::logic_error("Invalid connection state");
206+
}
207+
208+
auto already_read = request_buffer_.size() - offset_body_start_;
209+
offset_body_end_ = offset_body_start_ + body_size;
210+
if (already_read)
211+
{
212+
if (body_size <= already_read)
213+
{
214+
callable(boost::system::error_code());
215+
return;
216+
}
217+
}
218+
219+
if (!body_size)
220+
{
221+
disown();
222+
callable(boost::system::error_code());
223+
return;
224+
}
225+
226+
auto missing = body_size - already_read;
227+
228+
// +1 for an hypothetical \0
229+
auto capacity = offset_body_end_ + 1;
230+
if (request_buffer_.capacity() < capacity)
231+
{
232+
request_buffer_.reserve(capacity);
233+
// pointer might have changed, so we need to reconstruct header,
234+
// path, etc.
235+
reparse();
236+
}
237+
238+
request_buffer_.resize(offset_body_end_);
239+
async_read(
240+
boost::asio::buffer(request_buffer_.data() + offset_body_end_ - missing, missing),
241+
[callable = std::move(callable),
242+
this](const boost::system::error_code& ec, size_t size) mutable
243+
{
244+
disown();
245+
246+
if (ec)
247+
{
248+
LOG(connection_detail::conn_logger_, error)
249+
<< "Error detected while reading the body";
250+
callable(ec);
251+
return;
252+
}
253+
254+
callable(boost::system::error_code());
255+
}
256+
);
257+
}
258+
194259
void sendResponse();
195260
void sendContinue(Callback&& cb);
261+
std::pair<char*, size_t> mutable_body();
262+
263+
private:
264+
void reparse();
196265

197266
private:
198267
static void release(Connection* connection);
@@ -246,8 +315,9 @@ class Connection
246315
std::atomic_bool is_owned_ = {false};
247316
bool should_be_deleted_ = {false};
248317
std::vector<char> request_buffer_;
249-
std::vector<char> body_buffer_;
250318
size_t size_ = 0;
319+
size_t offset_body_start_ = 0;
320+
size_t offset_body_end_ = 0;
251321

252322
std::mutex mutex_;
253323

include/httpp/http/Protocol.hpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#define HTTPP_HTTP_PROTOCOL_HPP_
1313

1414
#include <string>
15+
#include <string_view>
1516

1617
#include <commonpp/core/string/std_tostring.hpp>
1718

@@ -48,9 +49,8 @@ enum class Method
4849
CONNECT
4950
};
5051

51-
std::string to_string(Method method);
52-
Method method_from(const std::string& str);
53-
Method method_from(const char* str);
52+
std::string_view to_string(Method method);
53+
Method method_from(std::string_view str);
5454

5555
enum class HttpCode : unsigned int
5656
{
@@ -106,7 +106,7 @@ enum class HttpCode : unsigned int
106106
HttpVersionNotSupported = 505
107107
};
108108

109-
const char* getDefaultMessage(HttpCode code);
109+
std::string_view getDefaultMessage(HttpCode code);
110110

111111
} // namespace HTTP
112112
} // namespace HTTPP

0 commit comments

Comments
 (0)