1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167
//! This module exports logic on deserialized announcement message use cjdns_core::{EncodingScheme, RoutingLabel}; use cjdns_crypto::hash::sha512; use cjdns_keys::{CJDNS_IP6, CJDNSPublicKey}; /// Deserialized cjdns route announcement message. /// /// Contains header, entities and other relevant senders data. /// A `binary_hash` field stands for the sha512 hash of announcement [packet](struct.Announcement.html#structfield.binary). #[derive(Debug, Clone, PartialEq, Eq)] pub struct Announcement { pub header: AnnouncementHeader, pub entities: AnnouncementEntities, pub node_pub_key: CJDNSPublicKey, pub node_ip: CJDNS_IP6, pub binary: Vec<u8>, pub hash: AnnHash, } /// Deserialized announcement message header. /// /// As it was stated previously, header size is 120 bytes: /// * `signature` takes first 64 bytes; /// * `pub_signing_key` takes 32 bytes after the `signature`; /// * `super_node_ip6` length is 16 bytes as it should be for cjdns IPv6 addresses. /// /// Rest data packed in 8 bytes and reserved for `timestamp`. Fields `is_reset` and `version` are encoded in first 4 bits from the right of the `timestamp`. #[derive(Debug, Clone, PartialEq, Eq)] pub struct AnnouncementHeader { pub signature: String, pub pub_signing_key: String, pub snode_ip: CJDNS_IP6, pub version: u8, pub is_reset: bool, pub timestamp: u64, } /// A sequence of entities in the announcement message. pub type AnnouncementEntities = Vec<Entity>; /// An array of slots storing network link samples. pub type LinkStateSlots<T> = [Option<T>; LINK_STATE_SLOTS as usize]; /// Samples are collected every 10 seconds, normally messages are submitted to the Route Server every minute, /// resulting in 6 samples. But we would store 3 times more samples so that if there is some reason it is unable /// to submit a message to the route server for up to 3 minutes, still no link state samples will be lost. pub const LINK_STATE_SLOTS: u8 = 18; /// Announcement message entity types. #[derive(Debug, Clone, PartialEq, Eq)] pub enum Entity { /// The packet diagram for version entity looks as follows: /// ```md /// 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 | version | /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ /// ``` /// /// * **length**: version entity length is always 4 /// * **type**: version entity type is always 2 /// * **version**: big endian representation of the protocol version of the node NodeProtocolVersion(u16), /// The packet diagram for peer entity looks as follows: /// ```md /// 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 | encoding form | flags | /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ /// 4 | MTU (8 byte units) | peer number | /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ /// 8 | unused | /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ /// 12 | | /// + + /// 16 | | /// + Peer IPv6 + /// 20 | | /// + + /// 24 | | /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ /// 28 | label | /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ /// ``` /// /// * **length**: peer length is always 32 /// * **type**: peer type is 1 /// * **encoding form**: this is the number of the form within the encoding scheme which is the smallest /// form that can represent the Director for reaching the peer from the announcer. Yes, you read that /// right, even though the entity is designed for reaching the announcer from the peer, in order /// to chain links for making a label, one must have the inverse encoding form for each hop such that /// the reverse label will be the same size as the forward label. /// * **flags**: A field for flags for future use such as whether the link is simplex or other /// information. Currently there are no flags. /// * **MTU8**: The maximum message size for messages going to the announcer from the peer. If this /// is set to zero it indicates the announcer is not aware of the MTU. /// * **peer number**: number of the peer in the network switch which corresponds to that peer. /// Used for referencing in [LinkState](enum.Entity.html#variant.LinkState) /// * **unused**: alignment padding. /// * **Peer IPv6**: The cjdns IPv6 address of the peer from which this node can be reached. /// * **label**: The label fragment (Director) which should be used for constructing a label for /// reaching the announcer from the peer. A label of 0 indicates that the route is being withdrawn and it is no longer usable. /// This is limited to 32 bits because 32 bits is the largest Director that can be represented in an encoding scheme. /// /// **Note:** The `label` field is an `Option`: zero label parsed as `None` (the route is being withdrawn and it is no longer usable), /// nonzero label is `Some(label)`. Peer(PeerData), /// As `EncodingScheme` serialization does not have a fixed width in bytes, `EncodingScheme` entities are /// prefixed with a number of pads in order that their length will be a multiple of four bytes. /// /// `hex` stands for hex string representation of serialized encoding `scheme`. EncodingScheme { hex: String, scheme: EncodingScheme }, /// `LinkState` stores data, which is used by route server/super node to plot good paths /// through the network and avoid links which have long or unreliable delay. /// So the data under `LinkState` represents the quality of network link. LinkState(LinkStateData), } #[derive(Debug, Clone, PartialEq, Eq)] pub struct PeerData { pub ipv6: CJDNS_IP6, pub label: Option<RoutingLabel<u32>>, pub mtu: u32, pub peer_num: u16, pub unused: u32, pub encoding_form_number: u8, pub flags: u8, } #[derive(Debug, Clone, PartialEq, Eq)] pub struct LinkStateData { pub node_id: u16, pub starting_point: u8, pub lag_slots: LinkStateSlots<u16>, pub drop_slots: LinkStateSlots<u16>, pub kb_recv_slots: LinkStateSlots<u32>, } /// 512-bit hash #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct AnnHash(pub Vec<u8>); impl AnnHash { #[inline] pub fn from_digest(digest: sha512::Digest) -> Self { let data = &digest.0[..]; AnnHash(Vec::from(data)) } #[inline] pub fn into_inner(self) -> Vec<u8> { let AnnHash(bytes) = self; bytes } #[inline] pub fn bytes(&self) -> &[u8] { let AnnHash(bytes) = self; &bytes } }