#ifndef TMWA_NET_VOMIT_HPP #define TMWA_NET_VOMIT_HPP // vomit.hpp - sickening socket accessors // // Copyright © ????-2004 Athena Dev Teams // Copyright © 2004-2011 The Mana World Development Team // Copyright © 2011-2014 Ben Longbons // // 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 . # include "fwd.hpp" # include "socket.hpp" // these first three are really in socket.cpp // but here for cleanliness /// Check how much can be read inline size_t RFIFOREST(Session *s) { return s->rdata_size - s->rdata_pos; } /// Done reading void RFIFOSKIP(Session *s, size_t len); /// Finish writing void WFIFOSET(Session *s, size_t len); template uint8_t *pod_addressof_m(T& structure) { static_assert(is_trivially_copyable::value, "Can only byte-copy POD-ish structs"); return &reinterpret_cast(structure); } template const uint8_t *pod_addressof_c(const T& structure) { static_assert(is_trivially_copyable::value, "Can only byte-copy POD-ish structs"); return &reinterpret_cast(structure); } /// Read from the queue inline const void *RFIFOP(Session *s, size_t pos) { return &s->rdata[s->rdata_pos + pos]; } inline uint8_t RFIFOB(Session *s, size_t pos) { return *static_cast(RFIFOP(s, pos)); } inline uint16_t RFIFOW(Session *s, size_t pos) { return *static_cast(RFIFOP(s, pos)); } inline uint32_t RFIFOL(Session *s, size_t pos) { return *static_cast(RFIFOP(s, pos)); } template void RFIFO_STRUCT(Session *s, size_t pos, T& structure) { really_memcpy(pod_addressof_m(structure), static_cast(RFIFOP(s, pos)), sizeof(T)); } inline IP4Address RFIFOIP(Session *s, size_t pos) { IP4Address o; RFIFO_STRUCT(s, pos, o); return o; } template inline VString RFIFO_STRING(Session *s, size_t pos) { const char *const begin = static_cast(RFIFOP(s, pos)); const char *const end = begin + len-1; const char *const mid = std::find(begin, end, '\0'); return XString(begin, mid, nullptr); } inline AString RFIFO_STRING(Session *s, size_t pos, size_t len) { const char *const begin = static_cast(RFIFOP(s, pos)); const char *const end = begin + len; const char *const mid = std::find(begin, end, '\0'); return XString(begin, mid, nullptr); } inline void RFIFO_BUF_CLONE(Session *s, uint8_t *buf, size_t len) { really_memcpy(buf, static_cast(RFIFOP(s, 0)), len); } /// Read from an arbitrary buffer inline const void *RBUFP(const uint8_t *p, size_t pos) { return p + pos; } inline uint8_t RBUFB(const uint8_t *p, size_t pos) { return *static_cast(RBUFP(p, pos)); } inline uint16_t RBUFW(const uint8_t *p, size_t pos) { return *static_cast(RBUFP(p, pos)); } inline uint32_t RBUFL(const uint8_t *p, size_t pos) { return *static_cast(RBUFP(p, pos)); } template void RBUF_STRUCT(const uint8_t *p, size_t pos, T& structure) { really_memcpy(pod_addressof_m(structure), p + pos, sizeof(T)); } inline IP4Address RBUFIP(const uint8_t *p, size_t pos) { IP4Address o; RBUF_STRUCT(p, pos, o); return o; } template inline VString RBUF_STRING(const uint8_t *p, size_t pos) { const char *const begin = static_cast(RBUFP(p, pos)); const char *const end = begin + len-1; const char *const mid = std::find(begin, end, '\0'); return XString(begin, mid, nullptr); } inline AString RBUF_STRING(const uint8_t *p, size_t pos, size_t len) { const char *const begin = static_cast(RBUFP(p, pos)); const char *const end = begin + len; const char *const mid = std::find(begin, end, '\0'); return XString(begin, mid, nullptr); } /// Unused - check how much data can be written // the existence of this seems scary inline size_t WFIFOSPACE(Session *s) { return s->max_wdata - s->wdata_size; } /// Write to the queue inline void *WFIFOP(Session *s, size_t pos) { return &s->wdata[s->wdata_size + pos]; } inline uint8_t& WFIFOB(Session *s, size_t pos) { return *static_cast(WFIFOP(s, pos)); } inline uint16_t& WFIFOW(Session *s, size_t pos) { return *static_cast(WFIFOP(s, pos)); } inline uint32_t& WFIFOL(Session *s, size_t pos) { return *static_cast(WFIFOP(s, pos)); } template void WFIFO_STRUCT(Session *s, size_t pos, T& structure) { really_memcpy(static_cast(WFIFOP(s, pos)), pod_addressof_c(structure), sizeof(T)); } inline IP4Address& WFIFOIP(Session *s, size_t pos) { static_assert(is_trivially_copyable::value, "That was the whole point"); return *static_cast(WFIFOP(s, pos)); } inline void WFIFO_STRING(Session *s, size_t pos, XString str, size_t len) { char *const begin = static_cast(WFIFOP(s, pos)); char *const end = begin + len; char *const mid = std::copy(str.begin(), str.end(), begin); std::fill(mid, end, '\0'); } inline void WFIFO_ZERO(Session *s, size_t pos, size_t len) { uint8_t *b = static_cast(WFIFOP(s, pos)); uint8_t *e = b + len; std::fill(b, e, '\0'); } inline void WFIFO_BUF_CLONE(Session *s, const uint8_t *buf, size_t len) { really_memcpy(static_cast(WFIFOP(s, 0)), buf, len); } /// Write to an arbitrary buffer inline void *WBUFP(uint8_t *p, size_t pos) { return p + pos; } inline uint8_t& WBUFB(uint8_t *p, size_t pos) { return *static_cast(WBUFP(p, pos)); } inline uint16_t& WBUFW(uint8_t *p, size_t pos) { return *static_cast(WBUFP(p, pos)); } inline uint32_t& WBUFL(uint8_t *p, size_t pos) { return *static_cast(WBUFP(p, pos)); } template void WBUF_STRUCT(uint8_t *p, size_t pos, T& structure) { really_memcpy(p + pos, pod_addressof_c(structure), sizeof(T)); } inline IP4Address& WBUFIP(uint8_t *p, size_t pos) { return *static_cast(WBUFP(p, pos)); } inline void WBUF_STRING(uint8_t *p, size_t pos, XString s, size_t len) { char *const begin = static_cast(WBUFP(p, pos)); char *const end = begin + len; char *const mid = std::copy(s.begin(), s.end(), begin); std::fill(mid, end, '\0'); } inline void WBUF_ZERO(uint8_t *p, size_t pos, size_t len) { uint8_t *b = static_cast(WBUFP(p, pos)); uint8_t *e = b + len; std::fill(b, e, '\0'); } inline void RFIFO_WFIFO_CLONE(Session *rs, Session *ws, size_t len) { really_memcpy(static_cast(WFIFOP(ws, 0)), static_cast(RFIFOP(rs, 0)), len); } #endif // TMWA_NET_VOMIT_HPP