aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/netaddress.h10
-rw-r--r--src/serialize.h48
2 files changed, 50 insertions, 8 deletions
diff --git a/src/netaddress.h b/src/netaddress.h
index b3d1407f72..38f8709257 100644
--- a/src/netaddress.h
+++ b/src/netaddress.h
@@ -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));
}
};
diff --git a/src/serialize.h b/src/serialize.h
index 57e434faf1..e54c7483d2 100644
--- a/src/serialize.h
+++ b/src/serialize.h
@@ -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
*/