My goal is to create a unique ID for all IP address - port pair. The UID must be same across systems (no conflict for different endian systems). Size of IPV4 UID is 6 bytes and for ipv6 is 18 bytes.
uint8_t sourcePair[18]; /*ipv4=(4+2) bytes or ipv6=(16+2) bytes*/
I have two functions that will take the remote endpoint of a socket and get the desired UID. The design is as follows.
void CmdInterpreter::makeSourcePairV4(asio::ip::tcp::endpoint& remoteEp, unsigned short portNum, unsigned char(&binSourcePair)[18])
{
auto addressClass = remoteEp.address().to_v4();
auto ipBin = addressClass.to_uint();
memcpy(&binSourcePair[0], &ipBin, 4);
memcpy(&binSourcePair[4], &portNum, 2);
}
void CmdInterpreter::makeSourcePairV6(asio::ip::tcp::endpoint& remoteEp, unsigned short portNum, unsigned char(&binSourcePair)[18])
{
auto addressClass = remoteEp.address().to_v6();
auto ipBin = addressClass.to_bytes();
memcpy(&binSourcePair[0], &ipBin[0], 16);
memcpy(&binSourcePair[16], &portNum, 2);
}
This is how these functions are called
remoteEp = socketPtr->remote_endpoint();
if (remoteEp.address().is_v4())
CmdInterpreter::makeSourcePairV4(remoteEp, remoteEp.port(), sourcePair);
else
CmdInterpreter::makeSourcePairV6(remoteEp, remoteEp.port(), sourcePair);
Here the problem is the only way to access the IPv6 underlying data is using to_byte() which will give the data in network byte order. Also, I am doing a memcopy in unsigned short which is multibyte in length. Does this work? Is it a safe way? Is their any workarounds?
For both IPv4 and IPv6 address, use to_byte() function to get the remote endpoint address in big-endian format. For little-endian host, the port number will make endianness problem which can be fixed by swapping the bytes. To encode it to base 64 I used cppcodec library.
The template function used to swap the port number is: