Skip to main content

buntrail_protocol/
negotiation.rs

1use crate::{frame::*, types::*};
2pub const INITIAL_CREDIT: usize = 512 * 1024;
3pub const CAPABILITIES: &[&str] = &[
4    "git.repository.v1",
5    "container.binding.v1",
6    "leases",
7    "leases.retirement",
8    "leases.observe",
9    "operations",
10    "file.read",
11    "file.resolve",
12    "file.remove",
13    "file.save",
14    "file.save_proof",
15    "services",
16    "git.read",
17    "git.existing",
18    "git.worktree_proof",
19    "git.original_lookup",
20    "terminal",
21    "terminal.ordered_controls",
22];
23#[derive(Clone)]
24pub struct Negotiated {
25    pub minor: u32,
26    pub capabilities: Vec<String>,
27    pub max_header: usize,
28    pub max_payload: usize,
29}
30impl Negotiated {
31    pub fn from_hello(header: &Header) -> Result<Self, &'static str> {
32        header.validate(0, None)?;
33        let Message::Hello {
34            capabilities,
35            max_header,
36            max_payload,
37        } = &header.message
38        else {
39            return Err("hello required");
40        };
41        if *max_header < 1024 || *max_payload < 65536 {
42            return Err("limits cannot support required control and chunk frames");
43        }
44        Ok(Self {
45            minor: MINOR,
46            capabilities: CAPABILITIES
47                .iter()
48                .filter(|c| capabilities.iter().any(|v| v == **c))
49                .map(|s| s.to_string())
50                .collect(),
51            max_header: *max_header as usize,
52            max_payload: *max_payload as usize,
53        })
54    }
55    pub fn supports(&self, name: &str) -> bool {
56        self.capabilities.iter().any(|s| s == name)
57    }
58}