everscale_network/proto/
adnl.rs

1use std::net::{Ipv4Addr, SocketAddrV4};
2
3use smallvec::SmallVec;
4use tl_proto::{Bare, Boxed, BoxedConstructor, TlError, TlPacket, TlRead, TlResult, TlWrite};
5
6use super::HashRef;
7
8#[derive(Clone)]
9pub struct OutgoingPacketContents<'tl> {
10    /// 7 or 3 random bytes
11    pub rand1: &'tl [u8],
12    pub from: Option<everscale_crypto::tl::PublicKey<'tl>>,
13    pub messages: OutgoingMessages<'tl>,
14    pub address: AddressList,
15    pub seqno: u64,
16    pub confirm_seqno: u64,
17    pub reinit_dates: Option<ReinitDates>,
18    pub signature: Option<&'tl [u8]>,
19    /// 3 or 7 random bytes
20    pub rand2: &'tl [u8],
21}
22
23impl<'tl> TlWrite for OutgoingPacketContents<'tl> {
24    type Repr = Boxed;
25
26    fn max_size_hint(&self) -> usize {
27        4 // constructor
28            + 8 // rand1 (1 byte length, 7 bytes data)
29            + 4 // flags
30            + self.from.max_size_hint()
31            + self.messages.max_size_hint()
32            + self.address.max_size_hint()
33            + 8 // seqno
34            + 8 // confirm_seqno
35            + self.reinit_dates.max_size_hint()
36            + self.signature.max_size_hint()
37            + 4 // rand2 (1 byte length, 3 bytes data)
38    }
39
40    fn write_to<P>(&self, packet: &mut P)
41    where
42        P: TlPacket,
43    {
44        const DEFAULT_FLAGS: u32 = (0b1 << 4) | (0b1 << 6) | (0b1 << 7);
45
46        let flags = DEFAULT_FLAGS
47            | (self.from.is_some() as u32)
48            | if self.messages.is_single() {
49                0b1 << 2
50            } else {
51                0b1 << 3
52            }
53            | ((self.reinit_dates.is_some() as u32) << 10)
54            | ((self.signature.is_some() as u32) << 11);
55
56        packet.write_u32(IncomingPacketContents::TL_ID); // constructor
57        self.rand1.write_to(packet);
58        packet.write_u32(flags);
59        self.from.write_to(packet);
60        self.messages.write_to(packet);
61        self.address.write_to(packet);
62        self.seqno.write_to(packet);
63        self.confirm_seqno.write_to(packet);
64        self.reinit_dates.write_to(packet);
65        self.signature.write_to(packet);
66        self.rand2.write_to(packet);
67    }
68}
69
70#[derive(Copy, Clone)]
71pub enum OutgoingMessages<'a> {
72    Single(&'a [u8]),
73    Pair(&'a [u8]),
74}
75
76impl OutgoingMessages<'_> {
77    #[inline(always)]
78    pub fn is_single(&self) -> bool {
79        matches!(self, Self::Single(_))
80    }
81}
82
83impl<'tl> TlWrite for OutgoingMessages<'tl> {
84    type Repr = Bare;
85
86    #[inline(always)]
87    fn max_size_hint(&self) -> usize {
88        match self {
89            Self::Single(raw) => raw.len(),
90            Self::Pair(raw) => 4 + raw.len(),
91        }
92    }
93
94    #[inline(always)]
95    fn write_to<P>(&self, packet: &mut P)
96    where
97        P: TlPacket,
98    {
99        match self {
100            Self::Single(raw) => packet.write_raw_slice(raw),
101            Self::Pair(raw) => {
102                packet.write_u32(2);
103                packet.write_raw_slice(raw);
104            }
105        }
106    }
107}
108
109#[derive(Clone)]
110pub struct IncomingPacketContents<'tl> {
111    pub from: Option<everscale_crypto::tl::PublicKey<'tl>>,
112    pub from_short: Option<HashRef<'tl>>,
113
114    pub messages: SmallVec<[Message<'tl>; 2]>,
115    pub address: Option<AddressList>,
116
117    pub seqno: Option<u64>,
118    pub confirm_seqno: Option<u64>,
119
120    pub reinit_dates: Option<ReinitDates>,
121
122    pub signature: Option<PacketContentsSignature>,
123}
124
125impl IncomingPacketContents<'_> {
126    const TL_ID: u32 = tl_proto::id!("adnl.packetContents", scheme = "scheme.tl");
127}
128
129impl<'tl> TlRead<'tl> for IncomingPacketContents<'tl> {
130    type Repr = Boxed;
131
132    fn read_from(packet: &'tl [u8], offset: &mut usize) -> TlResult<Self> {
133        #[inline(always)]
134        fn read_optional<'tl, T: TlRead<'tl>, const N: usize>(
135            flags: u32,
136            packet: &'tl [u8],
137            offset: &mut usize,
138        ) -> TlResult<Option<T>> {
139            Ok(if flags & (0b1 << N) != 0 {
140                match T::read_from(packet, offset) {
141                    Ok(value) => Some(value),
142                    Err(e) => return Err(e),
143                }
144            } else {
145                None
146            })
147        }
148
149        match u32::read_from(packet, offset) {
150            Ok(Self::TL_ID) => {}
151            Ok(_) => return Err(TlError::UnknownConstructor),
152            Err(e) => return Err(e),
153        }
154
155        ok!(<&[u8] as TlRead>::read_from(packet, offset)); // rand1
156
157        let flags_offset = *offset as u16;
158        let flags = ok!(u32::read_from(packet, offset));
159
160        let from = ok!(read_optional::<everscale_crypto::tl::PublicKey, 0>(
161            flags, packet, offset
162        ));
163        let from_short = ok!(read_optional::<HashRef, 1>(flags, packet, offset));
164
165        let message = ok!(read_optional::<Message, 2>(flags, packet, offset));
166        let messages = ok!(read_optional::<SmallVec<[Message<'tl>; 2]>, 3>(
167            flags, packet, offset
168        ));
169
170        let address = ok!(read_optional::<AddressList, 4>(flags, packet, offset));
171        ok!(read_optional::<AddressList, 5>(flags, packet, offset)); // priority_address
172
173        let seqno = ok!(read_optional::<u64, 6>(flags, packet, offset));
174        let confirm_seqno = ok!(read_optional::<u64, 7>(flags, packet, offset));
175
176        ok!(read_optional::<u32, 8>(flags, packet, offset)); // recv_addr_list_version
177        ok!(read_optional::<u32, 9>(flags, packet, offset)); // recv_priority_addr_list_version
178
179        let reinit_dates = ok!(read_optional::<ReinitDates, 10>(flags, packet, offset));
180
181        let signature = if flags & (0b1 << 11) != 0 {
182            let signature_start = *offset as u16;
183            let signature = ok!(<&[u8]>::read_from(packet, offset));
184            let signature_end = *offset as u16;
185
186            if signature.len() != 64 {
187                return Err(TlError::UnexpectedEof);
188            }
189
190            Some(PacketContentsSignature {
191                signature: signature.try_into().unwrap(),
192                flags_offset,
193                signature_start,
194                signature_end,
195            })
196        } else {
197            None
198        };
199
200        ok!(<&[u8] as TlRead>::read_from(packet, offset)); // rand2
201
202        Ok(Self {
203            from,
204            from_short,
205            messages: match (messages, message) {
206                (Some(messages), None) => messages,
207                (None, Some(message)) => {
208                    let mut messages = SmallVec::with_capacity(1);
209                    messages.push(message);
210                    messages
211                }
212                (Some(mut messages), Some(message)) => {
213                    messages.insert(0, message);
214                    messages
215                }
216                (None, None) => return Err(TlError::UnexpectedEof),
217            },
218            address,
219            seqno,
220            confirm_seqno,
221            reinit_dates,
222            signature,
223        })
224    }
225}
226
227#[derive(Copy, Clone)]
228pub struct PacketContentsSignature {
229    signature: [u8; 64],
230    flags_offset: u16,
231    signature_start: u16,
232    signature_end: u16,
233}
234
235impl PacketContentsSignature {
236    /// Modifies the content of the packet even though the PacketView
237    /// is passed as a constant reference
238    ///
239    /// # Safety
240    ///
241    /// * Must be called only once on same packet
242    ///
243    pub unsafe fn extract<'a>(self, packet: &mut [u8]) -> Option<(&'a [u8], [u8; 64])> {
244        let origin = packet.as_mut_ptr();
245
246        // `packet` before:
247        // [............_*__.................|__________________|.........]
248        // flags_offset ^     signature_start ^    signature_end ^
249
250        // NOTE: `flags_offset + 1` is used because flags are stored in LE bytes order and
251        // we need the second byte (signature mask - 0x0800)
252        let (signature_len, remaining) = match (packet.len() as u16, self.flags_offset + 1) {
253            (packet_len, flags_offset)
254                if flags_offset < packet_len
255                    && self.signature_start < self.signature_end
256                    && self.signature_end < packet_len =>
257            {
258                packet[flags_offset as usize] &= 0xf7; // reset signature bit
259
260                (
261                    self.signature_end - self.signature_start, // signature len
262                    packet_len - self.signature_end,           // remaining
263                )
264            }
265            _ => return None,
266        };
267
268        let src = origin.add(self.signature_end as usize);
269        let dst = origin.add(self.signature_start as usize);
270        std::ptr::copy(src, dst, remaining as usize);
271
272        // `packet` after:
273        // [............_0__.................||.........]-----removed-----]
274        // flags_offset ^     signature_start ^
275
276        Some((
277            std::slice::from_raw_parts(origin, packet.len() - signature_len as usize),
278            self.signature,
279        ))
280    }
281}
282
283#[derive(Debug, Copy, Clone, TlWrite, TlRead)]
284#[tl(size_hint = 8)]
285pub struct ReinitDates {
286    pub local: u32,
287    pub target: u32,
288}
289
290#[derive(Debug, Copy, Clone, TlRead, TlWrite)]
291#[tl(boxed, scheme = "scheme.tl")]
292pub enum Message<'tl> {
293    #[tl(id = "adnl.message.answer")]
294    Answer {
295        #[tl(size_hint = 32)]
296        query_id: HashRef<'tl>,
297        answer: &'tl [u8],
298    },
299
300    #[tl(id = "adnl.message.custom")]
301    Custom { data: &'tl [u8] },
302
303    #[tl(id = "adnl.message.confirmChannel", size_hint = 68)]
304    ConfirmChannel {
305        key: HashRef<'tl>,
306        peer_key: HashRef<'tl>,
307        date: u32,
308    },
309
310    #[tl(id = "adnl.message.part")]
311    Part {
312        #[tl(size_hint = 32)]
313        hash: HashRef<'tl>,
314        total_size: u32,
315        offset: u32,
316        data: &'tl [u8],
317    },
318
319    #[tl(id = "adnl.message.createChannel", size_hint = 36)]
320    CreateChannel { key: HashRef<'tl>, date: u32 },
321
322    #[tl(id = "adnl.message.query")]
323    Query {
324        #[tl(size_hint = 32)]
325        query_id: HashRef<'tl>,
326        query: &'tl [u8],
327    },
328
329    #[tl(id = "adnl.message.nop", size_hint = 0)]
330    Nop,
331
332    #[tl(id = "adnl.message.reinit", size_hint = 4)]
333    Reinit { date: u32 },
334}
335
336#[derive(Debug, Copy, Clone)]
337pub struct AddressList {
338    /// Single address instead of list, because only one is always passed
339    pub address: Option<Address>,
340    pub version: u32,
341    pub reinit_date: u32,
342    pub expire_at: u32,
343}
344
345impl BoxedConstructor for AddressList {
346    const TL_ID: u32 = tl_proto::id!("adnl.addressList", scheme = "scheme.tl");
347}
348
349impl TlWrite for AddressList {
350    type Repr = Bare;
351
352    fn max_size_hint(&self) -> usize {
353        // 4 bytes - address vector size
354        // optional address size
355        // 4 bytes - version
356        // 4 bytes - reinit_date
357        // 4 bytes - priority
358        // 4 bytes - expire_at
359        20 + self.address.max_size_hint()
360    }
361
362    fn write_to<P>(&self, packet: &mut P)
363    where
364        P: TlPacket,
365    {
366        u32::write_to(&(self.address.is_some() as u32), packet);
367        self.address.write_to(packet);
368        self.version.write_to(packet);
369        self.reinit_date.write_to(packet);
370        0u32.write_to(packet); // priority
371        self.expire_at.write_to(packet);
372    }
373}
374
375impl<'tl> TlRead<'tl> for AddressList {
376    type Repr = Bare;
377
378    fn read_from(packet: &'tl [u8], offset: &mut usize) -> TlResult<Self> {
379        let address_count = ok!(u32::read_from(packet, offset));
380        let mut address = None;
381        for _ in 0..address_count {
382            let item = ok!(Address::read_from(packet, offset));
383            if address.is_none() {
384                address = Some(item);
385            }
386        }
387
388        let version = ok!(u32::read_from(packet, offset));
389        let reinit_date = ok!(u32::read_from(packet, offset));
390        let _priority = ok!(u32::read_from(packet, offset));
391        let expire_at = ok!(u32::read_from(packet, offset));
392
393        Ok(Self {
394            address,
395            version,
396            reinit_date,
397            expire_at,
398        })
399    }
400}
401
402#[derive(Debug, Copy, Clone, TlRead, TlWrite)]
403#[tl(boxed, id = "adnl.address.udp", scheme = "scheme.tl", size_hint = 8)]
404pub struct Address {
405    pub ip: u32,
406    pub port: u32,
407}
408
409impl From<&SocketAddrV4> for Address {
410    fn from(addr: &SocketAddrV4) -> Self {
411        Self {
412            ip: u32::from_be_bytes(addr.ip().octets()),
413            port: addr.port() as u32,
414        }
415    }
416}
417
418impl From<Address> for SocketAddrV4 {
419    fn from(addr: Address) -> Self {
420        Self::new(Ipv4Addr::from(addr.ip), addr.port as u16)
421    }
422}
423
424#[derive(Debug, Copy, Clone, TlRead, TlWrite)]
425#[tl(boxed, id = "adnl.pong", size_hint = 8, scheme = "scheme.tl")]
426pub struct Pong {
427    pub value: u64,
428}
429
430#[cfg(test)]
431mod tests {
432    use super::*;
433
434    #[test]
435    fn correct_addr_conversion() {
436        let addr = SocketAddrV4::new(Ipv4Addr::LOCALHOST, 123);
437
438        let test = Address::from(&addr);
439        assert_eq!(test.ip, 0x7f000001);
440        assert_eq!(test.port, 123);
441
442        let test = SocketAddrV4::from(test);
443        assert_eq!(test, addr);
444    }
445}