summaryrefslogtreecommitdiff
path: root/include/net
diff options
context:
space:
mode:
Diffstat (limited to 'include/net')
-rw-r--r--include/net/client.hpp2
-rw-r--r--include/net/conn.hpp90
-rw-r--r--include/net/packet.hpp27
-rw-r--r--include/net/server.hpp2
-rw-r--r--include/net/types.hpp189
5 files changed, 42 insertions, 268 deletions
diff --git a/include/net/client.hpp b/include/net/client.hpp
index 23d250b..87b0ea1 100644
--- a/include/net/client.hpp
+++ b/include/net/client.hpp
@@ -23,7 +23,7 @@
namespace net {
class client {
- struct sockaddr_in server_address { };
+ struct sockaddr_in server_address {};
public:
client(std::string hostname, int port)
diff --git a/include/net/conn.hpp b/include/net/conn.hpp
index 95992ed..6f57293 100644
--- a/include/net/conn.hpp
+++ b/include/net/conn.hpp
@@ -9,15 +9,17 @@
#include <netinet/in.h>
#include "net/packet.hpp"
+#include "util/io.hpp"
namespace net {
class conn {
- int sock_fd;
+ io::serialized_io<io::file_io> rw;
sockaddr_in conn_addr;
socklen_t conn_addr_size;
- using handler_list = std::vector<std::function<bool(std::span<uint8_t>)>>;
+ using handler = std::function<bool(std::span<uint8_t>)>;
+ using handler_list = std::vector<handler>;
std::array<handler_list, 256> handlers;
std::map<uint16_t, handler_list> netmodule_handlers;
@@ -27,72 +29,20 @@ private:
uint16_t packet_size;
uint8_t id;
- recv(packet_size);
- recv(id);
+ rw.read(packet_size);
+ rw.read(id);
return { id, packet_size - 3 };
}
public:
conn(int sock_fd, sockaddr_in conn_addr, socklen_t conn_addr_size)
- : sock_fd(sock_fd)
+ : rw(io::file_io(sock_fd))
, conn_addr(conn_addr)
, conn_addr_size(conn_addr_size)
{
}
- ~conn()
- {
- close(sock_fd);
- }
-
- ssize_t send(std::span<uint8_t> data)
- {
- auto bytes = ::send(sock_fd, data.data(), data.size_bytes(), 0);
- if (bytes < 0) {
- throw std::runtime_error(strerror(errno));
- }
- return bytes;
- }
-
- template <std::integral T>
- ssize_t send(T t)
- {
- t = to_little(t);
- auto bytes = ::send(sock_fd, &t, sizeof(T), 0);
- if (bytes < 0) {
- throw std::runtime_error(strerror(errno));
- }
- return bytes;
- }
-
- ssize_t recv(std::span<uint8_t> data)
- {
- if (data.size_bytes() == 0) {
- return 0;
- }
-
- auto bytes = ::recv(sock_fd, data.data(), data.size_bytes(), 0);
- if (bytes <= 0) {
- throw std::runtime_error(strerror(errno));
- }
- return bytes;
- }
-
- template <std::integral T>
- ssize_t recv(T& t)
- {
- auto bytes = ::recv(sock_fd, &t, sizeof(T), 0);
- if (bytes <= 0) {
- throw std::runtime_error(strerror(errno));
- }
- t = to_little(t);
- if (bytes != sizeof(T)) {
- throw std::runtime_error(strerror(errno));
- }
- return bytes;
- }
-
template <packet::packet T>
void expect_packet(T& t)
{
@@ -101,11 +51,17 @@ public:
if (len > 0) {
std::vector<uint8_t> payload(len);
- recv(payload);
+ rw.read(payload);
decode_packet(payload, t);
}
}
+ template <class H>
+ void reg_handler(int id, H h)
+ {
+ handlers[id].push_back(h);
+ }
+
template <packet::packet P, typename H>
void reg_handler(H h)
{
@@ -133,13 +89,21 @@ public:
template <packet::packet T>
void send_packet(T p)
{
- auto payload = encode_packet(p);
+ send_packet(T::packet_id, encode_packet(p));
+ }
- send(int16_t(payload.size() + 3));
- send(T::packet_id);
+ void send_packet(uint8_t id, std::span<uint8_t> payload)
+ {
+ std::vector<uint8_t> packet_data;
+ auto buffer = io::serialized_io(io::buffered_io(packet_data));
+
+ buffer.write(int16_t(payload.size() + 3));
+ buffer.write(id);
if (payload.size() > 0) {
- send(payload);
+ buffer.write(payload);
}
+
+ rw.write(packet_data);
}
bool handle_netmodule(std::span<uint8_t> payload)
@@ -170,7 +134,7 @@ public:
}
std::vector<uint8_t> payload(len);
- recv(payload);
+ rw.read(payload);
// got netmodule
if (id == 82) {
diff --git a/include/net/packet.hpp b/include/net/packet.hpp
index 117fc15..950601e 100644
--- a/include/net/packet.hpp
+++ b/include/net/packet.hpp
@@ -17,6 +17,7 @@
#include <zlib.h>
#include "types.hpp"
+#include "util/io.hpp"
namespace net {
@@ -27,28 +28,22 @@ using packet_header = std::tuple<uint8_t, uint16_t>;
template <packet T>
void decode_packet(std::span<uint8_t> payload, T& t)
{
- std::size_t offset = 0;
+ std::size_t len = 0;
- boost::pfr::for_each_field(t, [&payload, &offset](auto& field, int i) {
- if (offset >= payload.size()) {
- throw std::runtime_error("Received invalid packet");
- }
- offset += decode_field(payload.subspan(offset), field);
- });
+ auto rd = io::serialized_io(io::buffered_io { payload });
+ len = rd.read(t);
- if (offset < payload.size()) {
- throw std::runtime_error(std::format("{}: {}", offset, payload.size()));
+ if (len != payload.size()) {
+ throw std::runtime_error(std::format("{}: {}", len, payload.size()));
}
}
template <packet T>
-std::vector<uint8_t> encode_raw_packet(T& t)
+std::vector<uint8_t> encode_packet_impl(T& t)
{
std::vector<uint8_t> payload;
-
- boost::pfr::for_each_field(t, [&payload](auto& field) {
- encode_field(payload, field);
- });
+ auto wt = io::serialized_io(io::buffered_io { payload });
+ wt.write(t);
return payload;
}
@@ -56,7 +51,7 @@ std::vector<uint8_t> encode_raw_packet(T& t)
template <packet T>
std::vector<uint8_t> encode_packet(T& t)
{
- return encode_raw_packet(t);
+ return encode_packet_impl(t);
}
template <compressed_packet T>
@@ -69,7 +64,7 @@ std::vector<uint8_t> encode_packet(T& t)
int ret, flush;
z_stream strm;
- auto raw_payload = encode_raw_packet(t);
+ auto raw_payload = encode_packet_impl(t);
strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;
diff --git a/include/net/server.hpp b/include/net/server.hpp
index 30791fc..9b5e7c5 100644
--- a/include/net/server.hpp
+++ b/include/net/server.hpp
@@ -23,7 +23,7 @@
namespace net {
class server {
- struct sockaddr_in server_address { };
+ struct sockaddr_in server_address {};
int sock_fd;
public:
diff --git a/include/net/types.hpp b/include/net/types.hpp
index a4a8c3b..13c96e0 100644
--- a/include/net/types.hpp
+++ b/include/net/types.hpp
@@ -1,13 +1,11 @@
#pragma once
-#include <string>
-#include <vector>
#include <array>
-#include <span>
#include <cstring>
+#include <string>
+#include <unistd.h>
#include "util/bitset.hpp"
-#include "util/endian.hpp"
#include "version.hpp"
namespace net {
@@ -76,183 +74,6 @@ struct death_reason {
std::string custom;
};
-void encode_field(std::vector<uint8_t>& data, const std::string& f)
-{
- auto bytes = reinterpret_cast<uint8_t const*>(f.data());
- data.insert(data.end(), uint8_t(f.size()));
- data.insert(data.end(), bytes, bytes + f.size());
-}
-
-template <std::integral T>
-void encode_field(std::vector<uint8_t>& data, T f)
-{
- auto fixed = to_little(f);
- auto* p = reinterpret_cast<uint8_t const*>(&fixed);
- data.insert(data.end(), p, p + sizeof(T));
-}
-
-template <std::floating_point T>
-void encode_field(std::vector<uint8_t>& data, T f)
-{
- auto x = reinterpret_cast<uint8_t*>(&f);
- data.insert(data.end(), x, x + sizeof(T));
-}
-
-void encode_field(std::vector<uint8_t>& data, nstring& s)
-{
- data.insert(data.end(), uint8_t(s.mode));
- encode_field(data, s.s);
-}
-
-void encode_field(std::vector<uint8_t>& data, const rgb& f)
-{
- encode_field(data, f.r);
- encode_field(data, f.g);
- encode_field(data, f.b);
-}
-
-template <typename T, std::size_t sz>
-void encode_field(std::vector<uint8_t>& data, std::array<T, sz>& f)
-{
- for (auto& e : f) {
- encode_field(data, e);
- }
-}
-
-template <typename T>
-void encode_field(std::vector<uint8_t>& data, std::vector<T>& f)
-{
- for (auto& e : f) {
- encode_field(data, e);
- }
-}
-
-template <typename T>
-void encode_field(std::vector<uint8_t>& data, std::span<T>& f)
-{
- for (auto& e : f) {
- encode_field(data, e);
- }
-}
-
-template <unsigned int bits>
-void encode_field(std::vector<uint8_t>& data, bitset<bits>& f)
-{
- for (auto& e : f) {
- encode_field(data, e);
- }
-}
-
-void encode_field(std::vector<uint8_t>& data, death_reason& f)
-{
- encode_field(data, f.reasons);
- if (f.reasons[death_reason::reason::Player]) {
- encode_field(data, f.player_index);
- }
- if (f.reasons[death_reason::reason::NPC]) {
- encode_field(data, f.npc_index);
- }
- if (f.reasons[death_reason::reason::Projectile]) {
- encode_field(data, f.projectile_index);
- }
- if (f.reasons[death_reason::reason::Other]) {
- encode_field(data, f.other_index);
- }
- if (f.reasons[death_reason::reason::ProjectileType]) {
- encode_field(data, f.projectile_type);
- }
- if (f.reasons[death_reason::reason::Item]) {
- encode_field(data, f.item_type);
- }
- if (f.reasons[death_reason::reason::ItemPrefix]) {
- encode_field(data, f.item_prefix);
- }
- if (f.reasons[death_reason::reason::Custom]) {
- encode_field(data, f.custom);
- }
-}
-
-ssize_t decode_field(std::span<uint8_t> data, std::string& f)
-{
- assert(data.size() > 0);
- uint8_t size = uint8_t(data[0]); // FIXME: varint
-
- assert(data.size() >= std::size_t(size + 1));
-
- f.resize(size);
- f.assign(reinterpret_cast<const char*>(data.data() + 1 /* FIXME: varint*/), size);
- return size + 1;
-}
-
-template <std::integral T>
-ssize_t decode_field(std::span<uint8_t> data, T& f)
-{
- assert(data.size() >= sizeof(T));
- std::memcpy(&f, data.data(), sizeof(T));
- f = to_little(f);
- return sizeof(T);
-}
-
-ssize_t decode_field(std::span<uint8_t> data, std::vector<uint8_t>& f)
-{
- f.insert(f.begin(), data.begin(), data.end());
- return f.size();
-}
-
-template <typename T, std::size_t sz>
-ssize_t decode_field(std::span<uint8_t> data, std::array<T, sz>& f)
-{
- assert(data.size() >= sizeof(T) * sz);
-
- ssize_t offset = 0;
- for (auto& e : f) {
- offset += decode_field(data.subspan(offset), e);
- }
-
- return offset;
-}
-
-ssize_t decode_field(std::span<uint8_t> data, death_reason& f)
-{
- int offset = 0;
- offset += decode_field(data, f.reasons);
- if (f.reasons[0]) {
- offset += decode_field(data.subspan(offset), f.player_index);
- }
- if (f.reasons[1]) {
- offset += decode_field(data.subspan(offset), f.npc_index);
- }
- if (f.reasons[2]) {
- offset += decode_field(data.subspan(offset), f.projectile_index);
- }
- if (f.reasons[3]) {
- offset += decode_field(data.subspan(offset), f.other_index);
- }
- if (f.reasons[4]) {
- offset += decode_field(data.subspan(offset), f.projectile_type);
- }
- if (f.reasons[5]) {
- offset += decode_field(data.subspan(offset), f.item_type);
- }
- if (f.reasons[6]) {
- offset += decode_field(data.subspan(offset), f.item_prefix);
- }
- if (f.reasons[7]) {
- offset += decode_field(data.subspan(offset), f.custom);
- }
-
- return offset;
-}
-ssize_t decode_field(std::span<uint8_t> data, rgb& f)
-{
- assert(data.size() >= 3);
-
- f.r = uint8_t(data[0]);
- f.g = uint8_t(data[1]);
- f.b = uint8_t(data[2]);
- return 3;
-}
-
struct conn_request {
static constexpr uint8_t packet_id = 1;
@@ -480,12 +301,6 @@ struct damage_player {
int8_t cooldown_counter;
};
-template <uint8_t id>
-struct raw {
- static constexpr uint8_t packet_id = id;
- std::vector<uint8_t> data;
-};
-
inline nstring operator""_ns(const char* str, std::size_t)
{
return nstring(str);