mirror of
https://github.com/BeamMP/BeamMP-Server.git
synced 2025-07-04 00:36:14 +00:00
fully implement tcp and udp send and recv of packet types
This commit is contained in:
parent
7e9bb0cbf2
commit
4aca87d3e6
@ -28,11 +28,11 @@ struct Client {
|
|||||||
ClientID id;
|
ClientID id;
|
||||||
bmp::State state;
|
bmp::State state;
|
||||||
|
|
||||||
Packet tcp_read(boost::system::error_code& ec);
|
Packet tcp_read();
|
||||||
void tcp_write(const Packet& packet, boost::system::error_code& ec);
|
void tcp_write(const Packet& packet);
|
||||||
void tcp_write_file_raw(const std::filesystem::path& path, boost::system::error_code& ec);
|
void tcp_write_file_raw(const std::filesystem::path& path);
|
||||||
Packet udp_read(boost::system::error_code& ec, ip::udp::socket& socket);
|
Packet udp_read(ip::udp::socket& socket);
|
||||||
void udp_write(const Packet& packet, ip::udp::socket& socket, boost::system::error_code& ec);
|
void udp_write(const Packet& packet, ip::udp::socket& socket);
|
||||||
|
|
||||||
Client(ip::udp::endpoint& ep, ip::tcp::socket&& socket);
|
Client(ip::udp::endpoint& ep, ip::tcp::socket&& socket);
|
||||||
~Client();
|
~Client();
|
||||||
|
@ -1,13 +1,33 @@
|
|||||||
#include "Network.h"
|
#include "Network.h"
|
||||||
#include "Common.h"
|
#include "Common.h"
|
||||||
|
#include "Environment.h"
|
||||||
|
|
||||||
Packet Client::tcp_read(boost::system::error_code& ec) {
|
#if defined(BEAMMP_LINUX)
|
||||||
|
#include <cstring>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <sys/sendfile.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#elif defined(BEAMMP_WINDOWS)
|
||||||
|
#else
|
||||||
|
#include <boost/iostreams/device/mapped_file.hpp>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
Packet Client::tcp_read() {
|
||||||
std::unique_lock lock(m_tcp_read_mtx);
|
std::unique_lock lock(m_tcp_read_mtx);
|
||||||
return Packet();
|
Packet packet{};
|
||||||
// CONTINUE
|
std::vector<uint8_t> 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);
|
std::unique_lock lock(m_tcp_write_mtx);
|
||||||
auto header = packet.header();
|
auto header = packet.header();
|
||||||
std::vector<uint8_t> header_data(bmp::Header::SERIALIZED_SIZE);
|
std::vector<uint8_t> 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");
|
beammp_errorf("Flags are not implemented");
|
||||||
}
|
}
|
||||||
header.serialize_to(header_data);
|
header.serialize_to(header_data);
|
||||||
write(m_tcp_socket, buffer(header_data), ec);
|
write(m_tcp_socket, buffer(header_data));
|
||||||
if (!ec) {
|
write(m_tcp_socket, buffer(packet.data));
|
||||||
write(m_tcp_socket, buffer(packet.data), ec);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
// maximum we can ever expect from udp
|
||||||
static thread_local std::vector<uint8_t> s_buffer(std::numeric_limits<uint16_t>::max());
|
static thread_local std::vector<uint8_t> s_buffer(std::numeric_limits<uint16_t>::max());
|
||||||
std::unique_lock lock(m_udp_read_mtx);
|
std::unique_lock lock(m_udp_read_mtx);
|
||||||
socket.receive_from(buffer(s_buffer),m_udp_ep, {}, ec);
|
socket.receive_from(buffer(s_buffer), m_udp_ep, {});
|
||||||
if (!ec) {
|
Packet packet;
|
||||||
Packet packet;
|
bmp::Header header {};
|
||||||
bmp::Header header{};
|
auto offset = header.deserialize_from(s_buffer);
|
||||||
auto offset = header.deserialize_from(s_buffer);
|
if (header.flags != bmp::Flags::None) {
|
||||||
if (header.flags != bmp::Flags::None) {
|
beammp_errorf("Flags are not implemented");
|
||||||
beammp_errorf("Flags are not implemented");
|
return {};
|
||||||
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();
|
auto header = packet.header();
|
||||||
std::vector<uint8_t> data(header.size + bmp::Header::SERIALIZED_SIZE);
|
std::vector<uint8_t> data(header.size + bmp::Header::SERIALIZED_SIZE);
|
||||||
auto offset = header.serialize_to(data);
|
auto offset = header.serialize_to(data);
|
||||||
std::copy(packet.data.begin(), packet.data.end(), data.begin() + static_cast<long>(offset));
|
std::copy(packet.data.begin(), packet.data.end(), data.begin() + static_cast<long>(offset));
|
||||||
socket.send_to(buffer(data), m_udp_ep, {}, ec);
|
socket.send_to(buffer(data), m_udp_ep, {});
|
||||||
}
|
}
|
||||||
|
|
||||||
Client::~Client() {
|
Client::~Client() {
|
||||||
@ -54,10 +70,26 @@ Client::Client(ip::udp::endpoint& ep, ip::tcp::socket&& socket)
|
|||||||
: m_udp_ep(ep)
|
: m_udp_ep(ep)
|
||||||
, m_tcp_socket(std::forward<ip::tcp::socket&&>(socket)) {
|
, m_tcp_socket(std::forward<ip::tcp::socket&&>(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)
|
#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
|
#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
|
#endif
|
||||||
}
|
}
|
||||||
bmp::Header Packet::header() const {
|
bmp::Header Packet::header() const {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user