Client-side noise protocol
/ build (push) Successful in 4m32s
Details
/ build (push) Successful in 4m32s
Details
This commit is contained in:
parent
46f4071d4f
commit
92cc57d2cd
|
@ -38,6 +38,9 @@ pub fn start(t: &mut Activation, ds: Arc<Cap>) {
|
||||||
|
|
||||||
t.spawn(Some(AnyValue::symbol("sturdy_ref_step")),
|
t.spawn(Some(AnyValue::symbol("sturdy_ref_step")),
|
||||||
enclose!((ds) move |t| super::sturdy::handle_sturdy_path_steps(t, ds)));
|
enclose!((ds) move |t| super::sturdy::handle_sturdy_path_steps(t, ds)));
|
||||||
|
|
||||||
|
t.spawn(Some(AnyValue::symbol("noise_ref_step")),
|
||||||
|
enclose!((ds) move |t| super::noise::handle_noise_path_steps(t, ds)));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run(t: &mut Activation, ds: Arc<Cap>, route: G::Route) -> ActorResult {
|
fn run(t: &mut Activation, ds: Arc<Cap>, route: G::Route) -> ActorResult {
|
||||||
|
|
|
@ -13,17 +13,21 @@ use preserves_schema::Codec;
|
||||||
use syndicate::actor::*;
|
use syndicate::actor::*;
|
||||||
use syndicate::relay::Mutex;
|
use syndicate::relay::Mutex;
|
||||||
use syndicate::relay::TunnelRelay;
|
use syndicate::relay::TunnelRelay;
|
||||||
|
use syndicate::rpc;
|
||||||
use syndicate::trace::TurnCause;
|
use syndicate::trace::TurnCause;
|
||||||
use syndicate::value::NestedValue;
|
use syndicate::value::NestedValue;
|
||||||
use syndicate::value::NoEmbeddedDomainCodec;
|
use syndicate::value::NoEmbeddedDomainCodec;
|
||||||
use syndicate::value::PackedWriter;
|
use syndicate::value::PackedWriter;
|
||||||
|
|
||||||
|
use syndicate::enclose;
|
||||||
use syndicate_macros::during;
|
use syndicate_macros::during;
|
||||||
use syndicate_macros::pattern;
|
use syndicate_macros::pattern;
|
||||||
|
|
||||||
use syndicate::schemas::dataspace;
|
use syndicate::schemas::dataspace;
|
||||||
use syndicate::schemas::gatekeeper;
|
use syndicate::schemas::gatekeeper;
|
||||||
use syndicate::schemas::noise;
|
use syndicate::schemas::noise;
|
||||||
|
use syndicate::schemas::rpc as R;
|
||||||
|
use syndicate::schemas::sturdy;
|
||||||
|
|
||||||
use crate::language;
|
use crate::language;
|
||||||
|
|
||||||
|
@ -37,7 +41,7 @@ pub fn handle_noise_binds(t: &mut Activation, ds: &Arc<Cap>) -> ActorResult {
|
||||||
target.value().to_embedded()?;
|
target.value().to_embedded()?;
|
||||||
let observer = language().parse::<gatekeeper::BindObserver>(&observer)?;
|
let observer = language().parse::<gatekeeper::BindObserver>(&observer)?;
|
||||||
let spec = language().parse::<noise::NoiseDescriptionDetail<AnyValue>>(&desc)?.0;
|
let spec = language().parse::<noise::NoiseDescriptionDetail<AnyValue>>(&desc)?.0;
|
||||||
match validate_noise_spec(spec) {
|
match validate_noise_service_spec(spec) {
|
||||||
Ok(spec) => if let gatekeeper::BindObserver::Present(o) = observer {
|
Ok(spec) => if let gatekeeper::BindObserver::Present(o) = observer {
|
||||||
o.assert(t, language(), &gatekeeper::Bound::Bound {
|
o.assert(t, language(), &gatekeeper::Bound::Bound {
|
||||||
path_step: Box::new(gatekeeper::PathStep {
|
path_step: Box::new(gatekeeper::PathStep {
|
||||||
|
@ -108,9 +112,9 @@ fn default_noise_protocol() -> String {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn validate_noise_spec(
|
fn validate_noise_spec(
|
||||||
spec: noise::NoiseServiceSpec<AnyValue>,
|
spec: noise::NoiseSpec<AnyValue>,
|
||||||
) -> Result<ValidatedNoiseSpec, ActorError> {
|
) -> Result<ValidatedNoiseSpec, ActorError> {
|
||||||
let protocol = match spec.base.protocol {
|
let protocol = match spec.protocol {
|
||||||
noise::NoiseProtocol::Present { protocol } => protocol,
|
noise::NoiseProtocol::Present { protocol } => protocol,
|
||||||
noise::NoiseProtocol::Invalid { protocol } =>
|
noise::NoiseProtocol::Invalid { protocol } =>
|
||||||
Err(format!("Invalid noise protocol {:?}", protocol))?,
|
Err(format!("Invalid noise protocol {:?}", protocol))?,
|
||||||
|
@ -127,28 +131,35 @@ fn validate_noise_spec(
|
||||||
let pattern = lookup_pattern(pattern_name).ok_or_else::<ActorError, _>(
|
let pattern = lookup_pattern(pattern_name).ok_or_else::<ActorError, _>(
|
||||||
|| format!("Unsupported handshake pattern {:?}", pattern_name).into())?;
|
|| format!("Unsupported handshake pattern {:?}", pattern_name).into())?;
|
||||||
|
|
||||||
let psks = match spec.base.pre_shared_keys {
|
let psks = match spec.pre_shared_keys {
|
||||||
noise::NoisePreSharedKeys::Present { pre_shared_keys } => pre_shared_keys,
|
noise::NoisePreSharedKeys::Present { pre_shared_keys } => pre_shared_keys,
|
||||||
noise::NoisePreSharedKeys::Invalid { pre_shared_keys } =>
|
noise::NoisePreSharedKeys::Invalid { pre_shared_keys } =>
|
||||||
Err(format!("Invalid pre-shared-keys {:?}", pre_shared_keys))?,
|
Err(format!("Invalid pre-shared-keys {:?}", pre_shared_keys))?,
|
||||||
noise::NoisePreSharedKeys::Absent => vec![],
|
noise::NoisePreSharedKeys::Absent => vec![],
|
||||||
};
|
};
|
||||||
|
|
||||||
let secret_key = match spec.secret_key {
|
Ok(ValidatedNoiseSpec {
|
||||||
|
service: spec.service.0,
|
||||||
|
protocol,
|
||||||
|
pattern,
|
||||||
|
psks,
|
||||||
|
secret_key: None,
|
||||||
|
public_key: spec.key,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn validate_noise_service_spec(
|
||||||
|
spec: noise::NoiseServiceSpec<AnyValue>,
|
||||||
|
) -> Result<ValidatedNoiseSpec, ActorError> {
|
||||||
|
let noise::NoiseServiceSpec { base, secret_key } = spec;
|
||||||
|
let v = validate_noise_spec(base)?;
|
||||||
|
let secret_key = match secret_key {
|
||||||
noise::SecretKeyField::Present { secret_key } => Some(secret_key),
|
noise::SecretKeyField::Present { secret_key } => Some(secret_key),
|
||||||
noise::SecretKeyField::Invalid { secret_key } =>
|
noise::SecretKeyField::Invalid { secret_key } =>
|
||||||
Err(format!("Invalid secret key {:?}", secret_key))?,
|
Err(format!("Invalid secret key {:?}", secret_key))?,
|
||||||
noise::SecretKeyField::Absent => None,
|
noise::SecretKeyField::Absent => None,
|
||||||
};
|
};
|
||||||
|
Ok(ValidatedNoiseSpec { secret_key, .. v })
|
||||||
Ok(ValidatedNoiseSpec {
|
|
||||||
service: spec.base.service.0,
|
|
||||||
protocol,
|
|
||||||
pattern,
|
|
||||||
psks,
|
|
||||||
secret_key,
|
|
||||||
public_key: spec.base.key,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn await_bind_noise(
|
fn await_bind_noise(
|
||||||
|
@ -164,9 +175,14 @@ fn await_bind_noise(
|
||||||
let observer = Arc::clone(&observer);
|
let observer = Arc::clone(&observer);
|
||||||
t.spawn_link(None, move |t| {
|
t.spawn_link(None, move |t| {
|
||||||
let bindings = a.value().to_sequence()?;
|
let bindings = a.value().to_sequence()?;
|
||||||
let spec = validate_noise_spec(language().parse(&bindings[0])?)?;
|
let spec = validate_noise_service_spec(language().parse(&bindings[0])?)?;
|
||||||
let service = bindings[1].value().to_embedded()?;
|
let service = bindings[1].value().to_embedded()?.clone();
|
||||||
run_noise_responder(t, spec, observer, Arc::clone(service))
|
let hs = make_handshake(&spec, false)?;
|
||||||
|
let responder_session = Cap::guard(crate::Language::arc(), t.create(
|
||||||
|
ResponderState::Introduction{ service, hs }));
|
||||||
|
observer.assert(
|
||||||
|
t, language(), &gatekeeper::Resolved::Accepted { responder_session });
|
||||||
|
Ok(())
|
||||||
});
|
});
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
|
@ -181,23 +197,28 @@ fn await_bind_noise(
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
type HandshakeState = noise_protocol::HandshakeState<X25519, ChaCha20Poly1305, Blake2s>;
|
type NoiseHandshakeState = noise_protocol::HandshakeState<X25519, ChaCha20Poly1305, Blake2s>;
|
||||||
|
|
||||||
|
struct HandshakeState {
|
||||||
|
peer: Arc<Cap>,
|
||||||
|
hs: NoiseHandshakeState,
|
||||||
|
initial_ref: Option<Arc<Cap>>,
|
||||||
|
initial_oid: Option<sturdy::Oid>,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct TransportState {
|
||||||
|
relay_input: Arc<Mutex<Option<TunnelRelay>>>,
|
||||||
|
c_recv: CipherState<ChaCha20Poly1305>,
|
||||||
|
}
|
||||||
|
|
||||||
enum ResponderState {
|
enum ResponderState {
|
||||||
Invalid, // used during state transitions
|
Invalid, // used during state transitions
|
||||||
Introduction {
|
Introduction {
|
||||||
service: Arc<Cap>,
|
service: Arc<Cap>,
|
||||||
hs: HandshakeState,
|
hs: NoiseHandshakeState,
|
||||||
},
|
|
||||||
Handshake {
|
|
||||||
initiator_session: Arc<Cap>,
|
|
||||||
service: Arc<Cap>,
|
|
||||||
hs: HandshakeState,
|
|
||||||
},
|
|
||||||
Transport {
|
|
||||||
relay_input: Arc<Mutex<Option<TunnelRelay>>>,
|
|
||||||
c_recv: CipherState<ChaCha20Poly1305>,
|
|
||||||
},
|
},
|
||||||
|
Handshake(HandshakeState),
|
||||||
|
Transport(TransportState),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Entity<noise::SessionItem> for ResponderState {
|
impl Entity<noise::SessionItem> for ResponderState {
|
||||||
|
@ -208,7 +229,12 @@ impl Entity<noise::SessionItem> for ResponderState {
|
||||||
};
|
};
|
||||||
match std::mem::replace(self, ResponderState::Invalid) {
|
match std::mem::replace(self, ResponderState::Invalid) {
|
||||||
ResponderState::Introduction { service, hs } => {
|
ResponderState::Introduction { service, hs } => {
|
||||||
*self = ResponderState::Handshake { initiator_session, service, hs };
|
*self = ResponderState::Handshake(HandshakeState {
|
||||||
|
peer: initiator_session,
|
||||||
|
hs,
|
||||||
|
initial_ref: Some(service.clone()),
|
||||||
|
initial_oid: None,
|
||||||
|
});
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
_ =>
|
_ =>
|
||||||
|
@ -224,24 +250,70 @@ impl Entity<noise::SessionItem> for ResponderState {
|
||||||
match self {
|
match self {
|
||||||
ResponderState::Invalid | ResponderState::Introduction { .. } =>
|
ResponderState::Invalid | ResponderState::Introduction { .. } =>
|
||||||
Err("Received Packet in invalid ResponderState")?,
|
Err("Received Packet in invalid ResponderState")?,
|
||||||
ResponderState::Handshake { initiator_session, service, hs } => match p {
|
ResponderState::Handshake(hss) => {
|
||||||
|
if let Some((None, ts)) = hss.handle_packet(t, p)? {
|
||||||
|
*self = ResponderState::Transport(ts);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ResponderState::Transport(ts) => ts.handle_packet(t, p)?,
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl HandshakeState {
|
||||||
|
fn handle_packet(
|
||||||
|
&mut self,
|
||||||
|
t: &mut Activation,
|
||||||
|
p: noise::Packet,
|
||||||
|
) -> Result<Option<(Option<Arc<Cap>>, TransportState)>, ActorError> {
|
||||||
|
match p {
|
||||||
noise::Packet::Complete(bs) => {
|
noise::Packet::Complete(bs) => {
|
||||||
if bs.len() < hs.get_next_message_overhead() {
|
if bs.len() < self.hs.get_next_message_overhead() {
|
||||||
Err("Invalid handshake message for pattern")?;
|
Err("Invalid handshake message for pattern")?;
|
||||||
}
|
}
|
||||||
if bs.len() > hs.get_next_message_overhead() {
|
if bs.len() > self.hs.get_next_message_overhead() {
|
||||||
Err("Cannot accept payload during handshake")?;
|
Err("Cannot accept payload during handshake")?;
|
||||||
}
|
}
|
||||||
hs.read_message(&bs, &mut [])?;
|
self.hs.read_message(&bs, &mut [])?;
|
||||||
let mut reply = vec![0u8; hs.get_next_message_overhead()];
|
if self.hs.completed() {
|
||||||
hs.write_message(&[], &mut reply[..])?;
|
self.complete_handshake(t)
|
||||||
initiator_session.message(t, language(), &noise::Packet::Complete(reply.into()));
|
} else {
|
||||||
if hs.completed() {
|
self.send_handshake_packet(t)
|
||||||
let (c_recv, mut c_send) = hs.get_ciphers();
|
}
|
||||||
let (_, relay_input, mut relay_output) =
|
}
|
||||||
TunnelRelay::_run(t, Some(Arc::clone(service)), None, false);
|
_ => Err("Fragmented handshake is not allowed")?,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn send_handshake_packet(
|
||||||
|
&mut self,
|
||||||
|
t: &mut Activation,
|
||||||
|
) -> Result<Option<(Option<Arc<Cap>>, TransportState)>, ActorError> {
|
||||||
|
let mut reply = vec![0u8; self.hs.get_next_message_overhead()];
|
||||||
|
self.hs.write_message(&[], &mut reply[..])?;
|
||||||
|
self.peer.message(t, language(), &noise::Packet::Complete(reply.into()));
|
||||||
|
if self.hs.completed() {
|
||||||
|
self.complete_handshake(t)
|
||||||
|
} else {
|
||||||
|
Ok(None)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn complete_handshake(
|
||||||
|
&mut self,
|
||||||
|
t: &mut Activation,
|
||||||
|
) -> Result<Option<(Option<Arc<Cap>>, TransportState)>, ActorError> {
|
||||||
|
let (c_i_to_r, c_r_to_i) = self.hs.get_ciphers();
|
||||||
|
let (c_recv, mut c_send) = if self.hs.get_is_initiator() {
|
||||||
|
(c_r_to_i, c_i_to_r)
|
||||||
|
} else {
|
||||||
|
(c_i_to_r, c_r_to_i)
|
||||||
|
};
|
||||||
|
let (peer_service, relay_input, mut relay_output) =
|
||||||
|
TunnelRelay::_run(t, self.initial_ref.clone(), self.initial_oid.clone(), false);
|
||||||
let trace_collector = t.trace_collector();
|
let trace_collector = t.trace_collector();
|
||||||
let initiator_session = Arc::clone(initiator_session);
|
let peer = self.peer.clone();
|
||||||
let relay_output_name = Some(AnyValue::symbol("relay_output"));
|
let relay_output_name = Some(AnyValue::symbol("relay_output"));
|
||||||
let transport_facet = t.facet_ref();
|
let transport_facet = t.facet_ref();
|
||||||
t.linked_task(relay_output_name.clone(), async move {
|
t.linked_task(relay_output_name.clone(), async move {
|
||||||
|
@ -262,7 +334,7 @@ impl Entity<noise::SessionItem> for ResponderState {
|
||||||
noise::Packet::Complete(c_send.encrypt_vec(&loaned_item.item))
|
noise::Packet::Complete(c_send.encrypt_vec(&loaned_item.item))
|
||||||
};
|
};
|
||||||
if !transport_facet.activate(&account, Some(cause.clone()), |t| {
|
if !transport_facet.activate(&account, Some(cause.clone()), |t| {
|
||||||
initiator_session.message(t, language(), &p);
|
peer.message(t, language(), &p);
|
||||||
Ok(())
|
Ok(())
|
||||||
}) {
|
}) {
|
||||||
break;
|
break;
|
||||||
|
@ -272,29 +344,31 @@ impl Entity<noise::SessionItem> for ResponderState {
|
||||||
}
|
}
|
||||||
Ok(LinkedTaskTermination::Normal)
|
Ok(LinkedTaskTermination::Normal)
|
||||||
});
|
});
|
||||||
*self = ResponderState::Transport { relay_input, c_recv };
|
Ok(Some((peer_service, TransportState { relay_input, c_recv })))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => Err("Fragmented handshake is not allowed")?,
|
|
||||||
},
|
impl TransportState {
|
||||||
ResponderState::Transport { relay_input, c_recv } => {
|
fn handle_packet(
|
||||||
|
&mut self,
|
||||||
|
t: &mut Activation,
|
||||||
|
p: noise::Packet,
|
||||||
|
) -> ActorResult {
|
||||||
let bs = match p {
|
let bs = match p {
|
||||||
noise::Packet::Complete(bs) =>
|
noise::Packet::Complete(bs) =>
|
||||||
c_recv.decrypt_vec(&bs[..]).map_err(|_| "Cannot decrypt packet")?,
|
self.c_recv.decrypt_vec(&bs[..]).map_err(|_| "Cannot decrypt packet")?,
|
||||||
noise::Packet::Fragmented(pieces) => {
|
noise::Packet::Fragmented(pieces) => {
|
||||||
let mut result = Vec::with_capacity(1024);
|
let mut result = Vec::with_capacity(1024);
|
||||||
for piece in pieces {
|
for piece in pieces {
|
||||||
result.extend(c_recv.decrypt_vec(&piece[..])
|
result.extend(self.c_recv.decrypt_vec(&piece[..])
|
||||||
.map_err(|_| "Cannot decrypt packet fragment")?);
|
.map_err(|_| "Cannot decrypt packet fragment")?);
|
||||||
}
|
}
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let mut g = relay_input.lock();
|
let mut g = self.relay_input.lock();
|
||||||
let tr = g.as_mut().expect("initialized");
|
let tr = g.as_mut().expect("initialized");
|
||||||
tr.handle_inbound_datagram(t, &bs[..])?;
|
tr.handle_inbound_datagram(t, &bs[..])?;
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -355,34 +429,133 @@ fn lookup_pattern(name: &str) -> Option<HandshakePattern> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_noise_responder(
|
fn make_handshake(
|
||||||
t: &mut Activation,
|
spec: &ValidatedNoiseSpec,
|
||||||
spec: ValidatedNoiseSpec,
|
is_initiator: bool,
|
||||||
observer: Arc<Cap>,
|
) -> Result<NoiseHandshakeState, ActorError> {
|
||||||
service: Arc<Cap>,
|
|
||||||
) -> ActorResult {
|
|
||||||
let hs = {
|
|
||||||
let mut builder = noise_protocol::HandshakeStateBuilder::new();
|
let mut builder = noise_protocol::HandshakeStateBuilder::new();
|
||||||
builder.set_pattern(spec.pattern);
|
builder.set_pattern(spec.pattern.clone());
|
||||||
builder.set_is_initiator(false);
|
builder.set_is_initiator(is_initiator);
|
||||||
let prologue = PackedWriter::encode(&mut NoEmbeddedDomainCodec, &spec.service)?;
|
let prologue = PackedWriter::encode(&mut NoEmbeddedDomainCodec, &spec.service)?;
|
||||||
builder.set_prologue(&prologue);
|
builder.set_prologue(&prologue);
|
||||||
match spec.secret_key {
|
match spec.secret_key.clone() {
|
||||||
None => (),
|
None => (),
|
||||||
Some(sk) => {
|
Some(sk) => {
|
||||||
let sk: [u8; 32] = sk.try_into().map_err(|_| "Bad secret key length")?;
|
let sk: [u8; 32] = sk.try_into().map_err(|_| "Bad secret key length")?;
|
||||||
builder.set_s(U8Array::from_slice(&sk));
|
builder.set_s(U8Array::from_slice(&sk));
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
builder.set_rs(U8Array::from_slice(&spec.public_key));
|
||||||
let mut hs = builder.build_handshake_state();
|
let mut hs = builder.build_handshake_state();
|
||||||
for psk in spec.psks.into_iter() {
|
for psk in spec.psks.iter() {
|
||||||
hs.push_psk(&psk);
|
hs.push_psk(psk);
|
||||||
|
}
|
||||||
|
Ok(hs)
|
||||||
}
|
}
|
||||||
hs
|
|
||||||
};
|
|
||||||
|
|
||||||
let responder_session =
|
pub fn handle_noise_path_steps(t: &mut Activation, ds: Arc<Cap>) -> ActorResult {
|
||||||
Cap::guard(crate::Language::arc(), t.create(ResponderState::Introduction{ service, hs }));
|
during!(t, ds, language(),
|
||||||
observer.assert(t, language(), &gatekeeper::Resolved::Accepted { responder_session });
|
<q <resolve-path-step $origin <noise $spec0>>>,
|
||||||
|
enclose!((ds) move |t: &mut Activation| {
|
||||||
|
if let Ok(spec) = language().parse::<noise::NoiseSpec>(&spec0) {
|
||||||
|
if let Some(origin) = origin.value().as_embedded().cloned() {
|
||||||
|
t.spawn_link(None, move |t| run_noise_initiator(t, ds, origin, spec));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}));
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn run_noise_initiator(
|
||||||
|
t: &mut Activation,
|
||||||
|
ds: Arc<Cap>,
|
||||||
|
origin: Arc<Cap>,
|
||||||
|
spec: noise::NoiseSpec,
|
||||||
|
) -> ActorResult {
|
||||||
|
let q = language().unparse(&gatekeeper::ResolvePathStep {
|
||||||
|
origin: origin.clone(),
|
||||||
|
path_step: gatekeeper::PathStep {
|
||||||
|
step_type: "noise".to_string(),
|
||||||
|
detail: language().unparse(&spec),
|
||||||
|
}
|
||||||
|
});
|
||||||
|
let service = spec.service.clone();
|
||||||
|
let validated = validate_noise_spec(spec)?;
|
||||||
|
let observer = Cap::guard(&language().syndicate, t.create(
|
||||||
|
syndicate::entity(()).on_asserted_facet(
|
||||||
|
enclose!((ds, q) move |_, t, r: gatekeeper::Resolved| {
|
||||||
|
match r {
|
||||||
|
gatekeeper::Resolved::Rejected(b) => {
|
||||||
|
ds.assert(t, language(), &rpc::answer(
|
||||||
|
language(), q.clone(), R::Result::Error {
|
||||||
|
error: b.detail }));
|
||||||
|
}
|
||||||
|
gatekeeper::Resolved::Accepted { responder_session } =>
|
||||||
|
run_initiator_session(
|
||||||
|
t, ds.clone(), q.clone(), &validated, responder_session)?,
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}))));
|
||||||
|
origin.assert(t, language(), &gatekeeper::Resolve {
|
||||||
|
step: gatekeeper::Step {
|
||||||
|
step_type: "noise".to_string(),
|
||||||
|
detail: language().unparse(&service),
|
||||||
|
},
|
||||||
|
observer,
|
||||||
|
});
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn run_initiator_session(
|
||||||
|
t: &mut Activation,
|
||||||
|
ds: Arc<Cap>,
|
||||||
|
question: AnyValue,
|
||||||
|
spec: &ValidatedNoiseSpec,
|
||||||
|
responder_session: Arc<Cap>,
|
||||||
|
) -> ActorResult {
|
||||||
|
let initiator_session_ref = t.create_inert();
|
||||||
|
let initiator_session = Cap::guard(crate::Language::arc(), initiator_session_ref.clone());
|
||||||
|
responder_session.assert(t, language(), &noise::Initiator { initiator_session });
|
||||||
|
let mut hss = HandshakeState {
|
||||||
|
peer: responder_session.clone(),
|
||||||
|
hs: make_handshake(spec, true)?,
|
||||||
|
initial_ref: None,
|
||||||
|
initial_oid: Some(sturdy::Oid(0.into())),
|
||||||
|
};
|
||||||
|
if !hss.hs.completed() {
|
||||||
|
if hss.send_handshake_packet(t)?.is_some() {
|
||||||
|
// TODO: this might be a valid pattern, check
|
||||||
|
panic!("Unexpected complete handshake after no messages");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
initiator_session_ref.become_entity(InitiatorState::Handshake { ds, question, hss });
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
enum InitiatorState {
|
||||||
|
Handshake {
|
||||||
|
ds: Arc<Cap>,
|
||||||
|
question: AnyValue,
|
||||||
|
hss: HandshakeState,
|
||||||
|
},
|
||||||
|
Transport(TransportState),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Entity<noise::Packet> for InitiatorState {
|
||||||
|
fn message(&mut self, t: &mut Activation, p: noise::Packet) -> ActorResult {
|
||||||
|
match self {
|
||||||
|
InitiatorState::Handshake { hss, ds, question } => {
|
||||||
|
if let Some((Some(peer_service), ts)) = hss.handle_packet(t, p)? {
|
||||||
|
let ds = ds.clone();
|
||||||
|
let question = question.clone();
|
||||||
|
*self = InitiatorState::Transport(ts);
|
||||||
|
ds.assert(t, language(), &rpc::answer(language(), question, R::Result::Ok {
|
||||||
|
value: AnyValue::domain(peer_service) }));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
InitiatorState::Transport(ts) => ts.handle_packet(t, p)?,
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -3,7 +3,6 @@ use std::sync::Arc;
|
||||||
use preserves_schema::Codec;
|
use preserves_schema::Codec;
|
||||||
|
|
||||||
use syndicate::actor::*;
|
use syndicate::actor::*;
|
||||||
use syndicate::during;
|
|
||||||
use syndicate::rpc;
|
use syndicate::rpc;
|
||||||
use syndicate::value::NestedValue;
|
use syndicate::value::NestedValue;
|
||||||
|
|
||||||
|
@ -107,7 +106,7 @@ pub fn handle_sturdy_path_steps(t: &mut Activation, ds: Arc<Cap>) -> ActorResult
|
||||||
enclose!((ds) move |t: &mut Activation| {
|
enclose!((ds) move |t: &mut Activation| {
|
||||||
if let Some(origin) = origin.value().as_embedded().cloned() {
|
if let Some(origin) = origin.value().as_embedded().cloned() {
|
||||||
let observer = Cap::guard(&language().syndicate, t.create(
|
let observer = Cap::guard(&language().syndicate, t.create(
|
||||||
during::entity(()).on_asserted_facet(
|
syndicate::entity(()).on_asserted_facet(
|
||||||
enclose!((origin, parameters) move |_, t, r: gatekeeper::Resolved| {
|
enclose!((origin, parameters) move |_, t, r: gatekeeper::Resolved| {
|
||||||
ds.assert(t, language(), &rpc::answer(
|
ds.assert(t, language(), &rpc::answer(
|
||||||
language(),
|
language(),
|
||||||
|
|
Loading…
Reference in New Issue