From 4aca87d3e61aac12bdd56fadb90b45816a87e710 Mon Sep 17 00:00:00 2001 From: Lion Kortlepel Date: Mon, 15 Jan 2024 20:56:44 +0100 Subject: [PATCH] fully implement tcp and udp send and recv of packet types --- include/Network.h | 10 +++--- src/Network.cpp | 78 +++++++++++++++++++++++++++++++++-------------- 2 files changed, 60 insertions(+), 28 deletions(-) diff --git a/include/Network.h b/include/Network.h index 32f9f7d..2c09f70 100644 --- a/include/Network.h +++ b/include/Network.h @@ -28,11 +28,11 @@ struct Client { ClientID id; bmp::State state; - Packet tcp_read(boost::system::error_code& ec); - void tcp_write(const Packet& packet, boost::system::error_code& ec); - void tcp_write_file_raw(const std::filesystem::path& path, boost::system::error_code& ec); - Packet udp_read(boost::system::error_code& ec, ip::udp::socket& socket); - void udp_write(const Packet& packet, ip::udp::socket& socket, boost::system::error_code& ec); + Packet tcp_read(); + void tcp_write(const Packet& packet); + void tcp_write_file_raw(const std::filesystem::path& path); + Packet udp_read(ip::udp::socket& socket); + void udp_write(const Packet& packet, ip::udp::socket& socket); Client(ip::udp::endpoint& ep, ip::tcp::socket&& socket); ~Client(); diff --git a/src/Network.cpp b/src/Network.cpp index f47d054..a000fea 100644 --- a/src/Network.cpp +++ b/src/Network.cpp @@ -1,13 +1,33 @@ #include "Network.h" #include "Common.h" +#include "Environment.h" -Packet Client::tcp_read(boost::system::error_code& ec) { +#if defined(BEAMMP_LINUX) +#include +#include +#include +#include +#elif defined(BEAMMP_WINDOWS) +#else +#include +#endif + +Packet Client::tcp_read() { std::unique_lock lock(m_tcp_read_mtx); - return Packet(); - // CONTINUE + Packet packet{}; + std::vector header_buffer(bmp::Header::SERIALIZED_SIZE); + read(m_tcp_socket, buffer(header_buffer)); + bmp::Header hdr{}; + hdr.deserialize_from(header_buffer); + // vector eaten up by now, recv again + packet.data.resize(hdr.size); + read(m_tcp_socket, buffer(packet.data)); + packet.purpose = hdr.purpose; + packet.flags = hdr.flags; + return packet; } -void Client::tcp_write(const Packet& packet, boost::system::error_code& ec) { +void Client::tcp_write(const Packet& packet) { std::unique_lock lock(m_tcp_write_mtx); auto header = packet.header(); std::vector header_data(bmp::Header::SERIALIZED_SIZE); @@ -15,35 +35,31 @@ void Client::tcp_write(const Packet& packet, boost::system::error_code& ec) { beammp_errorf("Flags are not implemented"); } header.serialize_to(header_data); - write(m_tcp_socket, buffer(header_data), ec); - if (!ec) { - write(m_tcp_socket, buffer(packet.data), ec); - } + write(m_tcp_socket, buffer(header_data)); + write(m_tcp_socket, buffer(packet.data)); } -Packet Client::udp_read(boost::system::error_code& ec, ip::udp::socket& socket) { +Packet Client::udp_read(ip::udp::socket& socket) { // maximum we can ever expect from udp static thread_local std::vector s_buffer(std::numeric_limits::max()); std::unique_lock lock(m_udp_read_mtx); - socket.receive_from(buffer(s_buffer),m_udp_ep, {}, ec); - if (!ec) { - Packet packet; - bmp::Header header{}; - auto offset = header.deserialize_from(s_buffer); - if (header.flags != bmp::Flags::None) { - beammp_errorf("Flags are not implemented"); - return {}; - } + socket.receive_from(buffer(s_buffer), m_udp_ep, {}); + Packet packet; + bmp::Header header {}; + auto offset = header.deserialize_from(s_buffer); + if (header.flags != bmp::Flags::None) { + beammp_errorf("Flags are not implemented"); + return {}; } - return {}; + return packet; } -void Client::udp_write(const Packet& packet, ip::udp::socket& socket, boost::system::error_code& ec) { +void Client::udp_write(const Packet& packet, ip::udp::socket& socket) { auto header = packet.header(); std::vector data(header.size + bmp::Header::SERIALIZED_SIZE); auto offset = header.serialize_to(data); std::copy(packet.data.begin(), packet.data.end(), data.begin() + static_cast(offset)); - socket.send_to(buffer(data), m_udp_ep, {}, ec); + socket.send_to(buffer(data), m_udp_ep, {}); } Client::~Client() { @@ -54,10 +70,26 @@ Client::Client(ip::udp::endpoint& ep, ip::tcp::socket&& socket) : m_udp_ep(ep) , m_tcp_socket(std::forward(socket)) { } -void Client::tcp_write_file_raw(const std::filesystem::path& path, boost::system::error_code& ec) { +void Client::tcp_write_file_raw(const std::filesystem::path& path) { #if defined(BEAMMP_LINUX) -#elif defined(BEAMMP_WINDOWS) + // sendfile + auto size = std::filesystem::file_size(path); + auto in_fd = ::open(path.generic_string().c_str(), O_RDONLY); + if (in_fd == -1) { + throw std::runtime_error(fmt::format("IO error opening '{}': {}", path.generic_string(), std::strerror(errno))); + } + int out_fd = m_tcp_socket.native_handle(); + auto n = sendfile(out_fd, in_fd, nullptr /* offset */, size); + ::close(in_fd); + if (n == -1) { + throw std::runtime_error(fmt::format("Failed sending '{}' to client via sendfile(): {}", path.generic_string(), std::strerror(errno))); + } #else + // TODO: Use TransmitFile on Windows for better performance + // primitive implementation using a memory-mapped file + boost::iostreams::mapped_file f(path.generic_string(), boost::iostreams::mapped_file::mapmode::readonly); + std::unique_lock lock(m_tcp_write_mtx); + write(m_tcp_socket, buffer(f.data(), f.size())); #endif } bmp::Header Packet::header() const {