From 1c1752f40aac20bf9a5e56817951a013c2219bed Mon Sep 17 00:00:00 2001 From: Ben Longbons Date: Tue, 10 Jun 2014 15:31:24 -0700 Subject: Generate the map server protocol Sigh, map server will have no smart filters yet --- src/net/packets.hpp | 204 ++++++++++++++++++++++++++++++++++++++-------------- src/net/timer.t.hpp | 51 +++++++++++++ 2 files changed, 201 insertions(+), 54 deletions(-) (limited to 'src/net') diff --git a/src/net/packets.hpp b/src/net/packets.hpp index 293aed8..54167e8 100644 --- a/src/net/packets.hpp +++ b/src/net/packets.hpp @@ -27,11 +27,16 @@ # include "../io/fwd.hpp" -// ordering violation, should invert +// TODO ordering violation, should invert # include "../proto2/fwd.hpp" # include "socket.hpp" +struct Buffer +{ + std::vector bytes; +}; + enum class RecvResult { Incomplete, @@ -69,6 +74,14 @@ bool packet_peek_id(Session *s, uint16_t *packet_id) return okay; } +inline +void send_buffer(Session *s, const Buffer& buffer) +{ + bool ok = !buffer.bytes.empty() && packet_send(s, buffer.bytes.data(), buffer.bytes.size()); + if (!ok) + s->set_eof(); +} + template __attribute__((warn_unused_result)) SendResult net_send_fpacket(Session *s, const NetPacket_Fixed& fixed) @@ -193,112 +206,146 @@ RecvResult net_recv_opacket(Session *s, NetPacket_Head& head, bool *has_opt, template -void send_fpacket(Session *s, const Packet_Fixed& fixed) +Buffer create_fpacket(const Packet_Fixed& fixed) { static_assert(id == Packet_Fixed::PACKET_ID, "Packet_Fixed::PACKET_ID"); static_assert(size == sizeof(NetPacket_Fixed), "sizeof(NetPacket_Fixed)"); - NetPacket_Fixed net_fixed; + Buffer buf; + buf.bytes.resize(sizeof(NetPacket_Fixed)); + auto& net_fixed = reinterpret_cast&>( + *(buf.bytes.begin() + 0)); if (!native_to_network(&net_fixed, fixed)) { - s->set_eof(); - return; + return Buffer(); } - SendResult rv = net_send_fpacket(s, net_fixed); - if (rv != SendResult::Success) - s->set_eof(); + return buf; } template -void send_ppacket(Session *s, Packet_Payload& payload) +Buffer create_ppacket(Packet_Payload& payload) { static_assert(id == Packet_Payload::PACKET_ID, "Packet_Payload::PACKET_ID"); - NetPacket_Payload net_payload; - payload.magic_packet_length = sizeof(NetPacket_Payload); + if (id != 0x8000) + payload.magic_packet_length = sizeof(NetPacket_Payload); + + Buffer buf; + buf.bytes.resize(sizeof(NetPacket_Payload)); + auto& net_payload = reinterpret_cast&>( + *(buf.bytes.begin() + 0)); if (!native_to_network(&net_payload, payload)) { - s->set_eof(); - return; + return Buffer(); } - SendResult rv = net_send_ppacket(s, net_payload); - if (rv != SendResult::Success) - s->set_eof(); + return buf; } template -void send_vpacket(Session *s, Packet_Head& head, const std::vector>& repeat) +Buffer create_vpacket(Packet_Head& head, const std::vector>& repeat) { static_assert(id == Packet_Head::PACKET_ID, "Packet_Head::PACKET_ID"); static_assert(headsize == sizeof(NetPacket_Head), "sizeof(NetPacket_Head)"); static_assert(id == Packet_Repeat::PACKET_ID, "Packet_Repeat::PACKET_ID"); static_assert(repeatsize == sizeof(NetPacket_Repeat), "sizeof(NetPacket_Repeat)"); - NetPacket_Head net_head; // since these are already allocated, can't overflow address space size_t total_size = sizeof(NetPacket_Head) + repeat.size() * sizeof(NetPacket_Repeat); // truncates head.magic_packet_length = total_size; if (head.magic_packet_length != total_size) { - s->set_eof(); - return; + return Buffer(); } - // TODO potentially avoid the allocation - std::vector> net_repeat(repeat.size()); + + Buffer buf; + buf.bytes.resize(total_size); + auto& net_head = reinterpret_cast&>( + *(buf.bytes.begin() + 0)); if (!native_to_network(&net_head, head)) { - s->set_eof(); - return; + return Buffer(); } for (size_t i = 0; i < repeat.size(); ++i) { - if (!native_to_network(&net_repeat[i], repeat[i])) + auto& net_repeat_i = reinterpret_cast&>( + *(buf.bytes.begin() + + sizeof(NetPacket_Head) + + i * sizeof(NetPacket_Repeat))); + if (!native_to_network(&net_repeat_i, repeat[i])) { - s->set_eof(); - return; + return Buffer(); } } - SendResult rv = net_send_vpacket(s, net_head, net_repeat); - if (rv != SendResult::Success) - s->set_eof(); + return buf; } template -void send_opacket(Session *s, Packet_Head& head, bool has_opt, const Packet_Option& opt) +Buffer create_opacket(Packet_Head& head, bool has_opt, const Packet_Option& opt) { static_assert(id == Packet_Head::PACKET_ID, "Packet_Head::PACKET_ID"); static_assert(headsize == sizeof(NetPacket_Head), "sizeof(NetPacket_Head)"); static_assert(id == Packet_Option::PACKET_ID, "Packet_Option::PACKET_ID"); static_assert(optsize == sizeof(NetPacket_Option), "sizeof(NetPacket_Option)"); - NetPacket_Head net_head; // since these are already allocated, can't overflow address space size_t total_size = sizeof(NetPacket_Head) + has_opt * sizeof(NetPacket_Option); // truncates head.magic_packet_length = total_size; if (head.magic_packet_length != total_size) { - s->set_eof(); - return; + return Buffer(); } - NetPacket_Option net_opt; + + Buffer buf; + buf.bytes.resize(total_size); + + auto& net_head = reinterpret_cast&>( + *(buf.bytes.begin() + 0)); if (!native_to_network(&net_head, head)) { - s->set_eof(); - return; + return Buffer(); } if (has_opt) { + auto& net_opt = reinterpret_cast&>( + *(buf.bytes.begin() + + sizeof(NetPacket_Head))); if (!native_to_network(&net_opt, opt)) { - s->set_eof(); - return; + return Buffer(); } } - SendResult rv = net_send_opacket(s, net_head, has_opt, net_opt); - if (rv != SendResult::Success) - s->set_eof(); + + return buf; +} + +template +void send_fpacket(Session *s, const Packet_Fixed& fixed) +{ + Buffer pkt = create_fpacket(fixed); + send_buffer(s, pkt); +} + +template +void send_ppacket(Session *s, Packet_Payload& payload) +{ + Buffer pkt = create_ppacket(payload); + send_buffer(s, pkt); +} + +template +void send_vpacket(Session *s, Packet_Head& head, const std::vector>& repeat) +{ + Buffer pkt = create_vpacket(head, repeat); + send_buffer(s, pkt); +} + +template +void send_opacket(Session *s, Packet_Head& head, bool has_opt, const Packet_Option& opt) +{ + Buffer pkt = create_opacket(head, has_opt, opt); + send_buffer(s, pkt); } template @@ -332,6 +379,14 @@ RecvResult recv_ppacket(Session *s, Packet_Payload& payload) if (!network_to_native(&payload, net_payload)) return RecvResult::Error; assert (payload.magic_packet_id == Packet_Payload::PACKET_ID); + if (id == 0x8000) + { + // 0x8000 is special + if (packet_avail(s) < payload.magic_packet_length) + return RecvResult::Incomplete; + payload.magic_packet_length = 4; + return RecvResult::Complete; + } if (payload.magic_packet_length != sizeof(net_payload)) return RecvResult::Error; } @@ -397,7 +452,7 @@ RecvResult recv_opacket(Session *s, Packet_Head& head, bool *has_opt, Packet // convenience for trailing strings template -void send_vpacket(Session *s, Packet_Head& head, const XString& repeat) +Buffer create_vpacket(Packet_Head& head, const XString& repeat) { static_assert(id == Packet_Head::PACKET_ID, "Packet_Head::PACKET_ID"); static_assert(headsize == sizeof(NetPacket_Head), "NetPacket_Head"); @@ -405,30 +460,44 @@ void send_vpacket(Session *s, Packet_Head& head, const XString& repeat) static_assert(repeatsize == sizeof(NetPacket_Repeat), "NetPacket_Repeat"); static_assert(repeatsize == 1, "repeatsize"); - NetPacket_Head net_head; // since it's already allocated, it can't overflow address space size_t total_length = sizeof(NetPacket_Head) + (repeat.size() + 1) * sizeof(NetPacket_Repeat); head.magic_packet_length = total_length; if (head.magic_packet_length != total_length) { - s->set_eof(); - return; + return Buffer(); } - // TODO potentially avoid the allocation + + Buffer buf; + buf.bytes.resize(total_length); + auto& net_head = reinterpret_cast&>( + *(buf.bytes.begin() + 0)); std::vector> net_repeat(repeat.size() + 1); if (!native_to_network(&net_head, head)) { - s->set_eof(); - return; + return Buffer(); } for (size_t i = 0; i < repeat.size(); ++i) { - net_repeat[i].c = Byte{static_cast(repeat[i])}; + auto& net_repeat_i = reinterpret_cast&>( + *(buf.bytes.begin() + + sizeof(NetPacket_Head) + + i)); + net_repeat_i.c = Byte{static_cast(repeat[i])}; } - net_repeat[repeat.size()].c = Byte{static_cast('\0')}; - SendResult rv = net_send_vpacket(s, net_head, net_repeat); - if (rv != SendResult::Success) - s->set_eof(); + auto& net_repeat_repeat_size = reinterpret_cast&>( + *(buf.bytes.begin() + + sizeof(NetPacket_Head) + + repeat.size())); + net_repeat_repeat_size.c = Byte{static_cast('\0')}; + return buf; +} + +template +void send_vpacket(Session *s, Packet_Head& head, const XString& repeat) +{ + Buffer pkt = create_vpacket(head, repeat); + send_buffer(s, pkt); } template @@ -461,6 +530,19 @@ RecvResult recv_vpacket(Session *s, Packet_Head& head, AString& repeat) // if there is nothing in the head but the id and length, use the below +template +Buffer create_packet_repeatonly(const std::vector>& v) +{ + static_assert(id == Packet_Head::PACKET_ID, "Packet_Head::PACKET_ID"); + static_assert(headsize == sizeof(NetPacket_Head), "repeat headsize"); + static_assert(headsize == 4, "repeat headsize"); + static_assert(id == Packet_Repeat::PACKET_ID, "Packet_Repeat::PACKET_ID"); + static_assert(repeatsize == sizeof(NetPacket_Repeat), "sizeof(NetPacket_Repeat)"); + + Packet_Head head; + return create_vpacket(head, v); +} + template void send_packet_repeatonly(Session *s, const std::vector>& v) { @@ -491,6 +573,20 @@ RecvResult recv_packet_repeatonly(Session *s, std::vector>& v) // and the combination of both of the above +template +Buffer create_packet_repeatonly(const XString& repeat) +{ + static_assert(id == Packet_Head::PACKET_ID, "Packet_Head::PACKET_ID"); + static_assert(headsize == sizeof(NetPacket_Head), "repeat headsize"); + static_assert(headsize == 4, "repeat headsize"); + static_assert(id == Packet_Repeat::PACKET_ID, "Packet_Repeat::PACKET_ID"); + static_assert(repeatsize == sizeof(NetPacket_Repeat), "sizeof(NetPacket_Repeat)"); + static_assert(repeatsize == 1, "repeatsize"); + + Packet_Head head; + return create_vpacket(head, repeat); +} + template void send_packet_repeatonly(Session *s, const XString& repeat) { diff --git a/src/net/timer.t.hpp b/src/net/timer.t.hpp index 91d4b74..be32872 100644 --- a/src/net/timer.t.hpp +++ b/src/net/timer.t.hpp @@ -26,6 +26,8 @@ # include # include +# include "../ints/little.hpp" + # include "../generic/dumb_ptr.hpp" /// An implementation of the C++ "clock" concept, exposing @@ -49,6 +51,55 @@ typedef milli_clock::duration interval_t; /// (to get additional arguments, use std::bind or a lambda). typedef std::function timer_func; +// 49.7 day problem +inline __attribute__((warn_unused_result)) +bool native_to_network(Little32 *net, tick_t nat) +{ + auto tmp = nat.time_since_epoch().count(); + return native_to_network(net, static_cast(tmp)); +} + +inline __attribute__((warn_unused_result)) +bool network_to_native(tick_t *nat, Little32 net) +{ + (void)nat; + (void)net; + abort(); +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(Little32 *net, interval_t nat) +{ + auto tmp = nat.count(); + return native_to_network(net, static_cast(tmp)); +} + +inline __attribute__((warn_unused_result)) +bool network_to_native(interval_t *nat, Little32 net) +{ + uint32_t tmp; + bool rv = network_to_native(&tmp, net); + *nat = interval_t(tmp); + return rv; +} + +inline __attribute__((warn_unused_result)) +bool native_to_network(Little16 *net, interval_t nat) +{ + auto tmp = nat.count(); + return native_to_network(net, static_cast(tmp)); +} + +inline __attribute__((warn_unused_result)) +bool network_to_native(interval_t *nat, Little16 net) +{ + uint16_t tmp; + bool rv = network_to_native(&tmp, net); + *nat = interval_t(tmp); + return rv; +} + + class Timer { friend struct TimerData; -- cgit v1.2.3-60-g2f50