Skip to content

Commit

Permalink
Introduce BigEndian wrapper and use it for netaddress ports
Browse files Browse the repository at this point in the history
  • Loading branch information
sipa authored and furszy committed Jul 3, 2021
1 parent fb3c646 commit 5c36b3d
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 8 deletions.
10 changes: 2 additions & 8 deletions src/netaddress.h
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ class CSubNet
class CService : public CNetAddr
{
protected:
unsigned short port; // host order
uint16_t port; // host order

public:
CService();
Expand Down Expand Up @@ -172,13 +172,7 @@ class CService : public CNetAddr
inline void SerializationOp(Stream& s, Operation ser_action)
{
READWRITE(ip);

// TODO: introduce native support for BE serialization in serialize.h
unsigned short portN = htons(port);
READWRITE(Span<unsigned char>((unsigned char*)&portN, 2));
if (ser_action.ForRead()) {
port = ntohs(portN);
}
READWRITE(WrapBigEndian(port));
}
};

Expand Down
48 changes: 48 additions & 0 deletions src/serialize.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,11 @@ template<typename Stream> inline void ser_writedata16(Stream &s, uint16_t obj)
obj = htole16(obj);
s.write((char*)&obj, 2);
}
template<typename Stream> inline void ser_writedata16be(Stream &s, uint16_t obj)
{
obj = htobe16(obj);
s.write((char*)&obj, 2);
}
template<typename Stream> inline void ser_writedata32(Stream &s, uint32_t obj)
{
obj = htole32(obj);
Expand All @@ -109,6 +114,12 @@ template<typename Stream> inline uint16_t ser_readdata16(Stream &s)
s.read((char*)&obj, 2);
return le16toh(obj);
}
template<typename Stream> inline uint16_t ser_readdata16be(Stream &s)
{
uint16_t obj;
s.read((char*)&obj, 2);
return be16toh(obj);
}
template<typename Stream> inline uint32_t ser_readdata32(Stream &s)
{
uint32_t obj;
Expand Down Expand Up @@ -461,6 +472,40 @@ class CVarInt
}
};

/** Serialization wrapper class for big-endian integers.
*
* Use this wrapper around integer types that are stored in memory in native
* byte order, but serialized in big endian notation. This is only intended
* to implement serializers that are compatible with existing formats, and
* its use is not recommended for new data structures.
*
* Only 16-bit types are supported for now.
*/
template<typename I>
class BigEndian
{
protected:
I& m_val;
public:
explicit BigEndian(I& val) : m_val(val)
{
static_assert(std::is_unsigned<I>::value, "BigEndian type must be unsigned integer");
static_assert(sizeof(I) == 2 && std::numeric_limits<I>::min() == 0 && std::numeric_limits<I>::max() == std::numeric_limits<uint16_t>::max(), "Unsupported BigEndian size");
}

template<typename Stream>
void Serialize(Stream& s) const
{
ser_writedata16be(s, m_val);
}

template<typename Stream>
void Unserialize(Stream& s)
{
m_val = ser_readdata16be(s);
}
};

class CCompactSize
{
protected:
Expand Down Expand Up @@ -512,6 +557,9 @@ class LimitedString
template<VarIntMode Mode=VarIntMode::DEFAULT, typename I>
CVarInt<Mode, I> WrapVarInt(I& n) { return CVarInt<Mode, I>{n}; }

template<typename I>
BigEndian<I> WrapBigEndian(I& n) { return BigEndian<I>(n); }

/**
* Forward declarations
*/
Expand Down

0 comments on commit 5c36b3d

Please sign in to comment.