/* vim: set expandtab ts=4 sw=4: */ /* * You may redistribute this program and/or modify it under the terms of * the GNU General Public License as published by the Free Software Foundation, * either version 3 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef Address_H #define Address_H #include "crypto/AddressCalc.h" #include "util/AddrTools.h" #include "util/Assert.h" #include "util/Bits.h" #include "util/Endian.h" #include "util/Hex.h" #include "util/platform/libc/strlen.h" #include #include #define Address_KEY_SIZE 32 #define Address_NETWORK_ADDR_SIZE 8 #define Address_SEARCH_TARGET_SIZE 16 #define Address_SERIALIZED_SIZE 40 struct Address { union { struct { // tricksy: this is effectively a 64 bit rotate of the following bytes array uint32_t three; uint32_t four; uint32_t one; uint32_t two; } ints; uint8_t bytes[Address_SEARCH_TARGET_SIZE]; } ip6; uint8_t key[Address_KEY_SIZE]; uint64_t path; }; #define Address_SIZE (Address_SEARCH_TARGET_SIZE + Address_KEY_SIZE + Address_NETWORK_ADDR_SIZE) Assert_compileTime(sizeof(struct Address) == Address_SIZE); static inline uint32_t Address_getPrefix(struct Address* addr) { if (addr->ip6.ints.one == 0 && addr->ip6.ints.two == 0 && addr->ip6.ints.three == 0 && addr->ip6.ints.four == 0) { AddressCalc_addressForPublicKey(addr->ip6.bytes, addr->key); } return Endian_bigEndianToHost32(addr->ip6.ints.one); } static inline uint32_t Address_prefixForSearchTarget(const uint8_t searchTarget[16]) { uint32_t prefix_be; Bits_memcpyConst(&prefix_be, &searchTarget[8], 4); return Endian_bigEndianToHost32(prefix_be); } static inline void Address_serialize(uint8_t output[Address_SERIALIZED_SIZE], const struct Address* addr) { Bits_memcpyConst(output, addr->key, Address_SERIALIZED_SIZE); if (!Endian_isBigEndian()) { uint64_t path_be = Endian_hostToBigEndian64(addr->path); Bits_memcpyConst(output + Address_KEY_SIZE, &path_be, Address_NETWORK_ADDR_SIZE); } } static inline void Address_parse(struct Address* addr, const uint8_t input[Address_SERIALIZED_SIZE]) { Bits_memset(addr->ip6.bytes, 0, 16); Bits_memcpyConst(addr->key, input, Address_SERIALIZED_SIZE); addr->path = Endian_bigEndianToHost64(addr->path); } static inline bool Address_isSame(const struct Address* addr, const struct Address* addr2) { return Bits_memcmp(addr->key, addr2->key, Address_SERIALIZED_SIZE) == 0; } static inline bool Address_isSameIp(const struct Address* addr, const struct Address* addr2) { return Bits_memcmp(addr->ip6.bytes, addr2->ip6.bytes, 16) == 0; } static inline bool Address_equalsSearchTarget( struct Address* addr, const uint8_t searchTarget[Address_SEARCH_TARGET_SIZE]) { Address_getPrefix(addr); return Bits_memcmp(addr->ip6.bytes, searchTarget, Address_SEARCH_TARGET_SIZE); } static inline void Address_forKey(struct Address* out, const uint8_t key[Address_KEY_SIZE]) { Bits_memcpyConst(out->key, key, Address_KEY_SIZE); AddressCalc_addressForPublicKey(out->ip6.bytes, key); } static inline void Address_printIp(uint8_t output[40], struct Address* addr) { Address_getPrefix(addr); AddrTools_printIp(output, addr->ip6.bytes); } static inline void Address_print(uint8_t output[60], struct Address* addr) { Address_printIp(output, addr); output[39] = '@'; AddrTools_printPath(output + 40, addr->path); } #endif