esp8266ndn
NDN Arduino library for ESP8266 and more
Loading...
Searching...
No Matches
ipv6-endpointid.hpp
Go to the documentation of this file.
1#ifndef NDNPH_PORT_TRANSPORT_SOCKET_IPV6_ENDPOINTID_HPP
2#define NDNPH_PORT_TRANSPORT_SOCKET_IPV6_ENDPOINTID_HPP
3
4#include "../../../core/common.hpp"
5
6namespace ndnph {
7namespace port_transport_socket {
8
18template<int capacity>
20public:
22 m_interns.fill({});
23 }
24
32 uint64_t encode(const uint8_t* addr, size_t addrLen, uint16_t port) {
33 EndpointId ep{};
34 ep.port = port;
35 if (addrLen == 4) {
36 std::copy_n(addr, 4, ep.v4);
37 return ep.id;
38 }
39 if (addrLen != 16) {
40 return 0;
41 }
42
43 ep.v6a = addr[9];
44 ep.v6b = addr[10];
45 ep.v6c = addr[13];
46 ep.v6d = addr[14];
47 ep.v6e = addr[15];
48 Intern r{addr[0], addr[1], addr[2], addr[3], addr[4], addr[5],
49 addr[6], addr[7], addr[8], addr[11], addr[12]};
50 ep.v6sum = computeChecksum(r);
51
52 auto found = std::find(m_interns.begin(), m_interns.end(), r);
53 if (found != m_interns.end()) {
54 ep.v6ref = 1 + std::distance(m_interns.begin(), found);
55 } else {
56 m_interns[m_internPos] = r;
57 ep.v6ref = ++m_internPos;
58 if (m_internPos == m_interns.size()) {
59 m_internPos = 0;
60 }
61 }
62 return ep.id;
63 }
64
72 size_t decode(uint64_t endpointId, uint8_t addr[16], uint16_t* port) {
73 EndpointId ep{};
74 ep.id = endpointId;
75 *port = ep.port;
76 if (!ep.isV6) {
77 std::copy_n(ep.v4, 4, addr);
78 return 4;
79 }
80
81 if (ep.v6ref == 0 || ep.v6ref > m_interns.size()) {
82 return 0;
83 }
84 auto r = m_interns[ep.v6ref - 1];
85 if (computeChecksum(r) != ep.v6sum) {
86 return 0;
87 }
88 std::copy_n(r.begin(), 9, addr);
89 addr[9] = ep.v6a;
90 addr[10] = ep.v6b;
91 addr[11] = r[9];
92 addr[12] = r[10];
93 addr[13] = ep.v6c;
94 addr[14] = ep.v6d;
95 addr[15] = ep.v6e;
96 return 16;
97 }
98
99private:
100 union EndpointId {
101 uint64_t id;
102 struct {
103 uint16_t port;
104 uint8_t v4[4];
105 uint16_t isV6;
106 };
107 struct {
108 // [____:____:____:____:__AA:BB__:__CC:DDEE]:port
109 uint16_t port_;
110 uint8_t v6a;
111 uint8_t v6b;
112 uint8_t v6c;
113 uint8_t v6d;
114 uint8_t v6e;
115 uint8_t v6ref : 4;
116 uint8_t v6sum : 4;
117 };
118 };
119 static_assert(sizeof(EndpointId) == sizeof(uint64_t), "");
120 static_assert(offsetof(EndpointId, port) == offsetof(EndpointId, port_), "");
121
122 // [AABB:CCDD:EEFF:GGHH:II__:__JJ:KK__:____]:____
123 using Intern = std::array<uint8_t, 11>;
124
125 // Rationale of choosing which bits go into EndpointId and which bits go into Intern:
126 // maximize the possibility of two IPv6 addresses have the same Intern entry.
127 // * Within a LAN, /64 network prefix AABB:CCDD:EEFF:GGHH is the same.
128 // * When using SLAAC and EUI-64, JJ:KK is always "FF-FE".
129 // * II has 6~7 bits of entropy because MAC address I/G bit is always zero.
130
131 uint8_t computeChecksum(const Intern& r) {
132 uint8_t sum = 0;
133 for (uint8_t b : r) {
134 sum ^= b;
135 }
136 return (sum & 0x0F) ^ (sum >> 4);
137 }
138
139private:
140 static_assert(capacity <= 15, "");
141 std::array<Intern, capacity> m_interns;
142 uint8_t m_internPos = 0;
143};
144
145} // namespace port_transport_socket
146} // namespace ndnph
147
148#endif // NDNPH_PORT_TRANSPORT_SOCKET_IPV6_ENDPOINTID_HPP
Helper to pack IPv6 endpoint into 64-bit EndpointId.
Definition ipv6-endpointid.hpp:19
size_t decode(uint64_t endpointId, uint8_t addr[16], uint16_t *port)
Unpack IP address+port from EndpointId.
Definition ipv6-endpointid.hpp:72
Ipv6EndpointIdHelper()
Definition ipv6-endpointid.hpp:21
uint64_t encode(const uint8_t *addr, size_t addrLen, uint16_t port)
Pack IP address+port into EndpointId.
Definition ipv6-endpointid.hpp:32
Definition fs.hpp:33