summaryrefslogtreecommitdiff
path: root/src/net
diff options
context:
space:
mode:
authorBen Longbons <b.r.longbons@gmail.com>2014-10-25 15:24:26 -0700
committerBen Longbons <b.r.longbons@gmail.com>2014-10-26 14:21:48 -0700
commit86395f53634b3ef1ce76a7f1e5edfdb61f8ffd80 (patch)
tree2710c62fe71d5e0d2e228fba9c951a040c4dcddf /src/net
parent6800761863dd45b6055768febc6ace6a20120dc7 (diff)
downloadtmwa-86395f53634b3ef1ce76a7f1e5edfdb61f8ffd80.tar.gz
tmwa-86395f53634b3ef1ce76a7f1e5edfdb61f8ffd80.tar.bz2
tmwa-86395f53634b3ef1ce76a7f1e5edfdb61f8ffd80.tar.xz
tmwa-86395f53634b3ef1ce76a7f1e5edfdb61f8ffd80.zip
Fix header ranking
Diffstat (limited to 'src/net')
-rw-r--r--src/net/fwd.hpp9
-rw-r--r--src/net/ip.cpp3
-rw-r--r--src/net/ip.hpp2
-rw-r--r--src/net/packets.cpp106
-rw-r--r--src/net/packets.hpp585
-rw-r--r--src/net/socket.cpp16
-rw-r--r--src/net/socket.hpp19
-rw-r--r--src/net/timer.hpp3
-rw-r--r--src/net/timestamp-utils.cpp72
-rw-r--r--src/net/timestamp-utils.hpp54
10 files changed, 150 insertions, 719 deletions
diff --git a/src/net/fwd.hpp b/src/net/fwd.hpp
index 2097772..5de8450 100644
--- a/src/net/fwd.hpp
+++ b/src/net/fwd.hpp
@@ -20,6 +20,13 @@
#include "../sanity.hpp"
+#include "../ints/fwd.hpp" // rank 1
+#include "../strings/fwd.hpp" // rank 1
+#include "../compat/fwd.hpp" // rank 2
+#include "../generic/fwd.hpp" // rank 3
+#include "../io/fwd.hpp" // rank 4
+// net/fwd.hpp is rank 5
+
namespace tmwa
{
@@ -28,6 +35,4 @@ class Session;
class IP4Address;
class TimerData;
-
-enum class RecvResult;
} // namespace tmwa
diff --git a/src/net/ip.cpp b/src/net/ip.cpp
index bfc2028..4ec022b 100644
--- a/src/net/ip.cpp
+++ b/src/net/ip.cpp
@@ -22,8 +22,7 @@
#include "../strings/vstring.hpp"
#include "../io/cxxstdio.hpp"
-
-#include "../mmo/extract.hpp"
+#include "../io/extract.hpp"
#include "../poison.hpp"
diff --git a/src/net/ip.hpp b/src/net/ip.hpp
index e9e71f4..ab45c56 100644
--- a/src/net/ip.hpp
+++ b/src/net/ip.hpp
@@ -25,8 +25,6 @@
#include <cstddef>
#include <cstdint>
-#include "../strings/fwd.hpp"
-
namespace tmwa
{
diff --git a/src/net/packets.cpp b/src/net/packets.cpp
deleted file mode 100644
index 3cba856..0000000
--- a/src/net/packets.cpp
+++ /dev/null
@@ -1,106 +0,0 @@
-#include "packets.hpp"
-// packets.cpp - palatable socket buffer accessors
-//
-// Copyright © 2014 Ben Longbons <b.r.longbons@gmail.com>
-//
-// This file is part of The Mana World (Athena server)
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-#include "../io/cxxstdio.hpp"
-#include "../io/write.hpp"
-
-#include "../poison.hpp"
-
-
-namespace tmwa
-{
-size_t packet_avail(Session *s)
-{
- return s->rdata_size - s->rdata_pos;
-}
-
-bool packet_fetch(Session *s, size_t offset, Byte *data, size_t sz)
-{
- if (packet_avail(s) < offset + sz)
- return false;
- const Byte *start = reinterpret_cast<const Byte *>(&s->rdata[s->rdata_pos + offset]);
- const Byte *end = start + sz;
- std::copy(start, end, data);
- return true;
-}
-void packet_discard(Session *s, size_t sz)
-{
- s->rdata_pos += sz;
-
- assert (s->rdata_size >= s->rdata_pos);
-}
-bool packet_send(Session *s, const Byte *data, size_t sz)
-{
- if (s->wdata_size + sz > s->max_wdata)
- {
- realloc_fifo(s, s->max_rdata, s->max_wdata << 1);
- PRINTF("socket: %d wdata expanded to %zu bytes.\n"_fmt, s, s->max_wdata);
- }
- if (!s->max_wdata || !s->wdata)
- {
- return false;
- }
- s->wdata_size += sz;
-
- Byte *end = reinterpret_cast<Byte *>(&s->wdata[s->wdata_size + 0]);
- Byte *start = end - sz;
- std::copy(data, data + sz, start);
- return true;
-}
-
-void packet_dump(io::WriteFile& logfp, Session *s)
-{
- FPRINTF(logfp,
- "---- 00-01-02-03-04-05-06-07 08-09-0A-0B-0C-0D-0E-0F\n"_fmt);
- char tmpstr[16 + 1] {};
- int i;
- for (i = 0; i < packet_avail(s); i++)
- {
- if ((i & 15) == 0)
- FPRINTF(logfp, "%04X "_fmt, i);
- Byte rfifob_ib;
- packet_fetch(s, i, &rfifob_ib, 1);
- uint8_t rfifob_i = rfifob_ib.value;
- FPRINTF(logfp, "%02x "_fmt, rfifob_i);
- if (rfifob_i > 0x1f)
- tmpstr[i % 16] = rfifob_i;
- else
- tmpstr[i % 16] = '.';
- if ((i - 7) % 16 == 0) // -8 + 1
- FPRINTF(logfp, " "_fmt);
- else if ((i + 1) % 16 == 0)
- {
- FPRINTF(logfp, " %s\n"_fmt, tmpstr);
- std::fill(tmpstr + 0, tmpstr + 17, '\0');
- }
- }
- if (i % 16 != 0)
- {
- for (int j = i; j % 16 != 0; j++)
- {
- FPRINTF(logfp, " "_fmt);
- if ((j - 7) % 16 == 0) // -8 + 1
- FPRINTF(logfp, " "_fmt);
- }
- FPRINTF(logfp, " %s\n"_fmt, tmpstr);
- }
- FPRINTF(logfp, "\n"_fmt);
-}
-} // namespace tmwa
diff --git a/src/net/packets.hpp b/src/net/packets.hpp
deleted file mode 100644
index 5cc377c..0000000
--- a/src/net/packets.hpp
+++ /dev/null
@@ -1,585 +0,0 @@
-#pragma once
-// packets.hpp - palatable socket buffer accessors
-//
-// Copyright © 2014 Ben Longbons <b.r.longbons@gmail.com>
-//
-// This file is part of The Mana World (Athena server)
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-#include "fwd.hpp"
-
-#include <vector>
-
-#include "../compat/cast.hpp"
-
-#include "../ints/little.hpp"
-
-#include "../io/fwd.hpp"
-
-// TODO ordering violation, should invert
-#include "../proto2/fwd.hpp"
-
-#include "socket.hpp"
-
-
-namespace tmwa
-{
-struct Buffer
-{
- std::vector<Byte> bytes;
-};
-
-enum class RecvResult
-{
- Incomplete,
- Complete,
- Error,
-};
-
-enum class SendResult
-{
- Success,
- Fail,
-};
-
-
-size_t packet_avail(Session *s);
-void packet_dump(io::WriteFile& out, Session *s);
-
-bool packet_fetch(Session *s, size_t offset, Byte *data, size_t sz);
-void packet_discard(Session *s, size_t sz);
-bool packet_send(Session *s, const Byte *data, size_t sz);
-
-inline
-bool packet_peek_id(Session *s, uint16_t *packet_id)
-{
- Little16 id;
- bool okay = packet_fetch(s, 0, reinterpret_cast<Byte *>(&id), 2);
- if (okay)
- {
- if (!network_to_native(packet_id, id))
- {
- s->set_eof();
- return false;
- }
- }
- 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))
-RecvResult net_recv_fpacket(Session *s, NetPacket_Fixed<id>& fixed)
-{
- bool ok = packet_fetch(s, 0, reinterpret_cast<Byte *>(&fixed), sizeof(NetPacket_Fixed<id>));
- if (ok)
- {
- packet_discard(s, sizeof(NetPacket_Fixed<id>));
- return RecvResult::Complete;
- }
- return RecvResult::Incomplete;
-}
-
-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>));
- 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;
- repeat.resize(bytes_repeat / sizeof(NetPacket_Repeat<id>));
- if (packet_fetch(s, sizeof(NetPacket_Head<id>), reinterpret_cast<Byte *>(repeat.data()), bytes_repeat))
- {
- packet_discard(s, nat.magic_packet_length);
- return RecvResult::Complete;
- }
- return RecvResult::Incomplete;
- }
- 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_Option<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>
-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>)");
-
- 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))
- {
- return Buffer();
- }
- return buf;
-}
-
-template<uint16_t id>
-Buffer create_ppacket(Packet_Payload<id>& payload)
-{
- static_assert(id == Packet_Payload<id>::PACKET_ID, "Packet_Payload<id>::PACKET_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))
- {
- return Buffer();
- }
- return buf;
-}
-
-template<uint16_t id, uint16_t headsize, uint16_t repeatsize>
-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>)");
-
- // 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)
- {
- return Buffer();
- }
-
- 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))
- {
- return Buffer();
- }
- for (size_t i = 0; i < repeat.size(); ++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]))
- {
- return Buffer();
- }
- }
- return buf;
-}
-
-template<uint16_t id, uint16_t headsize, uint16_t optsize>
-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>)");
-
- // 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)
- {
- return Buffer();
- }
-
- 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))
- {
- 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))
- {
- return Buffer();
- }
- }
-
- 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>
-__attribute__((warn_unused_result))
-RecvResult recv_fpacket(Session *s, Packet_Fixed<id>& fixed)
-{
- static_assert(id == Packet_Fixed<id>::PACKET_ID, "Packet_Fixed<id>::PACKET_ID");
- static_assert(size == sizeof(NetPacket_Fixed<id>), "NetPacket_Fixed<id>");
-
- NetPacket_Fixed<id> net_fixed;
- RecvResult rv = net_recv_fpacket(s, net_fixed);
- 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 (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;
- }
- return rv;
-}
-
-template<uint16_t id, uint16_t headsize, uint16_t repeatsize>
-__attribute__((warn_unused_result))
-RecvResult recv_vpacket(Session *s, Packet_Head<id>& head, 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>), "NetPacket_Head<id>");
- static_assert(id == Packet_Repeat<id>::PACKET_ID, "Packet_Repeat<id>::PACKET_ID");
- static_assert(repeatsize == sizeof(NetPacket_Repeat<id>), "NetPacket_Repeat<id>");
-
- NetPacket_Head<id> net_head;
- std::vector<NetPacket_Repeat<id>> net_repeat;
- RecvResult rv = net_recv_vpacket(s, net_head, net_repeat);
- 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)
- {
- if (!network_to_native(&repeat[i], net_repeat[i]))
- return RecvResult::Error;
- }
- }
- 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
-
-template<uint16_t id, uint16_t headsize, uint16_t repeatsize>
-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>");
- static_assert(id == Packet_Repeat<id>::PACKET_ID, "Packet_Repeat<id>::PACKET_ID");
- static_assert(repeatsize == sizeof(NetPacket_Repeat<id>), "NetPacket_Repeat<id>");
- static_assert(repeatsize == 1, "repeatsize");
-
- // 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)
- {
- return Buffer();
- }
-
- 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))
- {
- return Buffer();
- }
- for (size_t i = 0; i < repeat.size(); ++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])};
- }
- 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>
-__attribute__((warn_unused_result))
-RecvResult recv_vpacket(Session *s, Packet_Head<id>& head, AString& repeat)
-{
- 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_Repeat<id>::PACKET_ID, "Packet_Repeat<id>::PACKET_ID");
- static_assert(repeatsize == sizeof(NetPacket_Repeat<id>), "NetPacket_Repeat<id>");
- static_assert(repeatsize == 1, "repeatsize");
-
- 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;
- // reinterpret_cast is needed to correctly handle an empty vector
- const char *begin = sign_cast<const char *>(net_repeat.data());
- const char *end = begin + net_repeat.size();
- end = std::find(begin, end, '\0');
- repeat = XString(begin, end, nullptr);
- }
- return rv;
-}
-
-
-// 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");
- 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;
- send_vpacket<id, 4, repeatsize>(s, head, v);
-}
-
-template<uint16_t id, uint16_t headsize, uint16_t repeatsize>
-__attribute__((warn_unused_result))
-RecvResult recv_packet_repeatonly(Session *s, 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 recv_vpacket<id, 4, repeatsize>(s, head, 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");
- 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;
- send_vpacket<id, 4, repeatsize>(s, head, repeat);
-}
-
-template<uint16_t id, uint16_t headsize, uint16_t repeatsize>
-__attribute__((warn_unused_result))
-RecvResult recv_packet_repeatonly(Session *s, AString& 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 recv_vpacket<id, 4, repeatsize>(s, head, repeat);
-}
-} // namespace tmwa
diff --git a/src/net/socket.cpp b/src/net/socket.cpp
index a01cd81..fce45fb 100644
--- a/src/net/socket.cpp
+++ b/src/net/socket.cpp
@@ -34,10 +34,6 @@
#include "../io/cxxstdio.hpp"
-// TODO get rid of ordering violations
-#include "../mmo/utils.hpp"
-#include "../mmo/core.hpp"
-
#include "timer.hpp"
#include "../poison.hpp"
@@ -399,7 +395,7 @@ void realloc_fifo(Session *s, size_t rfifo_size, size_t wfifo_size)
}
}
-void do_sendrecv(interval_t next_ms)
+bool do_sendrecv(interval_t next_ms)
{
bool any = false;
io::FD_Set rfd = readfds, wfd;
@@ -419,9 +415,9 @@ void do_sendrecv(interval_t next_ms)
{
PRINTF("Shutting down - nothing to do\n"_fmt);
// TODO hoist this
- runflag = false;
+ return false;
}
- return;
+ return true;
}
struct timeval timeout;
{
@@ -431,7 +427,7 @@ void do_sendrecv(interval_t next_ms)
timeout.tv_usec = next_us.count();
}
if (io::FD_Set::select(fd_max, &rfd, &wfd, nullptr, &timeout) <= 0)
- return;
+ return true;
for (io::FD i : iter_fds())
{
Session *s = get_session(i);
@@ -451,9 +447,10 @@ void do_sendrecv(interval_t next_ms)
s->func_recv(s);
}
}
+ return true;
}
-void do_parsepacket(void)
+bool do_parsepacket(void)
{
for (io::FD i : iter_fds())
{
@@ -483,5 +480,6 @@ void do_parsepacket(void)
/// Reclaim buffer space for what was read
RFIFOFLUSH(s);
}
+ return true;
}
} // namespace tmwa
diff --git a/src/net/socket.hpp b/src/net/socket.hpp
index 576ef85..d6caefd 100644
--- a/src/net/socket.hpp
+++ b/src/net/socket.hpp
@@ -22,20 +22,19 @@
#include "fwd.hpp"
-#include <algorithm>
-
#include <sys/select.h>
+#include <algorithm>
#include <memory>
-#include "../compat/iter.hpp"
-#include "../compat/rawmem.hpp"
-#include "../compat/time_t.hpp"
-
#include "../strings/astring.hpp"
#include "../strings/vstring.hpp"
#include "../strings/xstring.hpp"
+#include "../compat/iter.hpp"
+#include "../compat/rawmem.hpp"
+#include "../compat/time_t.hpp"
+
#include "../generic/dumb_ptr.hpp"
#include "../io/fd.hpp"
@@ -125,8 +124,8 @@ public:
io::FD fd;
- friend void do_sendrecv(interval_t next);
- friend void do_parsepacket(void);
+ friend bool do_sendrecv(interval_t next);
+ friend bool do_parsepacket(void);
friend void delete_session(Session *);
};
@@ -171,7 +170,7 @@ void delete_session(Session *);
/// Make a the internal queues bigger
void realloc_fifo(Session *s, size_t rfifo_size, size_t wfifo_size);
/// Update all sockets that can be read/written from the queues
-void do_sendrecv(interval_t next);
+bool do_sendrecv(interval_t next);
/// Call the parser function for every socket that has read data
-void do_parsepacket(void);
+bool do_parsepacket(void);
} // namespace tmwa
diff --git a/src/net/timer.hpp b/src/net/timer.hpp
index 338e339..5e7cc90 100644
--- a/src/net/timer.hpp
+++ b/src/net/timer.hpp
@@ -21,11 +21,8 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "timer.t.hpp"
-
#include "fwd.hpp"
-#include "../strings/fwd.hpp"
-
namespace tmwa
{
diff --git a/src/net/timestamp-utils.cpp b/src/net/timestamp-utils.cpp
new file mode 100644
index 0000000..b5873ca
--- /dev/null
+++ b/src/net/timestamp-utils.cpp
@@ -0,0 +1,72 @@
+#include "timestamp-utils.hpp"
+// timestamp-utils.cpp - Useful stuff that hasn't been categorized.
+//
+// Copyright © ????-2004 Athena Dev Teams
+// Copyright © 2004-2011 The Mana World Development Team
+// Copyright © 2011-2014 Ben Longbons <b.r.longbons@gmail.com>
+//
+// This file is part of The Mana World (Athena server)
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+#include <sys/time.h>
+
+#include <algorithm>
+
+#include "../strings/xstring.hpp"
+
+#include "../compat/time_t.hpp"
+
+#include "../io/write.hpp"
+
+#include "../poison.hpp"
+
+
+namespace tmwa
+{
+static_assert(sizeof(timestamp_seconds_buffer) == 20, "seconds buffer");
+static_assert(sizeof(timestamp_milliseconds_buffer) == 24, "millis buffer");
+
+void stamp_time(timestamp_seconds_buffer& out, const TimeT *t)
+{
+ struct tm when = t ? *t : TimeT::now();
+ char buf[20];
+ strftime(buf, 20, "%Y-%m-%d %H:%M:%S", &when);
+ out = stringish<timestamp_seconds_buffer>(VString<19>(strings::really_construct_from_a_pointer, buf));
+}
+void stamp_time(timestamp_milliseconds_buffer& out)
+{
+ struct timeval tv;
+ gettimeofday(&tv, nullptr);
+ struct tm when = TimeT(tv.tv_sec);
+ char buf[24];
+ strftime(buf, 20, "%Y-%m-%d %H:%M:%S", &when);
+ sprintf(buf + 19, ".%03d", static_cast<int>(tv.tv_usec / 1000));
+ out = stringish<timestamp_milliseconds_buffer>(VString<23>(strings::really_construct_from_a_pointer, buf));
+}
+
+void log_with_timestamp(io::WriteFile& out, XString line)
+{
+ if (!line)
+ {
+ out.put('\n');
+ return;
+ }
+ timestamp_milliseconds_buffer tmpstr;
+ stamp_time(tmpstr);
+ out.really_put(tmpstr.data(), tmpstr.size());
+ out.really_put(": ", 2);
+ out.put_line(line);
+}
+} // namespace tmwa
diff --git a/src/net/timestamp-utils.hpp b/src/net/timestamp-utils.hpp
new file mode 100644
index 0000000..f5b5dce
--- /dev/null
+++ b/src/net/timestamp-utils.hpp
@@ -0,0 +1,54 @@
+#pragma once
+// timestamp-utils.hpp - Useful stuff that hasn't been categorized.
+//
+// Copyright © ????-2004 Athena Dev Teams
+// Copyright © 2004-2011 The Mana World Development Team
+// Copyright © 2011-2014 Ben Longbons <b.r.longbons@gmail.com>
+//
+// This file is part of The Mana World (Athena server)
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+#include "fwd.hpp"
+
+#include "../strings/vstring.hpp"
+
+
+namespace tmwa
+{
+struct timestamp_seconds_buffer : VString<19> {};
+struct timestamp_milliseconds_buffer : VString<23> {};
+void stamp_time(timestamp_seconds_buffer&, const TimeT *t=nullptr);
+void stamp_time(timestamp_milliseconds_buffer&);
+
+void log_with_timestamp(io::WriteFile& out, XString line);
+
+// TODO VString?
+#define TIMESTAMP_DUMMY "YYYY-MM-DD HH:MM:SS"
+static_assert(sizeof(TIMESTAMP_DUMMY) == sizeof(timestamp_seconds_buffer),
+ "timestamp size");
+#define WITH_TIMESTAMP(str) str TIMESTAMP_DUMMY
+// str: prefix: YYYY-MM-DD HH:MM:SS
+// sizeof: 01234567890123456789012345678
+// str + sizeof: ^
+// -1: ^
+// there's probably a better way to do this now
+#define REPLACE_TIMESTAMP(str, t) \
+ stamp_time( \
+ reinterpret_cast<timestamp_seconds_buffer *>( \
+ str + sizeof(str) \
+ )[-1], \
+ &t \
+ )
+} // namespace tmwa