Skip to content

Commit

Permalink
feat: rework interface and reading
Browse files Browse the repository at this point in the history
- 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
  • Loading branch information
daedric committed Jul 13, 2023
1 parent acfbb0f commit d87417e
Show file tree
Hide file tree
Showing 16 changed files with 1,240 additions and 2,097 deletions.
4 changes: 2 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,8 @@ option(BUILD_SHARED_LIBS "Build shared lib instead of static ones")

# Setting vars #################################################################
set(HTTPP_VERSION_MAJOR "0")
set(HTTPP_VERSION_MINOR "8")
set(HTTPP_VERSION_PATCH "0")
set(HTTPP_VERSION_MINOR "9")
set(HTTPP_VERSION_PATCH "0~pre-alpha")

set(CPACK_PACKAGE_VERSION_MAJOR ${HTTPP_VERSION_MAJOR})
set(CPACK_PACKAGE_VERSION_MINOR ${HTTPP_VERSION_MINOR})
Expand Down
128 changes: 99 additions & 29 deletions include/httpp/http/Connection.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,29 +90,31 @@ class Connection
throw std::logic_error("Invalid connection state");
}

size_t offset = 0;

if (not body_buffer_.empty())
auto already_read = request_buffer_.size() - offset_body_start_;
if (already_read)
{
if (size <= body_buffer_.size())
if (size <= already_read)
{
std::copy(begin(body_buffer_), begin(body_buffer_) + size, buffer);
body_buffer_.erase(begin(body_buffer_), begin(body_buffer_) + size);
offset_body_end_ = offset_body_start_ + size;
std::copy(
request_buffer_.begin() + offset_body_start_,
request_buffer_.begin() + offset_body_end_,
buffer
);
disown();
callable(boost::system::error_code());
return;
}
else
{
std::copy(begin(body_buffer_), end(body_buffer_), buffer);
size -= body_buffer_.size();
offset += body_buffer_.size();
body_buffer_.clear();
}
std::copy(
request_buffer_.begin() + offset_body_start_, request_buffer_.end(), buffer
);
size -= already_read;
request_buffer_.resize(offset_body_start_);
}

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

if (not body_buffer_.empty())
auto already_read = request_buffer_.size() - offset_body_start_;
if (already_read)
{
if (body_size <= body_buffer_.size())
auto body_start = request_buffer_.data() + offset_body_start_;
if (body_size <= already_read)
{
callable(boost::system::error_code(), body_buffer_.data(), body_size);
body_buffer_.erase(begin(body_buffer_), begin(body_buffer_) + body_size);
offset_body_end_ = offset_body_start_ + body_size;
callable(boost::system::error_code(), body_start, already_read);
body_size = 0;
}
else
{
callable(
boost::system::error_code(),
body_buffer_.data(),
body_buffer_.size()
);
body_size -= body_buffer_.size();
body_buffer_.clear();
callable(boost::system::error_code(), body_start, already_read);
body_size -= already_read;
}
}

Expand All @@ -165,12 +164,19 @@ class Connection
return;
}

offset_body_end_ = offset_body_start_;
auto buf_size = std::min(BUFFER_SIZE, body_size);

body_buffer_.resize(buf_size);
auto capacity = request_buffer_.capacity() - offset_body_start_;
if (capacity < buf_size)
{
request_buffer_.reserve(offset_body_start_ + buf_size + 1);
reparse();
}

request_buffer_.resize(offset_body_start_ + buf_size);
async_read_some(
boost::asio::buffer(body_buffer_),
boost::asio::buffer(request_buffer_.data() + offset_body_start_, buf_size),
[body_size,
callable = std::move(callable),
this](const boost::system::error_code& ec, size_t size) mutable
Expand All @@ -185,14 +191,77 @@ class Connection
return;
}

body_buffer_.resize(size);
request_buffer_.resize(offset_body_start_ + size);
read(body_size, std::move(callable));
}
);
}

template <typename Callable>
void read_whole(size_t body_size, Callable callable)
{
if (!own())
{
throw std::logic_error("Invalid connection state");
}

auto already_read = request_buffer_.size() - offset_body_start_;
offset_body_end_ = offset_body_start_ + body_size;
if (already_read)
{
if (body_size <= already_read)
{
callable(boost::system::error_code());
return;
}
}

if (!body_size)
{
disown();
callable(boost::system::error_code());
return;
}

auto missing = body_size - already_read;

// +1 for an hypothetical \0
auto capacity = offset_body_end_ + 1;
if (request_buffer_.capacity() < capacity)
{
request_buffer_.reserve(capacity);
// pointer might have changed, so we need to reconstruct header,
// path, etc.
reparse();
}

request_buffer_.resize(offset_body_end_);
async_read(
boost::asio::buffer(request_buffer_.data() + offset_body_end_ - missing, missing),
[callable = std::move(callable),
this](const boost::system::error_code& ec, size_t size) mutable
{
disown();

if (ec)
{
LOG(connection_detail::conn_logger_, error)
<< "Error detected while reading the body";
callable(ec);
return;
}

callable(boost::system::error_code());
}
);
}

void sendResponse();
void sendContinue(Callback&& cb);
std::pair<char*, size_t> mutable_body();

private:
void reparse();

private:
static void release(Connection* connection);
Expand Down Expand Up @@ -246,8 +315,9 @@ class Connection
std::atomic_bool is_owned_ = {false};
bool should_be_deleted_ = {false};
std::vector<char> request_buffer_;
std::vector<char> body_buffer_;
size_t size_ = 0;
size_t offset_body_start_ = 0;
size_t offset_body_end_ = 0;

std::mutex mutex_;

Expand Down
8 changes: 4 additions & 4 deletions include/httpp/http/Protocol.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#define HTTPP_HTTP_PROTOCOL_HPP_

#include <string>
#include <string_view>

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

Expand Down Expand Up @@ -48,9 +49,8 @@ enum class Method
CONNECT
};

std::string to_string(Method method);
Method method_from(const std::string& str);
Method method_from(const char* str);
std::string_view to_string(Method method);
Method method_from(std::string_view str);

enum class HttpCode : unsigned int
{
Expand Down Expand Up @@ -106,7 +106,7 @@ enum class HttpCode : unsigned int
HttpVersionNotSupported = 505
};

const char* getDefaultMessage(HttpCode code);
std::string_view getDefaultMessage(HttpCode code);

} // namespace HTTP
} // namespace HTTPP
Expand Down
Loading

0 comments on commit d87417e

Please sign in to comment.