Implement opt-in overlay TUN runtime
This commit is contained in:
parent
c2dee50dae
commit
d9728a326d
15 changed files with 2315 additions and 84 deletions
|
|
@ -5,7 +5,10 @@ use geth_discovery::{DiscoveredPeer, PeerCard};
|
|||
use geth_document::{DocumentResource, DocumentState};
|
||||
use geth_keychain::{KeychainOp, KeychainOpSignature, NodeEnrollmentRequest, NodeRecord};
|
||||
use geth_kv::{KvEntry, KvResource, KvSyncEntry};
|
||||
use geth_overlay::{OverlayJoinPlan, OverlayNetworkStatus, OverlayPlan};
|
||||
use geth_overlay::{
|
||||
OverlayInterfacePlan, OverlayJoinPlan, OverlayNetworkStatus, OverlayPacket, OverlayPlan,
|
||||
OverlayRuntimeStatus,
|
||||
};
|
||||
use geth_pipe::{PipeConnection, PipeListener, PipeMessage};
|
||||
use geth_pubsub::PubsubMessage;
|
||||
use geth_resource::ResourceDescriptor;
|
||||
|
|
@ -57,6 +60,31 @@ pub enum ControlRequest {
|
|||
OverlayLeave {
|
||||
name: String,
|
||||
},
|
||||
OverlayInterfacePlan {
|
||||
name: String,
|
||||
platform: Option<String>,
|
||||
},
|
||||
OverlayUp {
|
||||
name: String,
|
||||
bearer_secret: Option<String>,
|
||||
mtu: Option<u16>,
|
||||
},
|
||||
OverlayDown {
|
||||
name: String,
|
||||
},
|
||||
OverlayPeers {
|
||||
name: String,
|
||||
},
|
||||
OverlaySend {
|
||||
name: String,
|
||||
node: String,
|
||||
packet_base64: String,
|
||||
bearer_secret: Option<String>,
|
||||
},
|
||||
OverlayRecv {
|
||||
name: String,
|
||||
peek: bool,
|
||||
},
|
||||
CasAdd {
|
||||
path: PathBuf,
|
||||
},
|
||||
|
|
@ -501,6 +529,37 @@ pub enum ControlResponse {
|
|||
stopped: bool,
|
||||
note: String,
|
||||
},
|
||||
OverlayInterfacePlanned {
|
||||
plan: OverlayInterfacePlan,
|
||||
},
|
||||
OverlayRuntimeStarted {
|
||||
status: OverlayRuntimeStatus,
|
||||
},
|
||||
OverlayRuntimeStopped {
|
||||
name: String,
|
||||
stopped: bool,
|
||||
note: String,
|
||||
},
|
||||
OverlayPeers {
|
||||
name: String,
|
||||
peers: Vec<OverlayPeer>,
|
||||
note: String,
|
||||
},
|
||||
OverlayPacketSent {
|
||||
peer_node_id: String,
|
||||
peer_agent_id: String,
|
||||
endpoint_id: String,
|
||||
packet: Option<OverlayPacket>,
|
||||
allowed: bool,
|
||||
reason: String,
|
||||
note: String,
|
||||
},
|
||||
OverlayPackets {
|
||||
name: String,
|
||||
packets: Vec<OverlayPacket>,
|
||||
drained: bool,
|
||||
note: String,
|
||||
},
|
||||
CasAdded {
|
||||
hash: BlobHash,
|
||||
size_bytes: u64,
|
||||
|
|
@ -990,6 +1049,14 @@ pub struct CasProvider {
|
|||
pub last_seen_ms: i64,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct OverlayPeer {
|
||||
pub node_id: String,
|
||||
pub endpoint_id: Option<String>,
|
||||
pub virtual_ip: Option<String>,
|
||||
pub state: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(tag = "type", rename_all = "kebab-case")]
|
||||
pub enum PeerControlRequest {
|
||||
|
|
@ -1408,6 +1475,38 @@ pub enum PipeWireResponse {
|
|||
},
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[serde(tag = "type", rename_all = "kebab-case")]
|
||||
pub enum OverlayWireRequest {
|
||||
Packet {
|
||||
peer_card: PeerCard,
|
||||
network: String,
|
||||
packet_base64: String,
|
||||
nonce: String,
|
||||
bearer_proof: Option<BearerProof>,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[serde(tag = "type", rename_all = "kebab-case")]
|
||||
pub enum OverlayWireResponse {
|
||||
PacketAccepted {
|
||||
node_id: String,
|
||||
agent_id: String,
|
||||
endpoint_id: String,
|
||||
remote_endpoint_id: String,
|
||||
packet: Option<Box<OverlayPacket>>,
|
||||
allowed: bool,
|
||||
reason: String,
|
||||
evaluated_ops: usize,
|
||||
nonce: String,
|
||||
note: String,
|
||||
},
|
||||
Error {
|
||||
message: String,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct SyncWatermark {
|
||||
pub stream: String,
|
||||
|
|
@ -1518,6 +1617,28 @@ pub fn decode_pipe_wire_response(line: &str) -> Result<PipeWireResponse, Control
|
|||
serde_json::from_str(line).map_err(ControlError::from)
|
||||
}
|
||||
|
||||
pub fn encode_overlay_wire_request(request: &OverlayWireRequest) -> Result<String, ControlError> {
|
||||
let mut line = serde_json::to_string(request)?;
|
||||
line.push('\n');
|
||||
Ok(line)
|
||||
}
|
||||
|
||||
pub fn decode_overlay_wire_request(line: &str) -> Result<OverlayWireRequest, ControlError> {
|
||||
serde_json::from_str(line).map_err(ControlError::from)
|
||||
}
|
||||
|
||||
pub fn encode_overlay_wire_response(
|
||||
response: &OverlayWireResponse,
|
||||
) -> Result<String, ControlError> {
|
||||
let mut line = serde_json::to_string(response)?;
|
||||
line.push('\n');
|
||||
Ok(line)
|
||||
}
|
||||
|
||||
pub fn decode_overlay_wire_response(line: &str) -> Result<OverlayWireResponse, ControlError> {
|
||||
serde_json::from_str(line).map_err(ControlError::from)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
|
@ -1587,6 +1708,27 @@ mod tests {
|
|||
request
|
||||
);
|
||||
|
||||
let request = ControlRequest::OverlayUp {
|
||||
name: "home-lan".to_owned(),
|
||||
bearer_secret: Some("gbt_route".to_owned()),
|
||||
mtu: Some(1280),
|
||||
};
|
||||
assert_eq!(
|
||||
decode_request(&encode_request(&request).expect("encode")).expect("decode"),
|
||||
request
|
||||
);
|
||||
|
||||
let request = ControlRequest::OverlaySend {
|
||||
name: "home-lan".to_owned(),
|
||||
node: "node:peer".to_owned(),
|
||||
packet_base64: "RQAAFAAAQABAAQAAqBYAAawWAAI=".to_owned(),
|
||||
bearer_secret: Some("gbt_invite".to_owned()),
|
||||
};
|
||||
assert_eq!(
|
||||
decode_request(&encode_request(&request).expect("encode")).expect("decode"),
|
||||
request
|
||||
);
|
||||
|
||||
let response = ControlResponse::CasHas {
|
||||
hash: "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef".into(),
|
||||
present: true,
|
||||
|
|
@ -1605,6 +1747,69 @@ mod tests {
|
|||
response
|
||||
);
|
||||
|
||||
let response = ControlResponse::OverlayJoined {
|
||||
join: geth_overlay::OverlayJoinPlan {
|
||||
plan: geth_overlay::plan_overlay("home-lan", None, geth_overlay::OVERLAY_ALPN)
|
||||
.expect("overlay plan"),
|
||||
network: geth_overlay::membership_status(
|
||||
&geth_overlay::joined_overlay_membership(
|
||||
"home-lan",
|
||||
None,
|
||||
"node:local",
|
||||
"invite",
|
||||
10,
|
||||
)
|
||||
.expect("overlay membership"),
|
||||
),
|
||||
enabled: true,
|
||||
note: "membership persisted".to_owned(),
|
||||
},
|
||||
};
|
||||
assert_eq!(
|
||||
decode_response(&encode_response(&response).expect("encode")).expect("decode"),
|
||||
response
|
||||
);
|
||||
|
||||
let response = ControlResponse::OverlayRuntimeStarted {
|
||||
status: geth_overlay::OverlayRuntimeStatus {
|
||||
name: "home-lan".to_owned(),
|
||||
interface_name: "geth-homelan".to_owned(),
|
||||
virtual_ip: "172.22.0.10".to_owned(),
|
||||
cidr: "172.22.0.0/24".to_owned(),
|
||||
mtu: 1280,
|
||||
started_at_ms: 12,
|
||||
packets_from_tun: 1,
|
||||
packets_to_tun: 2,
|
||||
packets_to_peers: 3,
|
||||
last_error: None,
|
||||
note: "active".to_owned(),
|
||||
},
|
||||
};
|
||||
assert_eq!(
|
||||
decode_response(&encode_response(&response).expect("encode")).expect("decode"),
|
||||
response
|
||||
);
|
||||
|
||||
let response = ControlResponse::OverlayPackets {
|
||||
name: "home-lan".to_owned(),
|
||||
packets: vec![geth_overlay::OverlayPacket {
|
||||
id: "overlay-packet:test".to_owned(),
|
||||
network: "home-lan".to_owned(),
|
||||
source_node: "node:peer".to_owned(),
|
||||
destination_node: "node:local".to_owned(),
|
||||
packet_base64: "RQAAFAAAQABAAQAAqBYAAawWAAI=".to_owned(),
|
||||
size_bytes: 20,
|
||||
received_at_ms: 11,
|
||||
note: "received".to_owned(),
|
||||
}],
|
||||
drained: true,
|
||||
note: "packets".to_owned(),
|
||||
};
|
||||
assert_eq!(
|
||||
decode_response(&encode_response(&response).expect("encode")).expect("decode"),
|
||||
response
|
||||
);
|
||||
|
||||
let response = ControlResponse::NodeList {
|
||||
nodes: vec![NodeRecord {
|
||||
id: geth_types::NodeId::new("node:local"),
|
||||
|
|
@ -2641,6 +2846,63 @@ mod tests {
|
|||
response
|
||||
);
|
||||
|
||||
let request = OverlayWireRequest::Packet {
|
||||
peer_card: PeerCard {
|
||||
node_id: "node:caller".into(),
|
||||
agent_id: "agent:caller".into(),
|
||||
endpoints: Vec::new(),
|
||||
issued_at: geth_types::UnixMillis(1),
|
||||
signature: geth_discovery::SignatureMetadata {
|
||||
namespace: "geth.peer-card.v1@geth.local".to_owned(),
|
||||
signer: "agent:caller".to_owned(),
|
||||
public_key: "key".to_owned(),
|
||||
signature: "sig".to_owned(),
|
||||
},
|
||||
},
|
||||
network: "home".to_owned(),
|
||||
packet_base64: "RQAAFAAAQABAAQAAqBYAAawWAAI=".to_owned(),
|
||||
nonce: "nonce".to_owned(),
|
||||
bearer_proof: Some(BearerProof {
|
||||
secret: "bearer:test".into(),
|
||||
resource: "resource:overlay:home".into(),
|
||||
capabilities: vec!["overlay.route".into()],
|
||||
nonce: "nonce".to_owned(),
|
||||
response: "response".to_owned(),
|
||||
}),
|
||||
};
|
||||
assert_eq!(
|
||||
decode_overlay_wire_request(&encode_overlay_wire_request(&request).expect("encode"))
|
||||
.expect("decode"),
|
||||
request
|
||||
);
|
||||
|
||||
let response = OverlayWireResponse::PacketAccepted {
|
||||
node_id: "node:peer".to_owned(),
|
||||
agent_id: "agent:peer".to_owned(),
|
||||
endpoint_id: "endpoint:peer".to_owned(),
|
||||
remote_endpoint_id: "endpoint:caller".to_owned(),
|
||||
packet: Some(Box::new(geth_overlay::OverlayPacket {
|
||||
id: "overlay-packet:test".to_owned(),
|
||||
network: "home".to_owned(),
|
||||
source_node: "node:caller".to_owned(),
|
||||
destination_node: "node:peer".to_owned(),
|
||||
packet_base64: "RQAAFAAAQABAAQAAqBYAAawWAAI=".to_owned(),
|
||||
size_bytes: 20,
|
||||
received_at_ms: 12,
|
||||
note: "overlay".to_owned(),
|
||||
})),
|
||||
allowed: true,
|
||||
reason: "direct grant".to_owned(),
|
||||
evaluated_ops: 1,
|
||||
nonce: "nonce".to_owned(),
|
||||
note: "overlay wire".to_owned(),
|
||||
};
|
||||
assert_eq!(
|
||||
decode_overlay_wire_response(&encode_overlay_wire_response(&response).expect("encode"))
|
||||
.expect("decode"),
|
||||
response
|
||||
);
|
||||
|
||||
let request = PipeWireRequest::TcpConnect {
|
||||
peer_card: PeerCard {
|
||||
node_id: "node:caller".into(),
|
||||
|
|
|
|||
Loading…
Reference in a new issue