#pragma once #include #include #include #include #include #include #include #include "net/packet.hpp" #include "util/io.hpp" namespace net { class conn { io::serialized_io rw; sockaddr_in conn_addr; socklen_t conn_addr_size; using handler = std::function)>; using handler_list = std::vector; std::array handlers; std::map netmodule_handlers; private: packet::packet_header read_header() { uint16_t packet_size; uint8_t 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) : rw(io::file_io(sock_fd)) , conn_addr(conn_addr) , conn_addr_size(conn_addr_size) { } template void expect_packet(T& t) { auto [id, len] = read_header(); assert(id == T::packet_id); if (len > 0) { std::vector payload(len); rw.read(payload); decode_packet(payload, t); } } template void reg_handler(H h) { handlers[P::packet_id].push_back([this, h](std::span payload) { P t; if (payload.size() > 0) { packet::decode_packet(payload, t); } return h(t); }); } template void reg_handler(H h) { netmodule_handlers[P::module_id].push_back([this, h](std::span payload) { P t; if (payload.size() > 0) { packet::decode_packet(payload, t); } return h(t); }); } void send_packet(uint8_t id, std::span payload) { std::vector 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) { buffer.write(payload); } rw.write(packet_data); } template void send_packet(T p) { auto payload = encode_packet(p); send_packet(T::packet_id, payload); } template void handle(T unk_handler) { auto [id, len] = read_header(); if (id == 0) { return; } std::vector payload(len); rw.read(payload); if (handlers[id].size() <= 0) { unk_handler(id, payload); } for (auto& h : handlers[id]) { if (h(payload) == true) { return; } } } void handle() { handle([](int, std::vector) {}); } }; }