Skip to main content

netget/server/dbus/
wire.rs

1//! The D-Bus wire protocol (D-Bus Specification 0.43), shared by NetGet's server and client:
2//! the SASL handshake that precedes messages, and messages themselves — the fixed header, the
3//! header fields, and a body marshalled by its type signature. Bodies are converted to and from
4//! JSON so the model never sees bytes: a signature says how a JSON value is encoded.
5//!
6//! NetGet writes little-endian (`l`) and reads both byte orders. Two bounds are enforced before
7//! anything is allocated or recursed into: a message is at most [`MAX_MESSAGE_BYTES`], and
8//! containers — arrays, structs, dict entries and **variants** — nest at most [`MAX_DEPTH`]
9//! deep (half the specification's 64; see the constant). Variants matter: a signature is at most 255 bytes, but a variant carries its own
10//! signature inside the data, so without a counter seven bytes per level nest without limit.
11use anyhow::{bail, ensure, Context, Result};
12use serde_json::{json, Map, Value};
13use tokio::io::{AsyncBufRead, AsyncBufReadExt, AsyncRead, AsyncReadExt};
14
15/// The most a message may be, header and body. The specification allows 128 MiB.
16pub const MAX_MESSAGE_BYTES: usize = 1 << 20;
17/// Container nesting, variants included. The specification allows 64 (32 arrays + 32
18/// structs); NetGet allows 32, because a decoded value becomes JSON inside an event, and the
19/// event and handler pipeline bounds JSON at 64 levels: a 64-deep value plus its event's own
20/// wrapping does not fit, and was refused there instead of here.
21pub const MAX_DEPTH: usize = 32;
22/// One SASL line, and how many lines the handshake may take.
23pub const MAX_AUTH_LINE: usize = 16 * 1024;
24pub const MAX_AUTH_LINES: usize = 32;
25
26pub const METHOD_CALL: u8 = 1;
27pub const METHOD_RETURN: u8 = 2;
28pub const ERROR: u8 = 3;
29pub const SIGNAL: u8 = 4;
30pub const NO_REPLY_EXPECTED: u8 = 0x1;
31
32pub const BUS_NAME: &str = "org.freedesktop.DBus";
33pub const BUS_PATH: &str = "/org/freedesktop/DBus";
34
35pub fn type_name(kind: u8) -> &'static str {
36    match kind {
37        METHOD_CALL => "method_call",
38        METHOD_RETURN => "method_return",
39        ERROR => "error",
40        SIGNAL => "signal",
41        _ => "unknown",
42    }
43}
44
45/// One complete type.
46#[derive(Debug, Clone, PartialEq)]
47pub enum Ty {
48    Byte,
49    Bool,
50    I16,
51    U16,
52    I32,
53    U32,
54    I64,
55    U64,
56    Double,
57    Str,
58    Path,
59    Sig,
60    Fd,
61    Var,
62    Array(Box<Ty>),
63    Dict(Box<Ty>, Box<Ty>),
64    Struct(Vec<Ty>),
65}
66
67impl Ty {
68    fn align(&self) -> usize {
69        match self {
70            Ty::Byte | Ty::Sig | Ty::Var => 1,
71            Ty::I16 | Ty::U16 => 2,
72            Ty::Bool
73            | Ty::I32
74            | Ty::U32
75            | Ty::Str
76            | Ty::Path
77            | Ty::Fd
78            | Ty::Array(_)
79            | Ty::Dict(..) => 4,
80            Ty::I64 | Ty::U64 | Ty::Double | Ty::Struct(_) => 8,
81        }
82    }
83
84    fn is_basic(&self) -> bool {
85        !matches!(self, Ty::Var | Ty::Array(_) | Ty::Dict(..) | Ty::Struct(_))
86    }
87
88    pub fn signature(&self) -> String {
89        match self {
90            Ty::Byte => "y".into(),
91            Ty::Bool => "b".into(),
92            Ty::I16 => "n".into(),
93            Ty::U16 => "q".into(),
94            Ty::I32 => "i".into(),
95            Ty::U32 => "u".into(),
96            Ty::I64 => "x".into(),
97            Ty::U64 => "t".into(),
98            Ty::Double => "d".into(),
99            Ty::Str => "s".into(),
100            Ty::Path => "o".into(),
101            Ty::Sig => "g".into(),
102            Ty::Fd => "h".into(),
103            Ty::Var => "v".into(),
104            Ty::Array(t) => format!("a{}", t.signature()),
105            Ty::Dict(k, v) => format!("a{{{}{}}}", k.signature(), v.signature()),
106            Ty::Struct(ts) => format!("({})", ts.iter().map(Ty::signature).collect::<String>()),
107        }
108    }
109}
110
111/// Parse a signature into its complete types. At most 255 bytes, 32 nested arrays and 32
112/// nested structs, as the specification requires.
113pub fn parse_signature(sig: &str) -> Result<Vec<Ty>> {
114    ensure!(sig.len() <= 255, "a signature is at most 255 bytes");
115    let bytes = sig.as_bytes();
116    let mut pos = 0;
117    let mut out = Vec::new();
118    while pos < bytes.len() {
119        out.push(parse_one(bytes, &mut pos, 0, 0)?);
120    }
121    Ok(out)
122}
123
124fn parse_one(b: &[u8], pos: &mut usize, arrays: usize, structs: usize) -> Result<Ty> {
125    let c = *b.get(*pos).context("the signature ends inside a type")?;
126    *pos += 1;
127    Ok(match c {
128        b'y' => Ty::Byte,
129        b'b' => Ty::Bool,
130        b'n' => Ty::I16,
131        b'q' => Ty::U16,
132        b'i' => Ty::I32,
133        b'u' => Ty::U32,
134        b'x' => Ty::I64,
135        b't' => Ty::U64,
136        b'd' => Ty::Double,
137        b's' => Ty::Str,
138        b'o' => Ty::Path,
139        b'g' => Ty::Sig,
140        b'h' => Ty::Fd,
141        b'v' => Ty::Var,
142        b'a' => {
143            ensure!(
144                arrays < 32,
145                "arrays nest more than 32 deep in the signature"
146            );
147            if b.get(*pos) == Some(&b'{') {
148                *pos += 1;
149                let k = parse_one(b, pos, arrays + 1, structs)?;
150                ensure!(k.is_basic(), "a dict key must be a basic type");
151                let v = parse_one(b, pos, arrays + 1, structs)?;
152                ensure!(
153                    b.get(*pos) == Some(&b'}'),
154                    "a dict entry has exactly two types"
155                );
156                *pos += 1;
157                Ty::Dict(Box::new(k), Box::new(v))
158            } else {
159                Ty::Array(Box::new(parse_one(b, pos, arrays + 1, structs)?))
160            }
161        }
162        b'(' => {
163            ensure!(
164                structs < 32,
165                "structs nest more than 32 deep in the signature"
166            );
167            let mut fields = Vec::new();
168            while b.get(*pos) != Some(&b')') {
169                fields.push(parse_one(b, pos, arrays, structs + 1)?);
170            }
171            *pos += 1;
172            ensure!(!fields.is_empty(), "a struct has at least one field");
173            Ty::Struct(fields)
174        }
175        other => bail!("{:?} is not a D-Bus type code", other as char),
176    })
177}
178
179pub fn valid_object_path(p: &str) -> bool {
180    p == "/"
181        || (p.starts_with('/')
182            && !p.ends_with('/')
183            && p[1..].split('/').all(|e| {
184                !e.is_empty() && e.bytes().all(|c| c.is_ascii_alphanumeric() || c == b'_')
185            }))
186}
187
188pub fn valid_member(m: &str) -> bool {
189    !m.is_empty()
190        && m.len() <= 255
191        && !m.as_bytes()[0].is_ascii_digit()
192        && m.bytes().all(|c| c.is_ascii_alphanumeric() || c == b'_')
193}
194
195pub fn valid_interface(i: &str) -> bool {
196    i.len() <= 255
197        && i.split('.').count() >= 2
198        && i.split('.').all(|e| {
199            !e.is_empty()
200                && !e.as_bytes()[0].is_ascii_digit()
201                && e.bytes().all(|c| c.is_ascii_alphanumeric() || c == b'_')
202        })
203}
204
205pub fn valid_bus_name(n: &str) -> bool {
206    if n.len() > 255 || n.split('.').count() < 2 {
207        return false;
208    }
209    let unique = n.starts_with(':');
210    let body = n.strip_prefix(':').unwrap_or(n);
211    body.split('.').all(|e| {
212        !e.is_empty()
213            && (unique || !e.as_bytes()[0].is_ascii_digit())
214            && e.bytes()
215                .all(|c| c.is_ascii_alphanumeric() || c == b'_' || c == b'-')
216    })
217}
218
219struct W {
220    buf: Vec<u8>,
221}
222
223impl W {
224    fn pad(&mut self, a: usize) {
225        while !self.buf.len().is_multiple_of(a) {
226            self.buf.push(0);
227        }
228    }
229
230    fn u32(&mut self, v: u32) {
231        self.pad(4);
232        self.buf.extend(v.to_le_bytes());
233    }
234
235    fn string(&mut self, s: &str) -> Result<()> {
236        ensure!(!s.contains('\0'), "a D-Bus string cannot contain NUL");
237        self.u32(s.len() as u32);
238        self.buf.extend(s.as_bytes());
239        self.buf.push(0);
240        Ok(())
241    }
242
243    fn sig(&mut self, s: &str) -> Result<()> {
244        ensure!(s.len() <= 255, "a signature is at most 255 bytes");
245        self.buf.push(s.len() as u8);
246        self.buf.extend(s.as_bytes());
247        self.buf.push(0);
248        Ok(())
249    }
250
251    fn put(&mut self, ty: &Ty, v: &Value, depth: usize) -> Result<()> {
252        ensure!(depth <= MAX_DEPTH, "values nest more than {MAX_DEPTH} deep");
253        ensure!(
254            self.buf.len() <= MAX_MESSAGE_BYTES,
255            "the message exceeds {MAX_MESSAGE_BYTES} bytes"
256        );
257        let int = |lo: i128, hi: i128| -> Result<i128> {
258            let n = v
259                .as_i64()
260                .map(i128::from)
261                .or_else(|| v.as_u64().map(i128::from))
262                .or_else(|| v.as_str().and_then(|s| s.parse::<i128>().ok()))
263                .with_context(|| format!("{v} is not a whole number for {}", ty.signature()))?;
264            ensure!(
265                (lo..=hi).contains(&n),
266                "{n} does not fit D-Bus type {}",
267                ty.signature()
268            );
269            Ok(n)
270        };
271        let text = || {
272            v.as_str()
273                .with_context(|| format!("{v} is not a string for {}", ty.signature()))
274        };
275        match ty {
276            Ty::Byte => self.buf.push(int(0, 255)? as u8),
277            Ty::Bool => {
278                let b = v
279                    .as_bool()
280                    .or_else(|| v.as_u64().filter(|n| *n <= 1).map(|n| n == 1));
281                self.u32(u32::from(
282                    b.with_context(|| format!("{v} is not a boolean"))?,
283                ));
284            }
285            Ty::I16 => {
286                self.pad(2);
287                self.buf
288                    .extend((int(i16::MIN.into(), i16::MAX.into())? as i16).to_le_bytes());
289            }
290            Ty::U16 => {
291                self.pad(2);
292                self.buf
293                    .extend((int(0, u16::MAX.into())? as u16).to_le_bytes());
294            }
295            Ty::I32 => self.u32(int(i32::MIN.into(), i32::MAX.into())? as i32 as u32),
296            Ty::U32 => self.u32(int(0, u32::MAX.into())? as u32),
297            Ty::I64 => {
298                self.pad(8);
299                self.buf
300                    .extend((int(i64::MIN.into(), i64::MAX.into())? as i64).to_le_bytes());
301            }
302            Ty::U64 => {
303                self.pad(8);
304                self.buf
305                    .extend((int(0, u64::MAX.into())? as u64).to_le_bytes());
306            }
307            Ty::Double => {
308                self.pad(8);
309                let d = v.as_f64().with_context(|| format!("{v} is not a number"))?;
310                self.buf.extend(d.to_le_bytes());
311            }
312            Ty::Str => self.string(text()?)?,
313            Ty::Path => {
314                let p = text()?;
315                ensure!(valid_object_path(p), "{p:?} is not a D-Bus object path");
316                self.string(p)?;
317            }
318            Ty::Sig => {
319                let s = text()?;
320                parse_signature(s)?;
321                self.sig(s)?;
322            }
323            Ty::Fd => bail!("NetGet does not pass Unix file descriptors"),
324            Ty::Var => {
325                let (inner, value) = variant_parts(v)?;
326                let tys = parse_signature(&inner)?;
327                ensure!(
328                    tys.len() == 1,
329                    "a variant holds exactly one complete type, not {inner:?}"
330                );
331                self.sig(&inner)?;
332                self.put(&tys[0], &value, depth + 1)?;
333            }
334            Ty::Array(elem) => {
335                let items = v
336                    .as_array()
337                    .with_context(|| format!("{v} is not an array for {}", ty.signature()))?;
338                self.container(elem.align(), |w| {
339                    for item in items {
340                        w.put(elem, item, depth + 1)?;
341                    }
342                    Ok(())
343                })?;
344            }
345            Ty::Dict(k, val) => {
346                let entries: Vec<(Value, Value)> = match v {
347                    Value::Object(map) => map
348                        .iter()
349                        .map(|(key, x)| (key_value(k, key), x.clone()))
350                        .collect(),
351                    Value::Array(pairs) => pairs
352                        .iter()
353                        .map(|p| match p.as_array().map(Vec::as_slice) {
354                            Some([a, b]) => Ok((a.clone(), b.clone())),
355                            _ => bail!("a dict given as an array holds [key, value] pairs"),
356                        })
357                        .collect::<Result<_>>()?,
358                    _ => bail!("{v} is not an object for {}", ty.signature()),
359                };
360                self.container(8, |w| {
361                    for (key, x) in &entries {
362                        w.pad(8);
363                        w.put(k, key, depth + 1)?;
364                        w.put(val, x, depth + 1)?;
365                    }
366                    Ok(())
367                })?;
368            }
369            Ty::Struct(fields) => {
370                let items = v.as_array().with_context(|| {
371                    format!("{v} is not an array for struct {}", ty.signature())
372                })?;
373                ensure!(
374                    items.len() == fields.len(),
375                    "struct {} takes {} values, not {}",
376                    ty.signature(),
377                    fields.len(),
378                    items.len()
379                );
380                self.pad(8);
381                for (f, item) in fields.iter().zip(items) {
382                    self.put(f, item, depth + 1)?;
383                }
384            }
385        }
386        Ok(())
387    }
388
389    /// An array: its byte length, padding to the element alignment (not counted), elements.
390    fn container(
391        &mut self,
392        elem_align: usize,
393        body: impl FnOnce(&mut W) -> Result<()>,
394    ) -> Result<()> {
395        self.u32(0);
396        let len_at = self.buf.len() - 4;
397        self.pad(elem_align);
398        let start = self.buf.len();
399        body(self)?;
400        let len = (self.buf.len() - start) as u32;
401        self.buf[len_at..len_at + 4].copy_from_slice(&len.to_le_bytes());
402        Ok(())
403    }
404}
405
406/// A JSON object key as the dict's key type wants it.
407fn key_value(k: &Ty, key: &str) -> Value {
408    match k {
409        Ty::Str | Ty::Path | Ty::Sig => json!(key),
410        Ty::Bool => json!(key == "true"),
411        Ty::Double => key.parse::<f64>().map_or(json!(key), |d| json!(d)),
412        _ => key
413            .parse::<i64>()
414            .map(|n| json!(n))
415            .or_else(|_| key.parse::<u64>().map(|n| json!(n)))
416            .unwrap_or_else(|_| json!(key)),
417    }
418}
419
420/// A variant as the model writes it: `{"signature": "s", "value": ...}`, or a plain JSON
421/// value whose signature is inferred (string s, bool b, integer i or x or t, number d, array
422/// of strings as, other array av, object a{sv}).
423pub fn variant_parts(v: &Value) -> Result<(String, Value)> {
424    if let Some(map) = v.as_object() {
425        if map.len() == 2 {
426            if let (Some(Value::String(s)), Some(inner)) = (map.get("signature"), map.get("value"))
427            {
428                return Ok((s.clone(), inner.clone()));
429            }
430        }
431    }
432    Ok((infer_signature(v)?, v.clone()))
433}
434
435pub fn infer_signature(v: &Value) -> Result<String> {
436    Ok(match v {
437        Value::Null => {
438            bail!("null has no D-Bus type; give the variant as {{\"signature\", \"value\"}}")
439        }
440        Value::Bool(_) => "b".into(),
441        Value::Number(n) if n.is_i64() => {
442            if i32::try_from(n.as_i64().unwrap_or_default()).is_ok() {
443                "i".into()
444            } else {
445                "x".into()
446            }
447        }
448        Value::Number(n) if n.is_u64() => "t".into(),
449        Value::Number(_) => "d".into(),
450        Value::String(_) => "s".into(),
451        Value::Array(items) if !items.is_empty() && items.iter().all(Value::is_string) => {
452            "as".into()
453        }
454        Value::Array(_) => "av".into(),
455        Value::Object(_) => "a{sv}".into(),
456    })
457}
458
459/// Marshal values by signature; the signature and the bytes.
460pub fn marshal(signature: &str, values: &[Value]) -> Result<Vec<u8>> {
461    let tys = parse_signature(signature)?;
462    ensure!(
463        tys.len() == values.len(),
464        "signature {signature:?} has {} values, {} were given",
465        tys.len(),
466        values.len()
467    );
468    let mut w = W { buf: Vec::new() };
469    for (t, v) in tys.iter().zip(values) {
470        w.put(t, v, 0)?;
471    }
472    ensure!(
473        w.buf.len() <= MAX_MESSAGE_BYTES,
474        "the body exceeds {MAX_MESSAGE_BYTES} bytes"
475    );
476    Ok(w.buf)
477}
478
479struct R<'a> {
480    b: &'a [u8],
481    pos: usize,
482    big: bool,
483}
484
485impl R<'_> {
486    fn align(&mut self, a: usize) -> Result<()> {
487        let to = self.pos.div_ceil(a) * a;
488        ensure!(to <= self.b.len(), "the message ends inside padding");
489        self.pos = to;
490        Ok(())
491    }
492
493    fn take(&mut self, n: usize) -> Result<&[u8]> {
494        let end = self
495            .pos
496            .checked_add(n)
497            .filter(|e| *e <= self.b.len())
498            .context("the message ends inside a value")?;
499        let s = &self.b[self.pos..end];
500        self.pos = end;
501        Ok(s)
502    }
503
504    fn u32(&mut self) -> Result<u32> {
505        let big = self.big;
506        self.align(4)?;
507        let s = self.take(4)?;
508        let a = [s[0], s[1], s[2], s[3]];
509        Ok(if big {
510            u32::from_be_bytes(a)
511        } else {
512            u32::from_le_bytes(a)
513        })
514    }
515
516    fn u16(&mut self) -> Result<u16> {
517        let big = self.big;
518        self.align(2)?;
519        let s = self.take(2)?;
520        Ok(if big {
521            u16::from_be_bytes([s[0], s[1]])
522        } else {
523            u16::from_le_bytes([s[0], s[1]])
524        })
525    }
526
527    fn u64(&mut self) -> Result<u64> {
528        let big = self.big;
529        self.align(8)?;
530        let s = self.take(8)?;
531        let mut a = [0u8; 8];
532        a.copy_from_slice(s);
533        Ok(if big {
534            u64::from_be_bytes(a)
535        } else {
536            u64::from_le_bytes(a)
537        })
538    }
539
540    fn string(&mut self) -> Result<String> {
541        let len = self.u32()? as usize;
542        let s = self.take(len)?.to_vec();
543        ensure!(self.take(1)? == [0], "a string is not NUL-terminated");
544        String::from_utf8(s).context("a string is not valid UTF-8")
545    }
546
547    fn sig(&mut self) -> Result<String> {
548        let len = self.take(1)?[0] as usize;
549        let s = self.take(len)?.to_vec();
550        ensure!(self.take(1)? == [0], "a signature is not NUL-terminated");
551        String::from_utf8(s).context("a signature is not ASCII")
552    }
553
554    fn get(&mut self, ty: &Ty, depth: usize) -> Result<Value> {
555        ensure!(depth <= MAX_DEPTH, "values nest more than {MAX_DEPTH} deep");
556        Ok(match ty {
557            Ty::Byte => json!(self.take(1)?[0]),
558            Ty::Bool => {
559                let n = self.u32()?;
560                ensure!(n <= 1, "a boolean is {n}");
561                json!(n == 1)
562            }
563            Ty::I16 => json!(self.u16()? as i16),
564            Ty::U16 => json!(self.u16()?),
565            Ty::I32 => json!(self.u32()? as i32),
566            Ty::U32 | Ty::Fd => json!(self.u32()?),
567            Ty::I64 => json!(self.u64()? as i64),
568            Ty::U64 => json!(self.u64()?),
569            Ty::Double => json!(f64::from_bits(self.u64()?)),
570            Ty::Str => json!(self.string()?),
571            Ty::Path => {
572                let p = self.string()?;
573                ensure!(valid_object_path(&p), "{p:?} is not an object path");
574                json!(p)
575            }
576            Ty::Sig => {
577                let s = self.sig()?;
578                parse_signature(&s)?;
579                json!(s)
580            }
581            Ty::Var => {
582                let s = self.sig()?;
583                let tys = parse_signature(&s)?;
584                ensure!(
585                    tys.len() == 1,
586                    "a variant holds one complete type, not {s:?}"
587                );
588                json!({"signature": s, "value": self.get(&tys[0], depth + 1)?})
589            }
590            Ty::Array(elem) => {
591                let end = self.array_end(elem.align())?;
592                let mut items = Vec::new();
593                while self.pos < end {
594                    items.push(self.get(elem, depth + 1)?);
595                }
596                ensure!(self.pos == end, "an array's elements overrun its length");
597                Value::Array(items)
598            }
599            Ty::Dict(k, v) => {
600                let end = self.array_end(8)?;
601                let mut map = Map::new();
602                while self.pos < end {
603                    self.align(8)?;
604                    let key = match self.get(k, depth + 1)? {
605                        Value::String(s) => s,
606                        other => other.to_string(),
607                    };
608                    let value = self.get(v, depth + 1)?;
609                    map.insert(key, value);
610                }
611                ensure!(self.pos == end, "a dict's entries overrun its length");
612                Value::Object(map)
613            }
614            Ty::Struct(fields) => {
615                self.align(8)?;
616                let mut items = Vec::with_capacity(fields.len());
617                for f in fields {
618                    items.push(self.get(f, depth + 1)?);
619                }
620                Value::Array(items)
621            }
622        })
623    }
624
625    fn array_end(&mut self, elem_align: usize) -> Result<usize> {
626        let len = self.u32()? as usize;
627        ensure!(
628            len <= 64 << 20,
629            "an array of {len} bytes exceeds the specification's 64 MiB"
630        );
631        self.align(elem_align)?;
632        self.pos
633            .checked_add(len)
634            .filter(|e| *e <= self.b.len())
635            .context("an array's length overruns the message")
636    }
637}
638
639#[derive(Debug, Clone, Default, PartialEq)]
640pub struct Message {
641    pub kind: u8,
642    pub flags: u8,
643    pub serial: u32,
644    pub path: Option<String>,
645    pub interface: Option<String>,
646    pub member: Option<String>,
647    pub error_name: Option<String>,
648    pub reply_serial: Option<u32>,
649    pub destination: Option<String>,
650    pub sender: Option<String>,
651    pub signature: String,
652    /// The body, one JSON value per complete type of `signature`.
653    pub body: Vec<Value>,
654}
655
656impl Message {
657    pub fn call(path: &str, interface: Option<&str>, member: &str) -> Self {
658        Message {
659            kind: METHOD_CALL,
660            path: Some(path.into()),
661            interface: interface.map(Into::into),
662            member: Some(member.into()),
663            ..Default::default()
664        }
665    }
666
667    /// A METHOD_RETURN for `call`, sent from `sender` (the name it was addressed to).
668    pub fn reply_to(call: &Message, signature: &str, body: Vec<Value>) -> Self {
669        Message {
670            kind: METHOD_RETURN,
671            reply_serial: Some(call.serial),
672            destination: call.sender.clone(),
673            sender: call.destination.clone(),
674            signature: signature.into(),
675            body,
676            ..Default::default()
677        }
678    }
679
680    pub fn error_to(call: &Message, name: &str, message: &str) -> Self {
681        Message {
682            kind: ERROR,
683            reply_serial: Some(call.serial),
684            error_name: Some(name.into()),
685            destination: call.sender.clone(),
686            sender: call.destination.clone(),
687            signature: "s".into(),
688            body: vec![json!(message)],
689            ..Default::default()
690        }
691    }
692
693    pub fn expects_reply(&self) -> bool {
694        self.kind == METHOD_CALL && self.flags & NO_REPLY_EXPECTED == 0
695    }
696
697    /// The first string argument, as an ERROR's message is.
698    pub fn first_string(&self) -> Option<&str> {
699        self.body.first().and_then(Value::as_str)
700    }
701
702    pub fn encode(&self) -> Result<Vec<u8>> {
703        ensure!(self.serial != 0, "a message's serial is never 0");
704        let body = marshal(&self.signature, &self.body)?;
705        let mut w = W {
706            buf: vec![b'l', self.kind, self.flags, 1],
707        };
708        w.u32(body.len() as u32);
709        w.u32(self.serial);
710        let field = |w: &mut W, code: u8, sig: &str, v: &Value| -> Result<()> {
711            w.pad(8);
712            w.buf.push(code);
713            w.sig(sig)?;
714            w.put(&parse_signature(sig)?[0], v, 1)
715        };
716        w.container(8, |w| {
717            if let Some(p) = &self.path {
718                field(w, 1, "o", &json!(p))?;
719            }
720            if let Some(i) = &self.interface {
721                ensure!(valid_interface(i), "{i:?} is not a D-Bus interface name");
722                field(w, 2, "s", &json!(i))?;
723            }
724            if let Some(m) = &self.member {
725                ensure!(valid_member(m), "{m:?} is not a D-Bus member name");
726                field(w, 3, "s", &json!(m))?;
727            }
728            if let Some(e) = &self.error_name {
729                ensure!(valid_interface(e), "{e:?} is not a D-Bus error name");
730                field(w, 4, "s", &json!(e))?;
731            }
732            if let Some(r) = self.reply_serial {
733                field(w, 5, "u", &json!(r))?;
734            }
735            if let Some(d) = &self.destination {
736                ensure!(valid_bus_name(d), "{d:?} is not a D-Bus bus name");
737                field(w, 6, "s", &json!(d))?;
738            }
739            if let Some(s) = &self.sender {
740                field(w, 7, "s", &json!(s))?;
741            }
742            if !self.signature.is_empty() {
743                field(w, 8, "g", &json!(self.signature))?;
744            }
745            Ok(())
746        })?;
747        w.pad(8);
748        w.buf.extend(body);
749        ensure!(
750            w.buf.len() <= MAX_MESSAGE_BYTES,
751            "the message exceeds {MAX_MESSAGE_BYTES} bytes"
752        );
753        Ok(w.buf)
754    }
755}
756
757/// Read one message. Its announced size is checked against [`MAX_MESSAGE_BYTES`] from the
758/// fixed header, before the rest is read. `Ok(None)` at a clean end of stream.
759pub async fn read_message<Rd: AsyncRead + Unpin>(r: &mut Rd) -> Result<Option<Message>> {
760    let mut head = [0u8; 16];
761    match r.read_exact(&mut head).await {
762        Ok(_) => {}
763        Err(e) if e.kind() == std::io::ErrorKind::UnexpectedEof => return Ok(None),
764        Err(e) => return Err(e.into()),
765    }
766    let big = match head[0] {
767        b'l' => false,
768        b'B' => true,
769        other => bail!("{other:#04x} is not a D-Bus byte-order mark"),
770    };
771    ensure!(head[3] == 1, "D-Bus protocol version {} is not 1", head[3]);
772    let word = |at: usize| {
773        let a = [head[at], head[at + 1], head[at + 2], head[at + 3]];
774        (if big {
775            u32::from_be_bytes(a)
776        } else {
777            u32::from_le_bytes(a)
778        }) as usize
779    };
780    let (body_len, fields_len) = (word(4), word(12));
781    let total = 16usize.saturating_add(fields_len).saturating_add(7) / 8 * 8;
782    let total = total.saturating_add(body_len);
783    ensure!(
784        total <= MAX_MESSAGE_BYTES,
785        "the peer announced a {total}-byte message; the bound is {MAX_MESSAGE_BYTES}"
786    );
787    let mut buf = head.to_vec();
788    buf.resize(total, 0);
789    r.read_exact(&mut buf[16..]).await?;
790    decode(&buf).map(Some)
791}
792
793pub fn decode(buf: &[u8]) -> Result<Message> {
794    let big = buf[0] == b'B';
795    let mut r = R {
796        b: buf,
797        pos: 4,
798        big,
799    };
800    let body_len = r.u32()? as usize;
801    let serial = r.u32()?;
802    ensure!(serial != 0, "a message's serial is never 0");
803    let mut m = Message {
804        kind: buf[1],
805        flags: buf[2],
806        serial,
807        ..Default::default()
808    };
809    let fields_end = r.array_end(8)?;
810    while r.pos < fields_end {
811        r.align(8)?;
812        let code = r.take(1)?[0];
813        let sig = r.sig()?;
814        let tys = parse_signature(&sig)?;
815        ensure!(tys.len() == 1, "a header field holds one complete type");
816        let v = r.get(&tys[0], 1)?;
817        let s = || {
818            v.as_str()
819                .map(str::to_string)
820                .context("a header field has the wrong type")
821        };
822        match (code, sig.as_str()) {
823            (1, "o") => m.path = Some(s()?),
824            (2, "s") => m.interface = Some(s()?),
825            (3, "s") => m.member = Some(s()?),
826            (4, "s") => m.error_name = Some(s()?),
827            (5, "u") => m.reply_serial = v.as_u64().map(|n| n as u32),
828            (6, "s") => m.destination = Some(s()?),
829            (7, "s") => m.sender = Some(s()?),
830            (8, "g") => m.signature = s()?,
831            (9, "u") => ensure!(
832                v.as_u64() == Some(0),
833                "NetGet does not accept Unix file descriptors"
834            ),
835            (1..=9, other) => bail!("header field {code} has type {other:?}"),
836            _ => {} // unknown fields are ignored, as the specification requires
837        }
838    }
839    ensure!(
840        r.pos == fields_end,
841        "the header fields overrun their length"
842    );
843    r.align(8)?;
844    ensure!(
845        buf.len() - r.pos == body_len,
846        "the body is not the announced {body_len} bytes"
847    );
848    match m.kind {
849        METHOD_CALL => ensure!(
850            m.path.is_some() && m.member.is_some(),
851            "a method call needs a path and a member"
852        ),
853        METHOD_RETURN => ensure!(
854            m.reply_serial.is_some(),
855            "a method return needs a reply serial"
856        ),
857        ERROR => ensure!(
858            m.error_name.is_some() && m.reply_serial.is_some(),
859            "an error needs a name and a reply serial"
860        ),
861        SIGNAL => ensure!(
862            m.path.is_some() && m.interface.is_some() && m.member.is_some(),
863            "a signal needs a path, an interface and a member"
864        ),
865        _ => {} // unknown types are ignored by the caller, as the specification requires
866    }
867    for ty in parse_signature(&m.signature)? {
868        m.body.push(r.get(&ty, 0)?);
869    }
870    ensure!(
871        r.pos == buf.len(),
872        "the body has bytes its signature does not account for"
873    );
874    Ok(m)
875}
876
877/// One CRLF-terminated SASL line, at most [`MAX_AUTH_LINE`] bytes.
878pub async fn read_auth_line<B: AsyncBufRead + Unpin>(r: &mut B) -> Result<String> {
879    let mut line = Vec::new();
880    loop {
881        let chunk = r.fill_buf().await?;
882        ensure!(
883            !chunk.is_empty(),
884            "the peer closed the connection during authentication"
885        );
886        match chunk.iter().position(|b| *b == b'\n') {
887            Some(i) => {
888                line.extend(&chunk[..=i]);
889                r.consume(i + 1);
890                break;
891            }
892            None => {
893                let n = chunk.len();
894                line.extend_from_slice(chunk);
895                r.consume(n);
896            }
897        }
898        ensure!(
899            line.len() <= MAX_AUTH_LINE,
900            "an authentication line exceeds {MAX_AUTH_LINE} bytes"
901        );
902    }
903    ensure!(
904        line.len() <= MAX_AUTH_LINE,
905        "an authentication line exceeds {MAX_AUTH_LINE} bytes"
906    );
907    let text = String::from_utf8(line).context("an authentication line is not ASCII")?;
908    Ok(text.trim_end_matches(['\r', '\n']).to_string())
909}
910
911/// SASL's hex encoding of a string (EXTERNAL's identity, ANONYMOUS's trace).
912pub fn hex_ascii(s: &str) -> String {
913    hex::encode(s.as_bytes())
914}
915
916pub fn random_guid() -> String {
917    hex::encode(rand::random::<[u8; 16]>())
918}