Skip to content

Commit

Permalink
Add userspace codepath for coro_send_file
Browse files Browse the repository at this point in the history
  • Loading branch information
loonycyborg committed Mar 11, 2021
1 parent bb18675 commit 798618d
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 17 deletions.
23 changes: 8 additions & 15 deletions src/server/campaignd/server.cpp
Expand Up @@ -1149,16 +1149,11 @@ void server::handle_request_campaign(const server::request& req)
}

LOG_CS << req << "Sending add-on '" << name << "' version: " << to << " size: " << full_pack_size / 1024 << " KiB\n";
if(auto sock = utils::get_if<socket_ptr>(&req.sock)) {
utils::visit([this, &req, &full_pack_path](auto&& socket) {
boost::system::error_code ec;
coro_send_file(*sock, full_pack_path, req.yield[ec]);
if(check_error(ec, *sock)) return;
} else {
// FIXME: need to decide what to do about sending addons over TLS.
// sendfile is low level api so either drop TLS for this part
// or don't use sendfile at all.
ERR_CS << "Not sending addon over TLS yet\n";
}
coro_send_file(socket, full_pack_path, req.yield[ec]);
if(check_error(ec, socket)) return;
}, req.sock);
}

// Clients doing upgrades or some other specific thing shouldn't bump
Expand Down Expand Up @@ -1210,13 +1205,11 @@ void server::handle_request_campaign_hash(const server::request& req)
}

LOG_CS << req << "Sending add-on hash index for '" << req.cfg["name"] << "' size: " << file_size / 1024 << " KiB\n";
if(auto sock = utils::get_if<socket_ptr>(&req.sock)) {
utils::visit([this, &path, &req](auto&& socket) {
boost::system::error_code ec;
coro_send_file(*sock, path, req.yield[ec]);
if(check_error(ec, *sock)) return;
} else {
ERR_CS << "No sendfile over TLS\n";
}
coro_send_file(socket, path, req.yield[ec]);
if(check_error(ec, socket)) return;
}, req.sock);
}
}

Expand Down
38 changes: 36 additions & 2 deletions src/server/common/server_base.cpp
Expand Up @@ -309,10 +309,38 @@ template<class SocketPtr> void server_base::coro_send_doc(SocketPtr socket, simp
template void server_base::coro_send_doc<socket_ptr>(socket_ptr socket, simple_wml::document& doc, boost::asio::yield_context yield);
template void server_base::coro_send_doc<tls_socket_ptr>(tls_socket_ptr socket, simple_wml::document& doc, boost::asio::yield_context yield);

template<class SocketPtr> void coro_send_file_userspace(SocketPtr socket, const std::string& filename, boost::asio::yield_context yield)
{
std::size_t filesize { std::size_t(filesystem::file_size(filename)) };
union DataSize
{
uint32_t size;
char buf[4];
} data_size {};
data_size.size = htonl(filesize);

async_write(*socket, boost::asio::buffer(data_size.buf), yield);

auto ifs { filesystem::istream_file(filename) };
ifs->seekg(0);
while(ifs->good()) {
char buf[16384];
ifs->read(buf, sizeof(buf));
async_write(*socket, boost::asio::buffer(buf, ifs->gcount()), yield);
}
}

#ifdef HAVE_SENDFILE

template<class SocketPtr> void server_base::coro_send_file(SocketPtr socket, const std::string& filename, boost::asio::yield_context yield)
{
// We fallback to userspace if using TLS socket because sendfile is not aware of TLS state
// TODO: keep in mind possibility of using KTLS instead. This seem to be available only in openssl3 branch for now
if constexpr (utils::decayed_is_same<tls_socket_ptr, decltype(socket)>) {
coro_send_file_userspace(socket, filename, yield);
return;
} else {

std::size_t filesize { std::size_t(filesystem::file_size(filename)) };
int in_file { open(filename.c_str(), O_RDONLY) };
off_t offset { 0 };
Expand Down Expand Up @@ -364,12 +392,17 @@ template<class SocketPtr> void server_base::coro_send_file(SocketPtr socket, con

// Loop around to try calling sendfile again.
}
}
}

#elif defined(_WIN32)

template<class SocketPtr> void server_base::coro_send_file(SocketPtr socket, const std::string& filename, boost::asio::yield_context yield)
{
if constexpr (utils::decayed_is_same<tls_socket_ptr, decltype(socket)>) {
coro_send_file_userspace(socket, filename, yield);
return;
} else {

OVERLAPPED overlap;
std::vector<boost::asio::const_buffer> buffers;
Expand Down Expand Up @@ -425,19 +458,20 @@ template<class SocketPtr> void server_base::coro_send_file(SocketPtr socket, con
throw std::runtime_error("TransmitFile failed");
}
}
}
}

#else

template<class SocketPtr> void server_base::coro_send_file(SocketPtr socket, const std::string& filename, boost::asio::yield_context yield)
{
// TODO: Implement this for systems without sendfile()
assert(false && "Not implemented yet");
coro_send_file_userspace(socket, filename, yield);
}

#endif

template void server_base::coro_send_file<socket_ptr>(socket_ptr socket, const std::string& filename, boost::asio::yield_context yield);
template void server_base::coro_send_file<tls_socket_ptr>(tls_socket_ptr socket, const std::string& filename, boost::asio::yield_context yield);

template<class SocketPtr> std::unique_ptr<simple_wml::document> server_base::coro_receive_doc(SocketPtr socket, boost::asio::yield_context yield)
{
Expand Down

0 comments on commit 798618d

Please sign in to comment.