diff options
Diffstat (limited to 'src/net')
-rw-r--r-- | src/net/fwd.hpp | 2 | ||||
-rw-r--r-- | src/net/packets.hpp | 169 |
2 files changed, 169 insertions, 2 deletions
diff --git a/src/net/fwd.hpp b/src/net/fwd.hpp index ca54e8d..109aeed 100644 --- a/src/net/fwd.hpp +++ b/src/net/fwd.hpp @@ -27,4 +27,6 @@ class IP4Address; class TimerData; +enum class RecvResult; + #endif // TMWA_NET_FWD_HPP diff --git a/src/net/packets.hpp b/src/net/packets.hpp index 6146b90..293aed8 100644 --- a/src/net/packets.hpp +++ b/src/net/packets.hpp @@ -79,6 +79,14 @@ SendResult net_send_fpacket(Session *s, const NetPacket_Fixed<id>& fixed) template<uint16_t id> __attribute__((warn_unused_result)) +SendResult net_send_ppacket(Session *s, const NetPacket_Payload<id>& payload) +{ + bool ok = packet_send(s, reinterpret_cast<const Byte *>(&payload), sizeof(NetPacket_Payload<id>)); + return ok ? SendResult::Success : SendResult::Fail; +} + +template<uint16_t id> +__attribute__((warn_unused_result)) SendResult net_send_vpacket(Session *s, const NetPacket_Head<id>& head, const std::vector<NetPacket_Repeat<id>>& repeat) { bool ok = packet_send(s, reinterpret_cast<const Byte *>(&head), sizeof(NetPacket_Head<id>)); @@ -88,6 +96,18 @@ SendResult net_send_vpacket(Session *s, const NetPacket_Head<id>& head, const st template<uint16_t id> __attribute__((warn_unused_result)) +SendResult net_send_opacket(Session *s, const NetPacket_Head<id>& head, bool has_opt, const NetPacket_Option<id>& opt) +{ + bool ok = packet_send(s, reinterpret_cast<const Byte *>(&head), sizeof(NetPacket_Head<id>)); + if (has_opt) + { + ok &= packet_send(s, reinterpret_cast<const Byte *>(&opt), sizeof(NetPacket_Option<id>)); + } + return ok ? SendResult::Success : SendResult::Fail; +} + +template<uint16_t id> +__attribute__((warn_unused_result)) RecvResult net_recv_fpacket(Session *s, NetPacket_Fixed<id>& fixed) { bool ok = packet_fetch(s, 0, reinterpret_cast<Byte *>(&fixed), sizeof(NetPacket_Fixed<id>)); @@ -101,6 +121,19 @@ RecvResult net_recv_fpacket(Session *s, NetPacket_Fixed<id>& fixed) template<uint16_t id> __attribute__((warn_unused_result)) +RecvResult net_recv_ppacket(Session *s, NetPacket_Payload<id>& payload) +{ + bool ok = packet_fetch(s, 0, reinterpret_cast<Byte *>(&payload), sizeof(NetPacket_Payload<id>)); + if (ok) + { + packet_discard(s, sizeof(NetPacket_Payload<id>)); + return RecvResult::Complete; + } + return RecvResult::Incomplete; +} + +template<uint16_t id> +__attribute__((warn_unused_result)) RecvResult net_recv_vpacket(Session *s, NetPacket_Head<id>& head, std::vector<NetPacket_Repeat<id>>& repeat) { bool ok = packet_fetch(s, 0, reinterpret_cast<Byte *>(&head), sizeof(NetPacket_Head<id>)); @@ -127,6 +160,37 @@ RecvResult net_recv_vpacket(Session *s, NetPacket_Head<id>& head, std::vector<Ne return RecvResult::Incomplete; } +template<uint16_t id> +__attribute__((warn_unused_result)) +RecvResult net_recv_opacket(Session *s, NetPacket_Head<id>& head, bool *has_opt, NetPacket_Option<id>& opt) +{ + bool ok = packet_fetch(s, 0, reinterpret_cast<Byte *>(&head), sizeof(NetPacket_Head<id>)); + if (ok) + { + Packet_Head<id> nat; + if (!network_to_native(&nat, head)) + return RecvResult::Error; + if (packet_avail(s) < nat.magic_packet_length) + return RecvResult::Incomplete; + if (nat.magic_packet_length < sizeof(NetPacket_Head<id>)) + return RecvResult::Error; + size_t bytes_repeat = nat.magic_packet_length - sizeof(NetPacket_Head<id>); + if (bytes_repeat % sizeof(NetPacket_Repeat<id>)) + return RecvResult::Error; + size_t has_opt_pls = bytes_repeat / sizeof(NetPacket_Option<id>); + if (has_opt_pls > 1) + return RecvResult::Error; + *has_opt = has_opt_pls; + if (!*has_opt || packet_fetch(s, sizeof(NetPacket_Head<id>), reinterpret_cast<Byte *>(&opt), sizeof(NetPacket_Option<id>))) + { + packet_discard(s, nat.magic_packet_length); + return RecvResult::Complete; + } + return RecvResult::Incomplete; + } + return RecvResult::Incomplete; +} + template<uint16_t id, uint16_t size> void send_fpacket(Session *s, const Packet_Fixed<id>& fixed) @@ -145,6 +209,23 @@ void send_fpacket(Session *s, const Packet_Fixed<id>& fixed) s->set_eof(); } +template<uint16_t id> +void send_ppacket(Session *s, Packet_Payload<id>& payload) +{ + static_assert(id == Packet_Payload<id>::PACKET_ID, "Packet_Payload<id>::PACKET_ID"); + + NetPacket_Payload<id> net_payload; + payload.magic_packet_length = sizeof(NetPacket_Payload<id>); + if (!native_to_network(&net_payload, payload)) + { + s->set_eof(); + return; + } + SendResult rv = net_send_ppacket(s, net_payload); + if (rv != SendResult::Success) + s->set_eof(); +} + template<uint16_t id, uint16_t headsize, uint16_t repeatsize> void send_vpacket(Session *s, Packet_Head<id>& head, const std::vector<Packet_Repeat<id>>& repeat) { @@ -183,6 +264,43 @@ void send_vpacket(Session *s, Packet_Head<id>& head, const std::vector<Packet_Re s->set_eof(); } +template<uint16_t id, uint16_t headsize, uint16_t optsize> +void send_opacket(Session *s, Packet_Head<id>& head, bool has_opt, const Packet_Option<id>& opt) +{ + static_assert(id == Packet_Head<id>::PACKET_ID, "Packet_Head<id>::PACKET_ID"); + static_assert(headsize == sizeof(NetPacket_Head<id>), "sizeof(NetPacket_Head<id>)"); + static_assert(id == Packet_Option<id>::PACKET_ID, "Packet_Option<id>::PACKET_ID"); + static_assert(optsize == sizeof(NetPacket_Option<id>), "sizeof(NetPacket_Option<id>)"); + + NetPacket_Head<id> net_head; + // since these are already allocated, can't overflow address space + size_t total_size = sizeof(NetPacket_Head<id>) + has_opt * sizeof(NetPacket_Option<id>); + // truncates + head.magic_packet_length = total_size; + if (head.magic_packet_length != total_size) + { + s->set_eof(); + return; + } + NetPacket_Option<id> net_opt; + if (!native_to_network(&net_head, head)) + { + s->set_eof(); + return; + } + if (has_opt) + { + if (!native_to_network(&net_opt, opt)) + { + s->set_eof(); + return; + } + } + SendResult rv = net_send_opacket(s, net_head, has_opt, net_opt); + if (rv != SendResult::Success) + s->set_eof(); +} + template<uint16_t id, uint16_t size> __attribute__((warn_unused_result)) RecvResult recv_fpacket(Session *s, Packet_Fixed<id>& fixed) @@ -192,11 +310,30 @@ RecvResult recv_fpacket(Session *s, Packet_Fixed<id>& fixed) NetPacket_Fixed<id> net_fixed; RecvResult rv = net_recv_fpacket(s, net_fixed); - assert (fixed.magic_packet_id == Packet_Fixed<id>::PACKET_ID); if (rv == RecvResult::Complete) { if (!network_to_native(&fixed, net_fixed)) return RecvResult::Error; + assert (fixed.magic_packet_id == Packet_Fixed<id>::PACKET_ID); + } + return rv; +} + +template<uint16_t id> +__attribute__((warn_unused_result)) +RecvResult recv_ppacket(Session *s, Packet_Payload<id>& payload) +{ + static_assert(id == Packet_Payload<id>::PACKET_ID, "Packet_Payload<id>::PACKET_ID"); + + NetPacket_Payload<id> net_payload; + RecvResult rv = net_recv_ppacket(s, net_payload); + if (rv == RecvResult::Complete) + { + if (!network_to_native(&payload, net_payload)) + return RecvResult::Error; + assert (payload.magic_packet_id == Packet_Payload<id>::PACKET_ID); + if (payload.magic_packet_length != sizeof(net_payload)) + return RecvResult::Error; } return rv; } @@ -213,11 +350,12 @@ RecvResult recv_vpacket(Session *s, Packet_Head<id>& head, std::vector<Packet_Re NetPacket_Head<id> net_head; std::vector<NetPacket_Repeat<id>> net_repeat; RecvResult rv = net_recv_vpacket(s, net_head, net_repeat); - assert (head.magic_packet_id == Packet_Head<id>::PACKET_ID); if (rv == RecvResult::Complete) { if (!network_to_native(&head, net_head)) return RecvResult::Error; + assert (head.magic_packet_id == Packet_Head<id>::PACKET_ID); + repeat.resize(net_repeat.size()); for (size_t i = 0; i < net_repeat.size(); ++i) { @@ -228,6 +366,33 @@ RecvResult recv_vpacket(Session *s, Packet_Head<id>& head, std::vector<Packet_Re return rv; } +template<uint16_t id, uint16_t headsize, uint16_t optsize> +__attribute__((warn_unused_result)) +RecvResult recv_opacket(Session *s, Packet_Head<id>& head, bool *has_opt, Packet_Option<id>& opt) +{ + static_assert(id == Packet_Head<id>::PACKET_ID, "Packet_Head<id>::PACKET_ID"); + static_assert(headsize == sizeof(NetPacket_Head<id>), "NetPacket_Head<id>"); + static_assert(id == Packet_Option<id>::PACKET_ID, "Packet_Option<id>::PACKET_ID"); + static_assert(optsize == sizeof(NetPacket_Option<id>), "NetPacket_Option<id>"); + + NetPacket_Head<id> net_head; + NetPacket_Option<id> net_opt; + RecvResult rv = net_recv_opacket(s, net_head, has_opt, net_opt); + if (rv == RecvResult::Complete) + { + if (!network_to_native(&head, net_head)) + return RecvResult::Error; + assert (head.magic_packet_id == Packet_Head<id>::PACKET_ID); + + if (*has_opt) + { + if (!network_to_native(&opt, net_opt)) + return RecvResult::Error; + } + } + return rv; +} + // convenience for trailing strings |