fork download
  1. #include <array>
  2. #include <cstdint>
  3. #include <type_traits>
  4. #include <vector>
  5. #include <arpa/inet.h>
  6.  
  7.  
  8. uint8_t NetworkToHost(uint8_t inValue) { return inValue; }
  9. uint16_t NetworkToHost(uint16_t inValue) { return ntohs(inValue); }
  10. uint32_t NetworkToHost(uint32_t inValue) { return ntohl(inValue); }
  11.  
  12. uint8_t HostToNetwork(uint8_t inValue) { return inValue; }
  13. uint16_t HostToNetwork(uint16_t inValue) { return htons(inValue); }
  14. uint32_t HostToNetwork(uint32_t inValue) { return htonl(inValue); }
  15.  
  16.  
  17. /**
  18.  * @brief The NetEncoded class wraps a network-encoded value.
  19.  * Can be constructed from a host-encoded value using the "NetEncode" factory function.
  20.  * This class meets pod requirements and can be used to represent fields in packet headers.
  21.  */
  22. template<typename T>
  23. class NetEncoded
  24. {
  25. public:
  26. T hostValue() const
  27. {
  28. return NetworkToHost(_value);
  29. }
  30.  
  31. T netValue() const
  32. {
  33. return _value;
  34. }
  35.  
  36. friend bool operator<(const NetEncoded & lhs, const NetEncoded & rhs)
  37. {
  38. return lhs._value < rhs._value;
  39. }
  40.  
  41. friend bool operator==(const NetEncoded & lhs, const NetEncoded & rhs)
  42. {
  43. return lhs._value == rhs._value;
  44. }
  45.  
  46. friend bool operator!=(const NetEncoded & lhs, const NetEncoded & rhs)
  47. {
  48. return lhs._value != rhs._value;
  49. }
  50.  
  51. T _value;
  52. };
  53.  
  54.  
  55. /**
  56.  * @brief Net16 holds a 16-bit network-encoded value.
  57.  */
  58. typedef NetEncoded<uint16_t> Net16;
  59.  
  60.  
  61. static_assert(std::is_pod<Net16>::value, "Net16 is not a pod!");
  62. static_assert(sizeof(Net16) == sizeof(uint16_t), "Net16 does not have correct size!");
  63.  
  64.  
  65. /**
  66.  * @brief Net32 holds a 32-bit network-encoded value.
  67.  */
  68. typedef NetEncoded<uint32_t> Net32;
  69.  
  70.  
  71. /**
  72.  * @brief NetEncode overload for creating Net16 from uint16_t
  73.  */
  74. inline Net16 NetEncode(uint16_t value)
  75. {
  76. return { HostToNetwork(value) };
  77. }
  78.  
  79.  
  80. /**
  81.  * @brief NetEncode overload for creating Net32 from uint32_t
  82.  */
  83. inline Net32 NetEncode(uint32_t value)
  84. {
  85. return { HostToNetwork(value) };
  86. }
  87.  
  88.  
  89. /**
  90.  * @brief NetEncode overload for creating Net16 from a 2-byte object.
  91.  * @param An 16-bit object with host-encoding that is explictly convertible to uint16_t.
  92.  */
  93. template<typename T>
  94. inline Net16 NetEncode(T inValue, typename std::enable_if<sizeof(T) == sizeof(uint16_t)>::type * = 0)
  95. {
  96. return NetEncode(static_cast<uint16_t>(inValue));
  97. }
  98.  
  99.  
  100. /**
  101.  * @brief NetEncode overload for creating Net32 from a 4-byte object.
  102.  * @param An 32-bit object with host-encoding that is explictly convertible to uint32_t.
  103.  */
  104. template<typename T>
  105. inline Net32 NetEncode(T inValue, typename std::enable_if<sizeof(T) == sizeof(uint32_t)>::type * = 0)
  106. {
  107. return NetEncode(static_cast<uint32_t>(inValue));
  108. }
  109.  
  110.  
  111. enum class EtherType : uint16_t
  112. {
  113. ARP = 0x0806,
  114. IPv4 = 0x0800,
  115. VLAN = 0x8100,
  116. IPv6 = 0x86DD
  117. };
  118.  
  119. typedef std::array<uint8_t, 6> MACAddress;
  120.  
  121. struct EthernetHeader
  122. {
  123. MACAddress destination;
  124. MACAddress source;
  125. Net16 etherType;
  126. };
  127.  
  128.  
  129. template<typename T>
  130. inline const T & Decode(const uint8_t * bytes)
  131. {
  132. // TODO: Fix potential strict-aliasing problems.
  133. return *reinterpret_cast<const T *>(bytes);
  134. }
  135.  
  136.  
  137. int main()
  138. {
  139. std::vector<uint8_t> data(30);
  140. auto ethernetHeader = Decode<EthernetHeader>(data.data());
  141. auto etherType = static_cast<EtherType>(ethernetHeader.etherType.hostValue());
  142. }
Success #stdin #stdout 0s 3012KB
stdin
Standard input is empty
stdout
Standard output is empty