123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328 |
- /* 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 <https://www.gnu.org/licenses/>.
- */
- #ifndef Announce_H
- #define Announce_H
- #include "util/version/Version.h"
- #include "util/Assert.h"
- #include "util/Endian.h"
- #include "util/Bits.h"
- #include "util/Gcc.h"
- // NOTE: Length of 0 in a Announce message is invalid.
- // Length of 1 is by definition a pad byte.
- // Length field allows parsers to skip over entries which they do not understand.
- enum Announce_Type {
- Announce_Type_ENCODING_SCHEME,
- Announce_Type_PEER,
- Announce_Type_VERSION
- };
- struct Announce_Version
- {
- // Announce_Version_SIZE
- uint8_t length;
- // Announce_Type_VERSION
- uint8_t type;
- uint16_t version_be;
- };
- #define Announce_Version_SIZE 4
- Assert_compileTime(sizeof(struct Announce_Version) == Announce_Version_SIZE);
- static void Announce_Version_init(struct Announce_Version* v)
- {
- v->length = Announce_Version_SIZE;
- v->type = Announce_Type_VERSION;
- v->version_be = Endian_hostToBigEndian16(Version_CURRENT_PROTOCOL);
- }
- struct Announce_EncodingScheme
- {
- // Length of `scheme` + 2
- uint8_t length;
- // Announce_Type_ENCODING_SCHEME
- uint8_t type;
- // real length is `length` - 2
- uint8_t scheme[2];
- };
- static inline void Announce_EncodingScheme_push(struct Message* pushTo, String* compressedScheme)
- {
- Assert_true(compressedScheme->len + 2 < 256);
- Message_push(pushTo, compressedScheme->bytes, compressedScheme->len, NULL);
- Message_push8(pushTo, Announce_Type_ENCODING_SCHEME, NULL);
- Message_push8(pushTo, compressedScheme->len + 2, NULL);
- while ((uintptr_t)pushTo->bytes % 4) {
- Message_push8(pushTo, 1, NULL);
- }
- }
- /**
- * 1 2 3
- * 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * 0 | length | type | encodingForm | flags |
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * 4 | MTU (8 byte units) | drops |
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * 8 | latency | penalty |
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * 12 | |
- * + +
- * 16 | |
- * + Peer IPv6 +
- * 20 | |
- * + +
- * 24 | |
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * 28 | label |
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- */
- struct Announce_Peer
- {
- // Announce_Peer_SIZE
- uint8_t length;
- // Announce_Type_PEER
- uint8_t type;
- // The number of the encoding form needed for getting to this node via the peer.
- uint8_t encodingFormNum;
- // no flags yet but maybe in the future...
- uint8_t flags;
- // MTU of the link in 8 byte units.
- // 0 is unknown
- // 0xffff = MTU of 542280 bytes
- uint16_t mtu8_be;
- // Fraction of packets dropped in previous time-window (out of 65k)
- // 0xffff is unknown
- uint16_t drops_be;
- // Average latency of packets in previous time-window (milliseconds)
- // 0xffff is unknown
- uint16_t latency_be;
- // Penalty which would be applied to a packet (with current penalty 0)
- // if it passes through this link.
- // 0xffff is unknown
- uint16_t penalty_be;
- // Ipv6 of a node from which this node is reachable
- uint8_t ipv6[16];
- // Label for getting to this node from the given node
- // 0 means withdraw the link.
- uint32_t label_be;
- };
- #define Announce_Peer_SIZE 32
- Assert_compileTime(sizeof(struct Announce_Peer) == Announce_Peer_SIZE);
- static inline void Announce_Peer_init(struct Announce_Peer* peer)
- {
- Bits_memset(peer, 0, Announce_Peer_SIZE);
- peer->length = Announce_Peer_SIZE;
- peer->type = Announce_Type_PEER;
- }
- struct Announce_ItemHeader
- {
- uint8_t length;
- uint8_t type;
- };
- /**
- * 1 2 3
- * 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * 0 | |
- * + +
- * 4 | |
- * + +
- * 8 | |
- * + +
- * 12 | |
- * + +
- * 16 | |
- * + +
- * 20 | |
- * + +
- * 24 | |
- * + +
- * 28 | |
- * + Signature +
- * 32 | |
- * + +
- * 36 | |
- * + +
- * 40 | |
- * + +
- * 44 | |
- * + +
- * 48 | |
- * + +
- * 52 | |
- * + +
- * 56 | |
- * + +
- * 60 | |
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * 64 | |
- * + +
- * 68 | |
- * + +
- * 72 | |
- * + +
- * 76 | |
- * + Public Signing Key +
- * 80 | |
- * + +
- * 84 | |
- * + +
- * 88 | |
- * + +
- * 92 | |
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * 96 | |
- * + +
- * 100 | |
- * + SuperNode IP +
- * 104 | |
- * + +
- * 108 | |
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * 112 | |
- * + Timestamp +-+-+-+-+
- * 116 | |R| ver |
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- */
- struct Announce_Header
- {
- // Signature of the header concatinated with the SHA-512 of the set of
- uint8_t signature[64];
- // Public signing key (can be derived to crypto key, see Sign.h)
- uint8_t pubSigningKey[32];
- // This is the IPv6 of the supernode which we are announcing to.
- // Including this allows supernodes to replicate only messages which:
- // 1. Indicate that a subnode has changed its supernode
- // 2. Update a link state which affects best paths between clusters of nodes that
- // are controlled by a given supernode.
- uint8_t snodeIp[16];
- // Milliseconds since the epoch when this message was crafted and reset flag
- uint64_t timeStampVersionFlags_be;
- };
- #define Announce_Header_SIZE 120
- Assert_compileTime(sizeof(struct Announce_Header) == Announce_Header_SIZE);
- static inline int64_t Announce_Header_getTimestamp(struct Announce_Header* hdr)
- {
- return Endian_bigEndianToHost64(hdr->timeStampVersionFlags_be) >> 4;
- }
- static inline void Announce_Header_setTimestamp(struct Announce_Header* hdr,
- int64_t timestamp)
- {
- uint64_t uTime = (uint64_t) timestamp;
- // This will fail on January 1, 20892770.
- // It will also fail for negative timestamps.
- Assert_true(!(uTime >> 60));
- hdr->timeStampVersionFlags_be =
- (hdr->timeStampVersionFlags_be & Endian_hostToBigEndian64(0x0f)) |
- Endian_hostToBigEndian64(uTime << 4);
- }
- static inline bool Announce_Header_isReset(struct Announce_Header* hdr)
- {
- return (Endian_bigEndianToHost64(hdr->timeStampVersionFlags_be) >> 3) & 1;
- }
- static inline void Announce_Header_setReset(struct Announce_Header* hdr, bool isReset)
- {
- if (isReset) {
- hdr->timeStampVersionFlags_be |= Endian_hostToBigEndian64(1<<3);
- } else {
- hdr->timeStampVersionFlags_be &= ~Endian_hostToBigEndian64(1<<3);
- }
- }
- static inline int Announce_Header_getVersion(struct Announce_Header* hdr)
- {
- return Endian_bigEndianToHost64(hdr->timeStampVersionFlags_be) & 0x07;
- }
- #define Announce_Header_CURRENT_VERSION 1
- static inline void Announce_Header_setVersion(struct Announce_Header* hdr, int version)
- {
- hdr->timeStampVersionFlags_be =
- (hdr->timeStampVersionFlags_be & ~Endian_hostToBigEndian64(0x07)) |
- Endian_hostToBigEndian64(version & 0x07);
- }
- static inline struct Announce_ItemHeader* Announce_ItemHeader_next(struct Message* msg, void* last)
- {
- struct Announce_ItemHeader* ih = (struct Announce_ItemHeader*) last;
- if (ih) {
- Assert_true((uint8_t*)ih > &msg->bytes[-msg->padding]);
- Assert_true((uint8_t*)ih < &msg->bytes[msg->length]);
- ih = (struct Announce_ItemHeader*) ( &((uint8_t*) ih)[ih->length] );
- } else {
- ih = (struct Announce_ItemHeader*) &msg->bytes[Announce_Header_SIZE];
- }
- while ((uint8_t*)ih < &msg->bytes[msg->length]) {
- if (!ih->length) { return NULL; } // invalid message
- if (ih->length > 1) {
- if ( &((uint8_t*) ih)[ih->length] > &msg->bytes[msg->length] ) {
- // invalid message, overflow...
- return NULL;
- }
- return ih;
- }
- ih = (struct Announce_ItemHeader*) ( &((uint8_t*) ih)[ih->length] );
- }
- return NULL;
- }
- static inline bool Announce_isValid(struct Message* msg)
- {
- struct Announce_ItemHeader* ih = NULL;
- for (;;) {
- ih = Announce_ItemHeader_next(msg, ih);
- if (!ih) { return false; }
- if ((uint8_t*)ih == &msg->bytes[msg->length - ih->length]) { return true; }
- }
- }
- static inline struct Announce_Peer* Announce_Peer_next(struct Message* msg, void* last)
- {
- struct Announce_ItemHeader* ih = (struct Announce_ItemHeader*) last;
- do {
- ih = Announce_ItemHeader_next(msg, ih);
- } while (ih && ih->type != Announce_Type_PEER);
- return (struct Announce_Peer*) ih;
- }
- #endif
|