zenoh_codec/scouting/
hello.rs

1//
2// Copyright (c) 2023 ZettaScale Technology
3//
4// This program and the accompanying materials are made available under the
5// terms of the Eclipse Public License 2.0 which is available at
6// http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
7// which is available at https://www.apache.org/licenses/LICENSE-2.0.
8//
9// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
10//
11// Contributors:
12//   ZettaScale Zenoh Team, <zenoh@zettascale.tech>
13//
14use alloc::{vec, vec::Vec};
15
16use zenoh_buffers::{
17    reader::{DidntRead, Reader},
18    writer::{DidntWrite, Writer},
19};
20use zenoh_protocol::{
21    common::{imsg, ZExtUnknown},
22    core::{Locator, WhatAmI, ZenohIdProto},
23    scouting::{
24        hello::{flag, HelloProto},
25        id,
26    },
27};
28
29use crate::{RCodec, WCodec, Zenoh080, Zenoh080Header, Zenoh080Length};
30
31impl<W> WCodec<&HelloProto, &mut W> for Zenoh080
32where
33    W: Writer,
34{
35    type Output = Result<(), DidntWrite>;
36
37    fn write(self, writer: &mut W, x: &HelloProto) -> Self::Output {
38        let HelloProto {
39            version,
40            whatami,
41            zid,
42            locators,
43        } = x;
44
45        // Header
46        let mut header = id::HELLO;
47        if !locators.is_empty() {
48            header |= flag::L;
49        }
50        self.write(&mut *writer, header)?;
51
52        // Body
53        self.write(&mut *writer, version)?;
54
55        let mut flags: u8 = 0;
56        let whatami: u8 = match whatami {
57            WhatAmI::Router => 0b00,
58            WhatAmI::Peer => 0b01,
59            WhatAmI::Client => 0b10,
60        };
61        flags |= whatami & 0b11;
62        flags |= ((zid.size() - 1) as u8) << 4;
63        self.write(&mut *writer, flags)?;
64
65        let lodec = Zenoh080Length::new(zid.size());
66        lodec.write(&mut *writer, zid)?;
67
68        if !locators.is_empty() {
69            self.write(&mut *writer, locators.as_slice())?;
70        }
71
72        Ok(())
73    }
74}
75
76impl<R> RCodec<HelloProto, &mut R> for Zenoh080
77where
78    R: Reader,
79{
80    type Error = DidntRead;
81
82    fn read(self, reader: &mut R) -> Result<HelloProto, Self::Error> {
83        let header: u8 = self.read(&mut *reader)?;
84        let codec = Zenoh080Header::new(header);
85        codec.read(reader)
86    }
87}
88
89impl<R> RCodec<HelloProto, &mut R> for Zenoh080Header
90where
91    R: Reader,
92{
93    type Error = DidntRead;
94
95    fn read(self, reader: &mut R) -> Result<HelloProto, Self::Error> {
96        if imsg::mid(self.header) != id::HELLO {
97            return Err(DidntRead);
98        }
99
100        // Body
101        let version: u8 = self.codec.read(&mut *reader)?;
102        let flags: u8 = self.codec.read(&mut *reader)?;
103        let whatami = match flags & 0b11 {
104            0b00 => WhatAmI::Router,
105            0b01 => WhatAmI::Peer,
106            0b10 => WhatAmI::Client,
107            _ => return Err(DidntRead),
108        };
109        let length = 1 + ((flags >> 4) as usize);
110        let lodec = Zenoh080Length::new(length);
111        let zid: ZenohIdProto = lodec.read(&mut *reader)?;
112
113        let locators = if imsg::has_flag(self.header, flag::L) {
114            let locs: Vec<Locator> = self.codec.read(&mut *reader)?;
115            locs
116        } else {
117            vec![]
118        };
119
120        // Extensions
121        let mut has_extensions = imsg::has_flag(self.header, flag::Z);
122        while has_extensions {
123            let (_, more): (ZExtUnknown, bool) = self.codec.read(&mut *reader)?;
124            has_extensions = more;
125        }
126
127        Ok(HelloProto {
128            version,
129            zid,
130            whatami,
131            locators,
132        })
133    }
134}