Merge #12916: Introduce BigEndian wrapper and use it for netaddress ports
ece88fd
Introduce BigEndian wrapper and use it for netaddress ports (Pieter Wuille)
Pull request description:
This is another small improvement taken from #10785.
Instead of manually converting from/to BE format in the `CService` serializer, provide a generic way in serialize.h to serialize BE data (only 16 bits for now).
Tree-SHA512: bd67cf7eed465dad08551fb62f659e755e0691e4597a9f59d285d2b79975b50e5710d35a34a185b5ad232e1deda9a4946615f9132b1ed7d96ed8087f73ace66b
This commit is contained in:
commit
7b6041d1a7
2 changed files with 50 additions and 8 deletions
|
@ -141,7 +141,7 @@ class CSubNet
|
|||
class CService : public CNetAddr
|
||||
{
|
||||
protected:
|
||||
unsigned short port; // host order
|
||||
uint16_t port; // host order
|
||||
|
||||
public:
|
||||
CService();
|
||||
|
@ -168,13 +168,7 @@ class CService : public CNetAddr
|
|||
template <typename Stream, typename Operation>
|
||||
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));
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -79,6 +79,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);
|
||||
|
@ -101,6 +106,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;
|
||||
|
@ -416,6 +427,40 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
/** 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:
|
||||
|
@ -466,6 +511,9 @@ public:
|
|||
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
|
||||
*/
|
||||
|
|
Loading…
Reference in a new issue