summaryrefslogtreecommitdiff
path: root/src/net
diff options
context:
space:
mode:
Diffstat (limited to 'src/net')
-rw-r--r--src/net/packets.hpp204
-rw-r--r--src/net/timer.t.hpp51
2 files changed, 201 insertions, 54 deletions
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<Byte> 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<uint16_t id>
__attribute__((warn_unused_result))
SendResult net_send_fpacket(Session *s, const NetPacket_Fixed<id>& fixed)
@@ -193,112 +206,146 @@ RecvResult net_recv_opacket(Session *s, NetPacket_Head<id>& head, bool *has_opt,
template<uint16_t id, uint16_t size>
-void send_fpacket(Session *s, const Packet_Fixed<id>& fixed)
+Buffer create_fpacket(const Packet_Fixed<id>& fixed)
{
static_assert(id == Packet_Fixed<id>::PACKET_ID, "Packet_Fixed<id>::PACKET_ID");
static_assert(size == sizeof(NetPacket_Fixed<id>), "sizeof(NetPacket_Fixed<id>)");
- NetPacket_Fixed<id> net_fixed;
+ Buffer buf;
+ buf.bytes.resize(sizeof(NetPacket_Fixed<id>));
+ auto& net_fixed = reinterpret_cast<NetPacket_Fixed<id>&>(
+ *(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<uint16_t id>
-void send_ppacket(Session *s, Packet_Payload<id>& payload)
+Buffer create_ppacket(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 (id != 0x8000)
+ payload.magic_packet_length = sizeof(NetPacket_Payload<id>);
+
+ Buffer buf;
+ buf.bytes.resize(sizeof(NetPacket_Payload<id>));
+ auto& net_payload = reinterpret_cast<NetPacket_Payload<id>&>(
+ *(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<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)
+Buffer create_vpacket(Packet_Head<id>& head, const std::vector<Packet_Repeat<id>>& repeat)
{
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_Repeat<id>::PACKET_ID, "Packet_Repeat<id>::PACKET_ID");
static_assert(repeatsize == sizeof(NetPacket_Repeat<id>), "sizeof(NetPacket_Repeat<id>)");
- NetPacket_Head<id> net_head;
// since these are already allocated, can't overflow address space
size_t total_size = sizeof(NetPacket_Head<id>) + repeat.size() * sizeof(NetPacket_Repeat<id>);
// 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<NetPacket_Repeat<id>> net_repeat(repeat.size());
+
+ Buffer buf;
+ buf.bytes.resize(total_size);
+ auto& net_head = reinterpret_cast<NetPacket_Head<id>&>(
+ *(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<NetPacket_Repeat<id>&>(
+ *(buf.bytes.begin()
+ + sizeof(NetPacket_Head<id>)
+ + i * sizeof(NetPacket_Repeat<id>)));
+ 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<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)
+Buffer create_opacket(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;
+ return Buffer();
}
- NetPacket_Option<id> net_opt;
+
+ Buffer buf;
+ buf.bytes.resize(total_size);
+
+ auto& net_head = reinterpret_cast<NetPacket_Head<id>&>(
+ *(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<NetPacket_Option<id>&>(
+ *(buf.bytes.begin()
+ + sizeof(NetPacket_Head<id>)));
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<uint16_t id, uint16_t size>
+void send_fpacket(Session *s, const Packet_Fixed<id>& fixed)
+{
+ Buffer pkt = create_fpacket<id, size>(fixed);
+ send_buffer(s, pkt);
+}
+
+template<uint16_t id>
+void send_ppacket(Session *s, Packet_Payload<id>& payload)
+{
+ Buffer pkt = create_ppacket<id>(payload);
+ send_buffer(s, pkt);
+}
+
+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)
+{
+ Buffer pkt = create_vpacket<id, headsize, repeatsize>(head, repeat);
+ send_buffer(s, pkt);
+}
+
+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)
+{
+ Buffer pkt = create_opacket<id, headsize, optsize>(head, has_opt, opt);
+ send_buffer(s, pkt);
}
template<uint16_t id, uint16_t size>
@@ -332,6 +379,14 @@ RecvResult recv_ppacket(Session *s, Packet_Payload<id>& payload)
if (!network_to_native(&payload, net_payload))
return RecvResult::Error;
assert (payload.magic_packet_id == Packet_Payload<id>::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<id>& head, bool *has_opt, Packet
// convenience for trailing strings
template<uint16_t id, uint16_t headsize, uint16_t repeatsize>
-void send_vpacket(Session *s, Packet_Head<id>& head, const XString& repeat)
+Buffer create_vpacket(Packet_Head<id>& head, const XString& repeat)
{
static_assert(id == Packet_Head<id>::PACKET_ID, "Packet_Head<id>::PACKET_ID");
static_assert(headsize == sizeof(NetPacket_Head<id>), "NetPacket_Head<id>");
@@ -405,30 +460,44 @@ void send_vpacket(Session *s, Packet_Head<id>& head, const XString& repeat)
static_assert(repeatsize == sizeof(NetPacket_Repeat<id>), "NetPacket_Repeat<id>");
static_assert(repeatsize == 1, "repeatsize");
- NetPacket_Head<id> net_head;
// since it's already allocated, it can't overflow address space
size_t total_length = sizeof(NetPacket_Head<id>) + (repeat.size() + 1) * sizeof(NetPacket_Repeat<id>);
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<NetPacket_Head<id>&>(
+ *(buf.bytes.begin() + 0));
std::vector<NetPacket_Repeat<id>> 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<uint8_t>(repeat[i])};
+ auto& net_repeat_i = reinterpret_cast<NetPacket_Repeat<id>&>(
+ *(buf.bytes.begin()
+ + sizeof(NetPacket_Head<id>)
+ + i));
+ net_repeat_i.c = Byte{static_cast<uint8_t>(repeat[i])};
}
- net_repeat[repeat.size()].c = Byte{static_cast<uint8_t>('\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<NetPacket_Repeat<id>&>(
+ *(buf.bytes.begin()
+ + sizeof(NetPacket_Head<id>)
+ + repeat.size()));
+ net_repeat_repeat_size.c = Byte{static_cast<uint8_t>('\0')};
+ return buf;
+}
+
+template<uint16_t id, uint16_t headsize, uint16_t repeatsize>
+void send_vpacket(Session *s, Packet_Head<id>& head, const XString& repeat)
+{
+ Buffer pkt = create_vpacket<id, headsize, repeatsize>(head, repeat);
+ send_buffer(s, pkt);
}
template<uint16_t id, uint16_t headsize, uint16_t repeatsize>
@@ -462,6 +531,19 @@ RecvResult recv_vpacket(Session *s, Packet_Head<id>& head, AString& repeat)
// if there is nothing in the head but the id and length, use the below
template<uint16_t id, uint16_t headsize, uint16_t repeatsize>
+Buffer create_packet_repeatonly(const std::vector<Packet_Repeat<id>>& v)
+{
+ static_assert(id == Packet_Head<id>::PACKET_ID, "Packet_Head<id>::PACKET_ID");
+ static_assert(headsize == sizeof(NetPacket_Head<id>), "repeat headsize");
+ static_assert(headsize == 4, "repeat headsize");
+ static_assert(id == Packet_Repeat<id>::PACKET_ID, "Packet_Repeat<id>::PACKET_ID");
+ static_assert(repeatsize == sizeof(NetPacket_Repeat<id>), "sizeof(NetPacket_Repeat<id>)");
+
+ Packet_Head<id> head;
+ return create_vpacket<id, 4, repeatsize>(head, v);
+}
+
+template<uint16_t id, uint16_t headsize, uint16_t repeatsize>
void send_packet_repeatonly(Session *s, const std::vector<Packet_Repeat<id>>& v)
{
static_assert(id == Packet_Head<id>::PACKET_ID, "Packet_Head<id>::PACKET_ID");
@@ -492,6 +574,20 @@ RecvResult recv_packet_repeatonly(Session *s, std::vector<Packet_Repeat<id>>& v)
// and the combination of both of the above
template<uint16_t id, uint16_t headsize, uint16_t repeatsize>
+Buffer create_packet_repeatonly(const XString& repeat)
+{
+ static_assert(id == Packet_Head<id>::PACKET_ID, "Packet_Head<id>::PACKET_ID");
+ static_assert(headsize == sizeof(NetPacket_Head<id>), "repeat headsize");
+ static_assert(headsize == 4, "repeat headsize");
+ static_assert(id == Packet_Repeat<id>::PACKET_ID, "Packet_Repeat<id>::PACKET_ID");
+ static_assert(repeatsize == sizeof(NetPacket_Repeat<id>), "sizeof(NetPacket_Repeat<id>)");
+ static_assert(repeatsize == 1, "repeatsize");
+
+ Packet_Head<id> head;
+ return create_vpacket<id, 4, repeatsize>(head, repeat);
+}
+
+template<uint16_t id, uint16_t headsize, uint16_t repeatsize>
void send_packet_repeatonly(Session *s, const XString& repeat)
{
static_assert(id == Packet_Head<id>::PACKET_ID, "Packet_Head<id>::PACKET_ID");
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 <chrono>
# include <functional>
+# 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<void (TimerData *, tick_t)> 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<uint32_t>(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<uint32_t>(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<uint16_t>(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;