It actually takes connections again now! Still WIP
This commit is contained in:
parent
ede0e29370
commit
7fb20c11af
|
@ -878,7 +878,6 @@ checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857"
|
||||||
name = "preserves"
|
name = "preserves"
|
||||||
version = "0.15.0"
|
version = "0.15.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"lazy_static",
|
|
||||||
"num",
|
"num",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_bytes",
|
"serde_bytes",
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
use preserves_schema::compiler::*;
|
||||||
|
|
||||||
|
use std::io::Error;
|
||||||
|
|
||||||
|
fn main() -> Result<(), Error> {
|
||||||
|
let buildroot = std::env::current_dir()?;
|
||||||
|
|
||||||
|
let mut gen_dir = buildroot.clone();
|
||||||
|
gen_dir.push("src/schemas");
|
||||||
|
|
||||||
|
let mut c = CompilerConfig::new(gen_dir, "crate::schemas".to_owned());
|
||||||
|
c.module_aliases.insert(vec!["EntityRef".to_owned()], "crate::actor".to_owned());
|
||||||
|
|
||||||
|
let inputs = expand_inputs(&vec!["protocols/schema-bundle.bin".to_owned(),
|
||||||
|
"local-protocols/schema-bundle.bin".to_owned()])?;
|
||||||
|
for i in &inputs {
|
||||||
|
println!("cargo:rerun-if-changed={:?}", i);
|
||||||
|
}
|
||||||
|
c.load_schemas_and_bundles(&inputs)?;
|
||||||
|
compile(&c)
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
all: schema-bundle.bin
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f schema-bundle.bin
|
||||||
|
|
||||||
|
schema-bundle.bin: schemas/*.prs
|
||||||
|
preserves-schemac schemas/*.prs > $@.tmp
|
||||||
|
mv $@.tmp $@
|
|
@ -0,0 +1,3 @@
|
||||||
|
´³bundle·µ³tunnelRelay„´³schema·³version‘³definitions·³Input´³orµµ±eof´³lit³eof„„µ±packet´³rec´³lit³packet„´³tupleµ´³named³bs´³atom³
|
||||||
|
ByteString„„„„„„µ±segment´³rec´³lit³segment„´³tupleµ´³named³bs´³atom³
|
||||||
|
ByteString„„„„„„„„„³embeddedType´³refµ³ EntityRef„³Ref„„„„„
|
|
@ -0,0 +1,4 @@
|
||||||
|
version 1 .
|
||||||
|
embeddedType EntityRef.Ref .
|
||||||
|
|
||||||
|
Input = =eof / <packet @bs bytes> / <segment @bs bytes>.
|
283
src/actor.rs
283
src/actor.rs
|
@ -1,3 +1,7 @@
|
||||||
|
pub use futures::future::BoxFuture;
|
||||||
|
|
||||||
|
pub use std::future::ready;
|
||||||
|
|
||||||
use super::Assertion;
|
use super::Assertion;
|
||||||
use super::ActorId;
|
use super::ActorId;
|
||||||
use super::Handle;
|
use super::Handle;
|
||||||
|
@ -5,16 +9,12 @@ use super::schemas::internal_protocol::*;
|
||||||
use super::error::Error;
|
use super::error::Error;
|
||||||
|
|
||||||
use preserves::value::Domain;
|
use preserves::value::Domain;
|
||||||
use preserves::value::IOResult;
|
|
||||||
use preserves::value::IOValue;
|
use preserves::value::IOValue;
|
||||||
use preserves::value::Map;
|
use preserves::value::Map;
|
||||||
use preserves::value::NestedValue;
|
use preserves::value::NestedValue;
|
||||||
|
|
||||||
use std::boxed::Box;
|
use std::boxed::Box;
|
||||||
use std::cell::Cell;
|
|
||||||
use std::collections::hash_map::HashMap;
|
use std::collections::hash_map::HashMap;
|
||||||
use std::future::Future;
|
|
||||||
use std::future::ready;
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||||
|
|
||||||
|
@ -27,7 +27,7 @@ use tracing::{Instrument, trace, error};
|
||||||
pub type ActorResult = Result<(), Error>;
|
pub type ActorResult = Result<(), Error>;
|
||||||
pub type ActorHandle = tokio::task::JoinHandle<ActorResult>;
|
pub type ActorHandle = tokio::task::JoinHandle<ActorResult>;
|
||||||
|
|
||||||
pub trait Entity {
|
pub trait Entity: Send {
|
||||||
fn assert(&mut self, _t: &mut Activation, _a: Assertion, _h: Handle) -> ActorResult {
|
fn assert(&mut self, _t: &mut Activation, _a: Assertion, _h: Handle) -> ActorResult {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -41,6 +41,12 @@ pub trait Entity {
|
||||||
t.message(peer, Assertion::new(true));
|
t.message(peer, Assertion::new(true));
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
fn turn_end(&mut self, _t: &mut Activation) -> ActorResult {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
fn exit_hook(&mut self, _t: &mut Activation, _exit_status: &ActorResult) -> BoxFuture<ActorResult> {
|
||||||
|
Box::pin(ready(Ok(())))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type OutboundAssertions = Map<Handle, Arc<Ref>>;
|
type OutboundAssertions = Map<Handle, Arc<Ref>>;
|
||||||
|
@ -48,10 +54,12 @@ type OutboundAssertions = Map<Handle, Arc<Ref>>;
|
||||||
// This is what other implementations call a "Turn", renamed here to
|
// This is what other implementations call a "Turn", renamed here to
|
||||||
// avoid conflicts with schemas::internal_protocol::Turn.
|
// avoid conflicts with schemas::internal_protocol::Turn.
|
||||||
pub struct Activation<'activation> {
|
pub struct Activation<'activation> {
|
||||||
outbound_assertions: &'activation mut OutboundAssertions,
|
pub actor: &'activation mut Actor,
|
||||||
queues: HashMap<ActorId, Vec<(Arc<Ref>, Event)>>,
|
queues: HashMap<ActorId, Vec<(Arc<Ref>, Event)>>,
|
||||||
|
turn_end_revisit_flag: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
enum SystemMessage {
|
enum SystemMessage {
|
||||||
Release,
|
Release,
|
||||||
ReleaseOid(Oid),
|
ReleaseOid(Oid),
|
||||||
|
@ -63,17 +71,21 @@ pub struct Mailbox {
|
||||||
pub actor_id: ActorId,
|
pub actor_id: ActorId,
|
||||||
pub mailbox_id: u64,
|
pub mailbox_id: u64,
|
||||||
tx: UnboundedSender<SystemMessage>,
|
tx: UnboundedSender<SystemMessage>,
|
||||||
pub queue_depth: Arc<AtomicUsize>,
|
queue_depth: Arc<AtomicUsize>,
|
||||||
pub mailbox_count: Arc<AtomicUsize>,
|
mailbox_count: Arc<AtomicUsize>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Actor {
|
pub struct Actor {
|
||||||
pub template_mailbox: Mailbox,
|
actor_id: ActorId,
|
||||||
|
tx: UnboundedSender<SystemMessage>,
|
||||||
rx: UnboundedReceiver<SystemMessage>,
|
rx: UnboundedReceiver<SystemMessage>,
|
||||||
pub outbound_assertions: OutboundAssertions,
|
queue_depth: Arc<AtomicUsize>,
|
||||||
pub oid_map: Map<Oid, Cell<Box<dyn Entity + Send>>>,
|
mailbox_count: Arc<AtomicUsize>,
|
||||||
pub next_task_id: u64,
|
outbound_assertions: OutboundAssertions,
|
||||||
pub linked_tasks: Map<u64, CancellationToken>,
|
oid_map: Map<Oid, Box<dyn Entity + Send>>,
|
||||||
|
next_task_id: u64,
|
||||||
|
linked_tasks: Map<u64, CancellationToken>,
|
||||||
|
exit_hooks: Vec<Oid>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
|
#[derive(Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
|
||||||
|
@ -87,13 +99,10 @@ pub struct Ref {
|
||||||
|
|
||||||
impl<'activation> Activation<'activation> {
|
impl<'activation> Activation<'activation> {
|
||||||
pub fn for_actor(actor: &'activation mut Actor) -> Self {
|
pub fn for_actor(actor: &'activation mut Actor) -> Self {
|
||||||
Self::for_actor_details(&mut actor.outbound_assertions)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn for_actor_details(outbound_assertions: &'activation mut OutboundAssertions) -> Self {
|
|
||||||
Activation {
|
Activation {
|
||||||
outbound_assertions,
|
actor,
|
||||||
queues: HashMap::new(),
|
queues: HashMap::new(),
|
||||||
|
turn_end_revisit_flag: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -101,12 +110,12 @@ impl<'activation> Activation<'activation> {
|
||||||
let handle = crate::next_handle();
|
let handle = crate::next_handle();
|
||||||
self.queue_for(&r).push((Arc::clone(&r), Event::Assert(Box::new(
|
self.queue_for(&r).push((Arc::clone(&r), Event::Assert(Box::new(
|
||||||
Assert { assertion: Assertion(a.into()), handle: handle.clone() }))));
|
Assert { assertion: Assertion(a.into()), handle: handle.clone() }))));
|
||||||
self.outbound_assertions.insert(handle.clone(), r);
|
self.actor.outbound_assertions.insert(handle.clone(), r);
|
||||||
handle
|
handle
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn retract(&mut self, handle: Handle) {
|
pub fn retract(&mut self, handle: Handle) {
|
||||||
if let Some(r) = self.outbound_assertions.remove(&handle) {
|
if let Some(r) = self.actor.outbound_assertions.remove(&handle) {
|
||||||
self.retract_known_ref(r, handle)
|
self.retract_known_ref(r, handle)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -120,11 +129,15 @@ impl<'activation> Activation<'activation> {
|
||||||
Message { body: Assertion(m.into()) }))))
|
Message { body: Assertion(m.into()) }))))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_turn_end_flag(&mut self) {
|
||||||
|
self.turn_end_revisit_flag = true;
|
||||||
|
}
|
||||||
|
|
||||||
fn queue_for(&mut self, r: &Arc<Ref>) -> &mut Vec<(Arc<Ref>, Event)> {
|
fn queue_for(&mut self, r: &Arc<Ref>) -> &mut Vec<(Arc<Ref>, Event)> {
|
||||||
self.queues.entry(r.relay.actor_id).or_default()
|
self.queues.entry(r.relay.actor_id).or_default()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn deliver(&mut self) {
|
fn deliver(&mut self) {
|
||||||
for (_actor_id, turn) in std::mem::take(&mut self.queues).into_iter() {
|
for (_actor_id, turn) in std::mem::take(&mut self.queues).into_iter() {
|
||||||
if turn.len() == 0 { continue; }
|
if turn.len() == 0 { continue; }
|
||||||
let first_ref = Arc::clone(&turn[0].0);
|
let first_ref = Arc::clone(&turn[0].0);
|
||||||
|
@ -133,6 +146,24 @@ impl<'activation> Activation<'activation> {
|
||||||
|(r, e)| TurnEvent { oid: r.target.clone(), event: e }).collect()));
|
|(r, e)| TurnEvent { oid: r.target.clone(), event: e }).collect()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn with_oid<R,
|
||||||
|
Ff: FnOnce(&mut Self) -> R,
|
||||||
|
Fs: FnOnce(&mut Self, &mut Box<dyn Entity + Send>) -> R>(
|
||||||
|
&mut self,
|
||||||
|
oid: &Oid,
|
||||||
|
kf: Ff,
|
||||||
|
ks: Fs,
|
||||||
|
) -> R {
|
||||||
|
match self.actor.oid_map.remove_entry(&oid) {
|
||||||
|
None => kf(self),
|
||||||
|
Some((k, mut e)) => {
|
||||||
|
let result = ks(self, &mut e);
|
||||||
|
self.actor.oid_map.insert(k, e);
|
||||||
|
result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'activation> Drop for Activation<'activation> {
|
impl<'activation> Drop for Activation<'activation> {
|
||||||
|
@ -182,20 +213,28 @@ impl PartialOrd for Mailbox {
|
||||||
impl Clone for Mailbox {
|
impl Clone for Mailbox {
|
||||||
fn clone(&self) -> Self {
|
fn clone(&self) -> Self {
|
||||||
let Mailbox { actor_id, tx, queue_depth, mailbox_count, .. } = self;
|
let Mailbox { actor_id, tx, queue_depth, mailbox_count, .. } = self;
|
||||||
mailbox_count.fetch_add(1, Ordering::SeqCst);
|
let _old_refcount = mailbox_count.fetch_add(1, Ordering::SeqCst);
|
||||||
Mailbox {
|
let new_mailbox = Mailbox {
|
||||||
actor_id: *actor_id,
|
actor_id: *actor_id,
|
||||||
mailbox_id: crate::next_mailbox_id(),
|
mailbox_id: crate::next_mailbox_id(),
|
||||||
tx: tx.clone(),
|
tx: tx.clone(),
|
||||||
queue_depth: Arc::clone(queue_depth),
|
queue_depth: Arc::clone(queue_depth),
|
||||||
mailbox_count: Arc::clone(mailbox_count),
|
mailbox_count: Arc::clone(mailbox_count),
|
||||||
}
|
};
|
||||||
|
trace!(old_mailbox = debug(&self),
|
||||||
|
new_mailbox = debug(&new_mailbox),
|
||||||
|
new_mailbox_refcount = debug(_old_refcount + 1));
|
||||||
|
new_mailbox
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for Mailbox {
|
impl Drop for Mailbox {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
if self.mailbox_count.fetch_sub(1, Ordering::SeqCst) == 1 {
|
let old_mailbox_refcount = self.mailbox_count.fetch_sub(1, Ordering::SeqCst);
|
||||||
|
let new_mailbox_refcount = old_mailbox_refcount - 1;
|
||||||
|
trace!(mailbox = debug(&self),
|
||||||
|
new_mailbox_refcount);
|
||||||
|
if new_mailbox_refcount == 0 {
|
||||||
let _ = self.tx.send(SystemMessage::Release);
|
let _ = self.tx.send(SystemMessage::Release);
|
||||||
()
|
()
|
||||||
}
|
}
|
||||||
|
@ -205,58 +244,99 @@ impl Drop for Mailbox {
|
||||||
impl Actor {
|
impl Actor {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
let (tx, rx) = unbounded_channel();
|
let (tx, rx) = unbounded_channel();
|
||||||
|
let actor_id = crate::next_actor_id();
|
||||||
|
trace!(id = actor_id, "Actor::new");
|
||||||
Actor {
|
Actor {
|
||||||
template_mailbox: Mailbox {
|
actor_id,
|
||||||
actor_id: crate::next_actor_id(),
|
tx,
|
||||||
mailbox_id: crate::next_mailbox_id(),
|
|
||||||
tx,
|
|
||||||
queue_depth: Arc::new(AtomicUsize::new(0)),
|
|
||||||
mailbox_count: Arc::new(AtomicUsize::new(0)),
|
|
||||||
},
|
|
||||||
rx,
|
rx,
|
||||||
|
queue_depth: Arc::new(AtomicUsize::new(0)),
|
||||||
|
mailbox_count: Arc::new(AtomicUsize::new(0)),
|
||||||
outbound_assertions: Map::new(),
|
outbound_assertions: Map::new(),
|
||||||
oid_map: Map::new(),
|
oid_map: Map::new(),
|
||||||
next_task_id: 0,
|
next_task_id: 0,
|
||||||
linked_tasks: Map::new(),
|
linked_tasks: Map::new(),
|
||||||
|
exit_hooks: Vec::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn id(&self) -> ActorId {
|
pub fn id(&self) -> ActorId {
|
||||||
self.template_mailbox.actor_id
|
self.actor_id
|
||||||
|
}
|
||||||
|
|
||||||
|
fn mailbox(&mut self) -> Mailbox {
|
||||||
|
let _old_refcount = self.mailbox_count.fetch_add(1, Ordering::SeqCst);
|
||||||
|
let new_mailbox = Mailbox {
|
||||||
|
actor_id: self.actor_id,
|
||||||
|
mailbox_id: crate::next_mailbox_id(),
|
||||||
|
tx: self.tx.clone(),
|
||||||
|
queue_depth: Arc::clone(&self.queue_depth),
|
||||||
|
mailbox_count: Arc::clone(&self.mailbox_count),
|
||||||
|
};
|
||||||
|
trace!(new_mailbox = debug(&new_mailbox),
|
||||||
|
new_mailbox_refcount = debug(_old_refcount + 1));
|
||||||
|
new_mailbox
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn shutdown(&mut self) {
|
||||||
|
let _ = self.tx.send(SystemMessage::Release);
|
||||||
|
()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create<E: Entity + Send + 'static>(&mut self, e: E) -> Arc<Ref> {
|
pub fn create<E: Entity + Send + 'static>(&mut self, e: E) -> Arc<Ref> {
|
||||||
let r = Ref {
|
let r = Ref {
|
||||||
relay: self.template_mailbox.clone(),
|
relay: self.mailbox(),
|
||||||
target: crate::next_oid(),
|
target: crate::next_oid(),
|
||||||
};
|
};
|
||||||
self.oid_map.insert(r.target.clone(), Cell::new(Box::new(e)));
|
self.oid_map.insert(r.target.clone(), Box::new(e));
|
||||||
Arc::new(r)
|
Arc::new(r)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn boot<F: Future<Output = ActorResult> + Send + 'static>(
|
pub fn boot<F: 'static + Send + FnOnce(&mut Self) -> BoxFuture<ActorResult>>(
|
||||||
mut self,
|
mut self,
|
||||||
name: tracing::Span,
|
name: tracing::Span,
|
||||||
boot: F,
|
boot: F,
|
||||||
) -> ActorHandle {
|
) -> ActorHandle {
|
||||||
|
let id = self.id();
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
trace!("start");
|
trace!(id, "start");
|
||||||
let run_future = self.run(boot);
|
let result = self.run(boot).await;
|
||||||
let result = run_future.await;
|
{
|
||||||
|
let mut t = Activation::for_actor(&mut self);
|
||||||
|
for oid in std::mem::take(&mut t.actor.exit_hooks) {
|
||||||
|
match t.actor.oid_map.remove_entry(&oid) {
|
||||||
|
None => (),
|
||||||
|
Some((k, mut e)) => {
|
||||||
|
if let Err(err) = e.exit_hook(&mut t, &result).await {
|
||||||
|
tracing::warn!(err = debug(err),
|
||||||
|
oid = debug(oid),
|
||||||
|
"error in exit hook");
|
||||||
|
}
|
||||||
|
t.actor.oid_map.insert(k, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
match &result {
|
match &result {
|
||||||
Ok(()) => trace!("normal stop"),
|
Ok(()) => trace!(id, "normal stop"),
|
||||||
Err(e) => error!("{}", e),
|
Err(e) => error!(id, "error stop: {}", e),
|
||||||
}
|
}
|
||||||
result
|
result
|
||||||
}.instrument(name))
|
}.instrument(name))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn start(self, name: tracing::Span) -> ActorHandle {
|
pub fn start(self, name: tracing::Span) -> ActorHandle {
|
||||||
self.boot(name, ready(Ok(())))
|
self.boot(name, |_ac| Box::pin(ready(Ok(()))))
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn run<F: Future<Output = ActorResult>>(&mut self, boot: F) -> ActorResult {
|
async fn run<F: 'static + Send + FnOnce(&mut Self) -> BoxFuture<ActorResult>>(
|
||||||
boot.await?;
|
&mut self,
|
||||||
|
boot: F,
|
||||||
|
) -> ActorResult {
|
||||||
|
let id = self.id();
|
||||||
|
trace!(id, "boot");
|
||||||
|
boot(self).await?;
|
||||||
|
trace!(id, "run");
|
||||||
loop {
|
loop {
|
||||||
match self.rx.recv().await {
|
match self.rx.recv().await {
|
||||||
None =>
|
None =>
|
||||||
|
@ -265,6 +345,7 @@ impl Actor {
|
||||||
detail: _Any::new(false),
|
detail: _Any::new(false),
|
||||||
})?,
|
})?,
|
||||||
Some(m) => {
|
Some(m) => {
|
||||||
|
trace!(id, m = debug(&m), "system message");
|
||||||
if self.handle(m)? {
|
if self.handle(m)? {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
@ -273,12 +354,16 @@ impl Actor {
|
||||||
// (instead zeroing it on queue empty - it only needs to be approximate),
|
// (instead zeroing it on queue empty - it only needs to be approximate),
|
||||||
// but try_recv has been removed from mpsc at the time of writing. See
|
// but try_recv has been removed from mpsc at the time of writing. See
|
||||||
// https://github.com/tokio-rs/tokio/issues/3350 .
|
// https://github.com/tokio-rs/tokio/issues/3350 .
|
||||||
self.template_mailbox.queue_depth.fetch_sub(1, Ordering::Relaxed);
|
self.queue_depth.fetch_sub(1, Ordering::Relaxed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn add_exit_hook(&mut self, oid: &Oid) {
|
||||||
|
self.exit_hooks.push(oid.clone())
|
||||||
|
}
|
||||||
|
|
||||||
fn handle(&mut self, m: SystemMessage) -> Result<bool, Error> {
|
fn handle(&mut self, m: SystemMessage) -> Result<bool, Error> {
|
||||||
match m {
|
match m {
|
||||||
SystemMessage::Release =>
|
SystemMessage::Release =>
|
||||||
|
@ -288,30 +373,35 @@ impl Actor {
|
||||||
Ok(false)
|
Ok(false)
|
||||||
}
|
}
|
||||||
SystemMessage::Turn(Turn(events)) => {
|
SystemMessage::Turn(Turn(events)) => {
|
||||||
|
let mut t = Activation::for_actor(self);
|
||||||
|
let mut revisit_oids = Vec::new();
|
||||||
for TurnEvent { oid, event } in events.into_iter() {
|
for TurnEvent { oid, event } in events.into_iter() {
|
||||||
if let Some(e) = self.oid_map.get_mut(&oid) {
|
t.with_oid(&oid, |_| Ok(()), |t, e| match event {
|
||||||
let mut t = Activation::for_actor_details(&mut self.outbound_assertions);
|
Event::Assert(b) => {
|
||||||
let e = e.get_mut();
|
let Assert { assertion: Assertion(assertion), handle } = *b;
|
||||||
match event {
|
e.assert(t, assertion, handle)
|
||||||
Event::Assert(b) => {
|
|
||||||
let Assert { assertion: Assertion(assertion), handle } = *b;
|
|
||||||
e.assert(&mut t, assertion, handle)?;
|
|
||||||
}
|
|
||||||
Event::Retract(b) => {
|
|
||||||
let Retract { handle } = *b;
|
|
||||||
e.retract(&mut t, handle)?;
|
|
||||||
}
|
|
||||||
Event::Message(b) => {
|
|
||||||
let Message { body: Assertion(body) } = *b;
|
|
||||||
e.message(&mut t, body)?;
|
|
||||||
}
|
|
||||||
Event::Sync(b) => {
|
|
||||||
let Sync { peer } = *b;
|
|
||||||
e.sync(&mut t, peer)?;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
Event::Retract(b) => {
|
||||||
|
let Retract { handle } = *b;
|
||||||
|
e.retract(t, handle)
|
||||||
|
}
|
||||||
|
Event::Message(b) => {
|
||||||
|
let Message { body: Assertion(body) } = *b;
|
||||||
|
e.message(t, body)
|
||||||
|
}
|
||||||
|
Event::Sync(b) => {
|
||||||
|
let Sync { peer } = *b;
|
||||||
|
e.sync(t, peer)
|
||||||
|
}
|
||||||
|
})?;
|
||||||
|
if t.turn_end_revisit_flag {
|
||||||
|
t.turn_end_revisit_flag = false;
|
||||||
|
revisit_oids.push(oid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for oid in revisit_oids {
|
||||||
|
t.with_oid(&oid, |_| Ok(()), |t, e| e.turn_end(t))?;
|
||||||
|
}
|
||||||
Ok(false)
|
Ok(false)
|
||||||
}
|
}
|
||||||
SystemMessage::Crash(e) =>
|
SystemMessage::Crash(e) =>
|
||||||
|
@ -319,33 +409,41 @@ impl Actor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn linked_task<F: Future<Output = ActorResult> + Send + 'static>(
|
pub fn linked_task<F: futures::Future<Output = ActorResult> + Send + 'static>(
|
||||||
&mut self,
|
&mut self,
|
||||||
name: tracing::Span,
|
name: tracing::Span,
|
||||||
boot: F,
|
boot: F,
|
||||||
) {
|
) -> ActorHandle {
|
||||||
let mailbox = self.template_mailbox.clone();
|
let id = self.id();
|
||||||
|
let mailbox = self.mailbox();
|
||||||
let token = CancellationToken::new();
|
let token = CancellationToken::new();
|
||||||
let task_id = self.next_task_id;
|
let task_id = self.next_task_id;
|
||||||
self.next_task_id += 1;
|
self.next_task_id += 1;
|
||||||
{
|
let handle = {
|
||||||
let token = token.clone();
|
let token = token.clone();
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
trace!("linked task start");
|
trace!(id, task_id, "linked task start");
|
||||||
select! {
|
select! {
|
||||||
_ = token.cancelled() => (),
|
_ = token.cancelled() => {
|
||||||
result = boot => match result {
|
trace!(id, task_id, "linked task cancelled");
|
||||||
Ok(()) => trace!("linked task normal stop"),
|
Ok(())
|
||||||
Err(e) => {
|
}
|
||||||
error!("linked task error: {}", e);
|
result = boot => {
|
||||||
let _ = mailbox.tx.send(SystemMessage::Crash(e));
|
match &result {
|
||||||
()
|
Ok(()) => trace!(id, task_id, "linked task normal stop"),
|
||||||
|
Err(e) => {
|
||||||
|
error!(id, task_id, "linked task error: {}", e);
|
||||||
|
let _ = mailbox.tx.send(SystemMessage::Crash(e.clone()));
|
||||||
|
()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
result
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}.instrument(name));
|
}.instrument(name))
|
||||||
}
|
};
|
||||||
self.linked_tasks.insert(task_id, token);
|
self.linked_tasks.insert(task_id, token);
|
||||||
|
handle
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -363,6 +461,12 @@ impl Drop for Actor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Ref {
|
||||||
|
pub fn external_event(&self, event: Event) {
|
||||||
|
self.relay.send(Turn(vec![TurnEvent { oid: self.target.clone(), event }]))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Drop for Ref {
|
impl Drop for Ref {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
let _ = self.relay.tx.send(SystemMessage::ReleaseOid(self.target.clone()));
|
let _ = self.relay.tx.send(SystemMessage::ReleaseOid(self.target.clone()));
|
||||||
|
@ -370,20 +474,17 @@ impl Drop for Ref {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Domain for Ref {
|
impl Domain for Ref {}
|
||||||
fn from_preserves(v: IOValue) -> IOResult<Self> {
|
|
||||||
panic!("aiee")
|
impl std::convert::TryFrom<&IOValue> for Ref {
|
||||||
}
|
type Error = preserves_schema::support::ParseError;
|
||||||
fn as_preserves(&self) -> IOValue {
|
fn try_from(_v: &IOValue) -> Result<Self, Self::Error> {
|
||||||
panic!("aiee")
|
panic!("Attempted to serialize Ref via IOValue");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Domain for super::schemas::sturdy::WireRef {
|
impl std::convert::From<&Ref> for IOValue {
|
||||||
fn from_preserves(v: IOValue) -> IOResult<Self> {
|
fn from(_v: &Ref) -> IOValue {
|
||||||
panic!("aiee")
|
panic!("Attempted to deserialize Ref via IOValue");
|
||||||
}
|
|
||||||
fn as_preserves(&self) -> IOValue {
|
|
||||||
panic!("aiee")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,6 @@
|
||||||
use futures::{SinkExt, StreamExt};
|
use futures::SinkExt;
|
||||||
|
use futures::StreamExt;
|
||||||
|
|
||||||
use preserves::value::PackedReader;
|
|
||||||
use preserves::value::PackedWriter;
|
|
||||||
use preserves::value::Reader;
|
|
||||||
use preserves::value::Writer;
|
|
||||||
|
|
||||||
use std::convert::TryFrom;
|
|
||||||
use std::future::Ready;
|
|
||||||
use std::future::ready;
|
use std::future::ready;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
@ -17,12 +11,10 @@ use syndicate::dataspace::*;
|
||||||
use syndicate::error::Error;
|
use syndicate::error::Error;
|
||||||
use syndicate::error::error;
|
use syndicate::error::error;
|
||||||
use syndicate::config;
|
use syndicate::config;
|
||||||
use syndicate::packets;
|
use syndicate::relay;
|
||||||
use syndicate::peer::Peer;
|
|
||||||
|
|
||||||
use tokio::net::TcpListener;
|
use tokio::net::TcpListener;
|
||||||
use tokio::net::TcpStream;
|
use tokio::net::TcpStream;
|
||||||
use tokio_util::codec::Framed;
|
|
||||||
|
|
||||||
use tracing::{Level, info, trace};
|
use tracing::{Level, info, trace};
|
||||||
|
|
||||||
|
@ -31,7 +23,7 @@ use tungstenite::Message;
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let filter = tracing_subscriber::filter::EnvFilter::from_default_env()
|
let filter = tracing_subscriber::filter::EnvFilter::from_default_env()
|
||||||
.add_directive(tracing_subscriber::filter::LevelFilter::INFO.into());
|
.add_directive(tracing_subscriber::filter::LevelFilter::TRACE.into());
|
||||||
let subscriber = tracing_subscriber::FmtSubscriber::builder()
|
let subscriber = tracing_subscriber::FmtSubscriber::builder()
|
||||||
.with_ansi(true)
|
.with_ansi(true)
|
||||||
.with_max_level(Level::TRACE)
|
.with_max_level(Level::TRACE)
|
||||||
|
@ -80,7 +72,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
trace!("startup");
|
trace!("startup");
|
||||||
|
|
||||||
let ds = {
|
let ds = {
|
||||||
let ac = Actor::new();
|
let mut ac = Actor::new();
|
||||||
let ds = ac.create(Dataspace::new());
|
let ds = ac.create(Dataspace::new());
|
||||||
daemons.push(ac.start(tracing::info_span!("dataspace")));
|
daemons.push(ac.start(tracing::info_span!("dataspace")));
|
||||||
ds
|
ds
|
||||||
|
@ -89,8 +81,9 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
for port in config.ports.clone() {
|
for port in config.ports.clone() {
|
||||||
let ds = Arc::clone(&ds);
|
let ds = Arc::clone(&ds);
|
||||||
let config = Arc::clone(&config);
|
let config = Arc::clone(&config);
|
||||||
let ac = Actor::new();
|
let mut ac = Actor::new();
|
||||||
ac.linked_task(tracing::info_span!("listener", port), run_listener(ds, port, config));
|
ac.linked_task(tracing::info_span!("tcp", port), run_listener(ds, port, config));
|
||||||
|
daemons.push(ac.start(tracing::info_span!("tcp", port)));
|
||||||
}
|
}
|
||||||
|
|
||||||
futures::future::join_all(daemons).await;
|
futures::future::join_all(daemons).await;
|
||||||
|
@ -103,29 +96,15 @@ fn message_error<E: std::fmt::Display>(e: E) -> Error {
|
||||||
error(&e.to_string(), false)
|
error(&e.to_string(), false)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn encode_message(p: packets::Packet) -> Result<Message, Error> {
|
fn extract_binary_packets(
|
||||||
let mut bs = Vec::with_capacity(128);
|
|
||||||
PackedWriter::new(&mut bs).write(&(&p).into())?;
|
|
||||||
Ok(Message::Binary(bs))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn message_encoder(p: packets::Packet) -> Ready<Result<Message, Error>>
|
|
||||||
{
|
|
||||||
ready(encode_message(p))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn message_decoder_inner(
|
|
||||||
r: Result<Message, tungstenite::Error>,
|
r: Result<Message, tungstenite::Error>,
|
||||||
) -> Result<Option<packets::Packet>, Error> {
|
) -> Result<Option<Vec<u8>>, Error> {
|
||||||
match r {
|
match r {
|
||||||
Ok(m) => match m {
|
Ok(m) => match m {
|
||||||
Message::Text(_) =>
|
Message::Text(_) =>
|
||||||
Err("Text websocket frames are not accepted")?,
|
Err("Text websocket frames are not accepted")?,
|
||||||
Message::Binary(bs) => {
|
Message::Binary(bs) =>
|
||||||
let iov = PackedReader::decode_bytes(&bs).demand_next(false)?;
|
Ok(Some(bs)),
|
||||||
let p = packets::Packet::try_from(&iov)?;
|
|
||||||
Ok(Some(p))
|
|
||||||
}
|
|
||||||
Message::Ping(_) =>
|
Message::Ping(_) =>
|
||||||
Ok(None), // pings are handled by tungstenite before we see them
|
Ok(None), // pings are handled by tungstenite before we see them
|
||||||
Message::Pong(_) =>
|
Message::Pong(_) =>
|
||||||
|
@ -137,50 +116,46 @@ fn message_decoder_inner(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn message_decoder(r: Result<Message, tungstenite::Error>) -> Ready<Option<Result<packets::Packet, Error>>> {
|
|
||||||
ready(message_decoder_inner(r).transpose())
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn run_connection(
|
async fn run_connection(
|
||||||
mut stream: TcpStream,
|
ac: &mut Actor,
|
||||||
|
stream: TcpStream,
|
||||||
ds: Arc<Ref>,
|
ds: Arc<Ref>,
|
||||||
addr: std::net::SocketAddr,
|
addr: std::net::SocketAddr,
|
||||||
config: Arc<config::ServerConfig>,
|
config: Arc<config::ServerConfig>,
|
||||||
) -> ActorResult {
|
) -> ActorResult {
|
||||||
let mut buf = [0; 1]; // peek at the first byte to see what kind of connection to expect
|
let mut buf = [0; 1]; // peek at the first byte to see what kind of connection to expect
|
||||||
match stream.peek(&mut buf).await? {
|
let (i, o) = match stream.peek(&mut buf).await? {
|
||||||
1 => match buf[0] {
|
1 => match buf[0] {
|
||||||
71 /* ASCII 'G' for "GET" */ => {
|
71 /* ASCII 'G' for "GET" */ => {
|
||||||
info!(protocol = display("websocket"), peer = debug(addr));
|
info!(protocol = display("websocket"), peer = debug(addr));
|
||||||
let s = tokio_tungstenite::accept_async(stream).await
|
let s = tokio_tungstenite::accept_async(stream).await
|
||||||
.map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e))?;
|
.map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e))?;
|
||||||
let (o, i) = s.split();
|
let (o, i) = s.split();
|
||||||
let i = i.filter_map(message_decoder);
|
let i = i.filter_map(|r| ready(extract_binary_packets(r).transpose()));
|
||||||
let o = o.sink_map_err(message_error).with(message_encoder);
|
let o = o.sink_map_err(message_error).with(|bs| ready(Ok(Message::Binary(bs))));
|
||||||
let mut p = Peer::new(i, o, ds, config);
|
(relay::Input::Packets(Box::pin(i)), relay::Output::Packets(Box::pin(o)))
|
||||||
p.run().await?
|
|
||||||
},
|
},
|
||||||
_ => {
|
_ => {
|
||||||
info!(protocol = display("raw"), peer = debug(addr));
|
info!(protocol = display("raw"), peer = debug(addr));
|
||||||
let (o, i) = Framed::new(stream, packets::Codec).split();
|
let (i, o) = stream.into_split();
|
||||||
let mut p = Peer::new(i, o, ds, config);
|
(relay::Input::Bytes(Box::pin(i)), relay::Output::Bytes(Box::pin(o)))
|
||||||
p.run().await?
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
0 => Err(error("closed before starting", false))?,
|
0 => Err(error("closed before starting", false))?,
|
||||||
_ => unreachable!()
|
_ => unreachable!()
|
||||||
}
|
};
|
||||||
Ok(())
|
Ok(relay::TunnelRelay::run(ac, i, o)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn run_listener(ds: Arc<Ref>, port: u16, config: Arc<config::ServerConfig>) -> ActorResult {
|
async fn run_listener(ds: Arc<Ref>, port: u16, config: Arc<config::ServerConfig>) -> ActorResult {
|
||||||
let listener = TcpListener::bind(format!("0.0.0.0:{}", port)).await?;
|
let listener = TcpListener::bind(format!("0.0.0.0:{}", port)).await?;
|
||||||
loop {
|
loop {
|
||||||
let (stream, addr) = listener.accept().await?;
|
let (stream, addr) = listener.accept().await?;
|
||||||
let mut ac = Actor::new();
|
|
||||||
let ds = Arc::clone(&ds);
|
let ds = Arc::clone(&ds);
|
||||||
let config = Arc::clone(&config);
|
let config = Arc::clone(&config);
|
||||||
ac.linked_task(tracing::info_span!("connection", id = (ac.id())),
|
let ac = Actor::new();
|
||||||
run_connection(stream, ds, addr, config));
|
let id = ac.id();
|
||||||
|
ac.boot(tracing::info_span!(parent: None, "connection", id),
|
||||||
|
move |ac| Box::pin(run_connection(ac, stream, ds, addr, config)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,10 +13,9 @@ pub mod bag;
|
||||||
pub mod config;
|
pub mod config;
|
||||||
pub mod dataspace;
|
pub mod dataspace;
|
||||||
pub mod error;
|
pub mod error;
|
||||||
pub mod schemas;
|
|
||||||
pub mod packets;
|
|
||||||
pub mod pattern;
|
pub mod pattern;
|
||||||
pub mod peer;
|
pub mod relay;
|
||||||
|
pub mod schemas;
|
||||||
pub mod skeleton;
|
pub mod skeleton;
|
||||||
|
|
||||||
pub type Assertion = schemas::dataspace::_Any;
|
pub type Assertion = schemas::dataspace::_Any;
|
||||||
|
|
|
@ -1,35 +0,0 @@
|
||||||
pub use crate::schemas::internal_protocol::*;
|
|
||||||
|
|
||||||
use bytes::{Buf, BufMut, BytesMut};
|
|
||||||
|
|
||||||
use std::convert::TryFrom;
|
|
||||||
|
|
||||||
use preserves::value::PackedReader;
|
|
||||||
use preserves::value::PackedWriter;
|
|
||||||
use preserves::value::Reader;
|
|
||||||
use preserves::value::Writer;
|
|
||||||
|
|
||||||
pub struct Codec;
|
|
||||||
|
|
||||||
impl tokio_util::codec::Decoder for Codec {
|
|
||||||
type Item = Packet;
|
|
||||||
type Error = Error;
|
|
||||||
fn decode(&mut self, bs: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error> {
|
|
||||||
let mut r = PackedReader::decode_bytes(bs);
|
|
||||||
match r.next(false)? {
|
|
||||||
None => Ok(None),
|
|
||||||
Some(item) => {
|
|
||||||
let count = r.source.index;
|
|
||||||
bs.advance(count);
|
|
||||||
Ok(Some(Packet::try_from(&item)?))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl tokio_util::codec::Encoder<&Packet> for Codec {
|
|
||||||
type Error = Error;
|
|
||||||
fn encode(&mut self, item: &Packet, bs: &mut BytesMut) -> Result<(), Self::Error> {
|
|
||||||
Ok(PackedWriter::new(&mut bs.writer()).write(&item.into())?)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,293 @@
|
||||||
|
use bytes::Buf;
|
||||||
|
use bytes::BytesMut;
|
||||||
|
|
||||||
|
use crate::actor::*;
|
||||||
|
use crate::error::Error;
|
||||||
|
use crate::schemas::internal_protocol::*;
|
||||||
|
use crate::schemas::tunnel_relay;
|
||||||
|
|
||||||
|
use futures::Sink;
|
||||||
|
use futures::SinkExt;
|
||||||
|
use futures::Stream;
|
||||||
|
use futures::StreamExt;
|
||||||
|
|
||||||
|
use preserves::value::BinarySource;
|
||||||
|
use preserves::value::BytesBinarySource;
|
||||||
|
use preserves::value::DomainDecode;
|
||||||
|
use preserves::value::DomainEncode;
|
||||||
|
use preserves::value::IOValue;
|
||||||
|
use preserves::value::Map;
|
||||||
|
use preserves::value::NoEmbeddedDomainCodec;
|
||||||
|
use preserves::value::PackedReader;
|
||||||
|
use preserves::value::PackedWriter;
|
||||||
|
use preserves::value::Reader;
|
||||||
|
use preserves::value::Writer;
|
||||||
|
use preserves_schema::support::lazy_static;
|
||||||
|
|
||||||
|
use std::convert::TryFrom;
|
||||||
|
use std::io;
|
||||||
|
use std::pin::Pin;
|
||||||
|
use std::sync::Arc;
|
||||||
|
use std::sync::atomic;
|
||||||
|
|
||||||
|
use tokio::io::AsyncRead;
|
||||||
|
use tokio::io::AsyncReadExt;
|
||||||
|
use tokio::io::AsyncWrite;
|
||||||
|
use tokio::io::AsyncWriteExt;
|
||||||
|
|
||||||
|
use tracing;
|
||||||
|
|
||||||
|
struct WireSymbol {
|
||||||
|
oid: Oid,
|
||||||
|
obj: Arc<Ref>,
|
||||||
|
ref_count: atomic::AtomicUsize,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Membrane {
|
||||||
|
oid_map: Map<Oid, Arc<WireSymbol>>,
|
||||||
|
ref_map: Map<Arc<Ref>, Arc<WireSymbol>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Membranes {
|
||||||
|
exported: Membrane,
|
||||||
|
imported: Membrane,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum Input {
|
||||||
|
Packets(Pin<Box<dyn Stream<Item = Result<Vec<u8>, Error>> + Send>>),
|
||||||
|
Bytes(Pin<Box<dyn AsyncRead + Send>>),
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum Output {
|
||||||
|
Packets(Pin<Box<dyn Sink<Vec<u8>, Error = Error> + Send>>),
|
||||||
|
Bytes(Pin<Box<dyn AsyncWrite + Send>>),
|
||||||
|
}
|
||||||
|
|
||||||
|
// There are other kinds of relay. This one has exactly two participants connected to each other.
|
||||||
|
pub struct TunnelRelay
|
||||||
|
{
|
||||||
|
input_buffer: BytesMut,
|
||||||
|
o: Output,
|
||||||
|
inbound_assertions: Map</* remote */ Handle, (/* local */ Handle, Vec<Arc<WireSymbol>>)>,
|
||||||
|
outbound_assertions: Map<Handle, Vec<Arc<WireSymbol>>>,
|
||||||
|
membranes: Membranes,
|
||||||
|
pending_outbound: Vec<TurnEvent>,
|
||||||
|
}
|
||||||
|
|
||||||
|
lazy_static! {
|
||||||
|
static ref INERT_REF: Arc<Ref> = {
|
||||||
|
struct InertEntity;
|
||||||
|
impl crate::actor::Entity for InertEntity {}
|
||||||
|
let mut ac = crate::actor::Actor::new();
|
||||||
|
ac.create(InertEntity)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
impl WireSymbol {
|
||||||
|
fn acquire(&self) {
|
||||||
|
self.ref_count.fetch_add(1, atomic::Ordering::Relaxed);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn release(&self) -> bool {
|
||||||
|
self.ref_count.fetch_sub(1, atomic::Ordering::Relaxed) == 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Membrane {
|
||||||
|
fn new() -> Self {
|
||||||
|
Membrane {
|
||||||
|
oid_map: Map::new(),
|
||||||
|
ref_map: Map::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn insert(&mut self, oid: Oid, obj: Arc<Ref>) -> Arc<WireSymbol> {
|
||||||
|
let ws = Arc::new(WireSymbol {
|
||||||
|
oid: oid.clone(),
|
||||||
|
obj: Arc::clone(&obj),
|
||||||
|
ref_count: atomic::AtomicUsize::new(0),
|
||||||
|
});
|
||||||
|
self.oid_map.insert(oid, Arc::clone(&ws));
|
||||||
|
self.ref_map.insert(obj, Arc::clone(&ws));
|
||||||
|
ws
|
||||||
|
}
|
||||||
|
|
||||||
|
fn release(&mut self, ws: &Arc<WireSymbol>) {
|
||||||
|
if ws.release() {
|
||||||
|
self.oid_map.remove(&ws.oid);
|
||||||
|
self.ref_map.remove(&ws.obj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TunnelRelay {
|
||||||
|
pub fn run(ac: &mut Actor, i: Input, o: Output) -> ActorResult {
|
||||||
|
let tr = ac.create(TunnelRelay {
|
||||||
|
input_buffer: BytesMut::with_capacity(1024),
|
||||||
|
o,
|
||||||
|
inbound_assertions: Map::new(),
|
||||||
|
outbound_assertions: Map::new(),
|
||||||
|
membranes: Membranes {
|
||||||
|
exported: Membrane::new(),
|
||||||
|
imported: Membrane::new(),
|
||||||
|
},
|
||||||
|
pending_outbound: Vec::new(),
|
||||||
|
});
|
||||||
|
ac.add_exit_hook(&tr.target);
|
||||||
|
ac.linked_task(tracing::info_span!("reader"), input_loop(i, tr));
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_packet(&mut self, p: Packet) -> ActorResult {
|
||||||
|
match p {
|
||||||
|
Packet::Error(b) => {
|
||||||
|
tracing::info!(message = debug(b.message.clone()),
|
||||||
|
detail = debug(b.detail.clone()),
|
||||||
|
"received Error from peer");
|
||||||
|
Err(*b)
|
||||||
|
},
|
||||||
|
Packet::Turn(b) => {
|
||||||
|
let Turn(events) = *b;
|
||||||
|
for TurnEvent { oid, event } in events {
|
||||||
|
tracing::info!(oid = debug(oid), event = debug(event))
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn send_event(&mut self, oid: Oid, event: Event) -> bool {
|
||||||
|
let need_flush = self.pending_outbound.is_empty();
|
||||||
|
self.pending_outbound.push(TurnEvent { oid, event });
|
||||||
|
need_flush
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn decode_packet(&mut self, bs: &[u8]) -> Result<Packet, Error> {
|
||||||
|
let mut src = BytesBinarySource::new(bs);
|
||||||
|
Ok(Packet::try_from(&src.packed::<_, _Any, _>(&mut self.membranes).demand_next(false)?)?)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn encode_packet(&mut self, p: Packet) -> Result<Vec<u8>, Error> {
|
||||||
|
Ok(PackedWriter::encode::<_, _Any, _>(&mut self.membranes, &_Any::from(&p))?)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn send_packet(&mut self, p: Packet) -> ActorResult {
|
||||||
|
let bs = self.encode_packet(p)?;
|
||||||
|
match &mut self.o {
|
||||||
|
Output::Packets(sink) => Ok(sink.send(bs).await?),
|
||||||
|
Output::Bytes(w) => Ok(w.write_all(&bs).await?),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DomainDecode<_Ptr> for Membranes {
|
||||||
|
fn decode_embedded<'de, 'src, S: BinarySource<'de>>(
|
||||||
|
&mut self,
|
||||||
|
src: &'src mut S,
|
||||||
|
_read_annotations: bool,
|
||||||
|
) -> io::Result<_Ptr> {
|
||||||
|
let v: IOValue = PackedReader::new(src, NoEmbeddedDomainCodec).demand_next(false)?;
|
||||||
|
Ok(Arc::new(_Dom::try_from(&v)?))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DomainEncode<_Ptr> for Membranes {
|
||||||
|
fn encode_embedded<W: Writer>(
|
||||||
|
&mut self,
|
||||||
|
w: &mut W,
|
||||||
|
d: &_Ptr,
|
||||||
|
) -> io::Result<()> {
|
||||||
|
w.write(&mut NoEmbeddedDomainCodec, &IOValue::from(d.as_ref()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn input_loop(
|
||||||
|
i: Input,
|
||||||
|
relay: Arc<Ref>,
|
||||||
|
) -> ActorResult {
|
||||||
|
fn s<M: Into<_Any>>(relay: &Arc<Ref>, m: M) {
|
||||||
|
relay.external_event(Event::Message(Box::new(Message { body: Assertion(m.into()) })))
|
||||||
|
}
|
||||||
|
|
||||||
|
match i {
|
||||||
|
Input::Packets(mut src) => {
|
||||||
|
loop {
|
||||||
|
match src.next().await {
|
||||||
|
None => {
|
||||||
|
s(&relay, &tunnel_relay::Input::Eof);
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
Some(bs) => s(&relay, &tunnel_relay::Input::Packet { bs: bs? }),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Input::Bytes(mut r) => {
|
||||||
|
let mut buf = BytesMut::with_capacity(1024);
|
||||||
|
loop {
|
||||||
|
buf.reserve(1024);
|
||||||
|
let n = r.read_buf(&mut buf).await?;
|
||||||
|
match n {
|
||||||
|
0 => {
|
||||||
|
s(&relay, &tunnel_relay::Input::Eof);
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
while buf.has_remaining() {
|
||||||
|
let bs = buf.chunk();
|
||||||
|
let n = bs.len();
|
||||||
|
s(&relay, &tunnel_relay::Input::Segment { bs: bs.to_vec() });
|
||||||
|
buf.advance(n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Entity for TunnelRelay {
|
||||||
|
fn message(&mut self, t: &mut Activation, m: _Any) -> ActorResult {
|
||||||
|
if let Ok(m) = tunnel_relay::Input::try_from(&m) {
|
||||||
|
match m {
|
||||||
|
tunnel_relay::Input::Eof => {
|
||||||
|
tracing::info!("eof");
|
||||||
|
t.actor.shutdown();
|
||||||
|
}
|
||||||
|
tunnel_relay::Input::Packet { bs } => {
|
||||||
|
let p = self.decode_packet(&bs)?;
|
||||||
|
self.handle_packet(p)?
|
||||||
|
}
|
||||||
|
tunnel_relay::Input::Segment { bs } => {
|
||||||
|
self.input_buffer.extend_from_slice(&bs);
|
||||||
|
loop {
|
||||||
|
let (e, count) = {
|
||||||
|
let mut src = BytesBinarySource::new(&self.input_buffer);
|
||||||
|
let mut r = src.packed::<_, _Any, _>(&mut self.membranes);
|
||||||
|
let e = r.next(false)?;
|
||||||
|
(e, r.source.index)
|
||||||
|
};
|
||||||
|
match e {
|
||||||
|
None => break,
|
||||||
|
Some(item) => {
|
||||||
|
self.input_buffer.advance(count);
|
||||||
|
self.handle_packet(Packet::try_from(&item)?)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn exit_hook(&mut self, _t: &mut Activation, exit_status: &ActorResult) -> BoxFuture<ActorResult> {
|
||||||
|
if let Err(e) = exit_status {
|
||||||
|
let e = e.clone();
|
||||||
|
Box::pin(self.send_packet(Packet::Error(Box::new(e))))
|
||||||
|
} else {
|
||||||
|
Box::pin(ready(Ok(())))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue