Skip to content

Commit

Permalink
improved relationship establishment control messages
Browse files Browse the repository at this point in the history
Signed-off-by: Marc Schoolderman <[email protected]>
  • Loading branch information
tweedegolf-marc committed Jun 18, 2024
1 parent 7989205 commit c13817d
Show file tree
Hide file tree
Showing 8 changed files with 615 additions and 257 deletions.
162 changes: 152 additions & 10 deletions examples/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,31 @@ enum Commands {
#[arg(short, long)]
one: bool,
},
#[command(arg_required_else_help = true)]
Request {
#[arg(short, long, required = true)]
sender_vid: String,
#[arg(short, long, required = true)]
receiver_vid: String,
#[arg(long)]
nested: bool,
},
Accept {
#[arg(short, long, required = true)]
sender_vid: String,
#[arg(short, long, required = true)]
receiver_vid: String,
#[arg(long, required = true)]
thread_id: String,
#[arg(long)]
nested: bool,
},
Cancel {
#[arg(short, long, required = true)]
sender_vid: String,
#[arg(short, long, required = true)]
receiver_vid: String,
},
}

type Aliases = HashMap<String, String>;
Expand Down Expand Up @@ -348,24 +373,43 @@ async fn run() -> Result<(), Error> {
}
ReceivedTspMessage::RequestRelationship {
sender,
thread_id: _,
thread_id,
route: _,
nested_vid: None,
} => {
info!("received relationship request from {}", sender);
let thread_id = Base64UrlUnpadded::encode_string(&thread_id);
info!(
"received relationship request from {sender}, thread-id '{thread_id}'",
);
}
ReceivedTspMessage::AcceptRelationship { sender } => {
ReceivedTspMessage::AcceptRelationship {
sender,
nested_vid: None,
} => {
info!("received accept relationship from {}", sender);
}
ReceivedTspMessage::RequestRelationship {
sender,
thread_id,
route: _,
nested_vid: Some(vid),
} => {
let thread_id = Base64UrlUnpadded::encode_string(&thread_id);
info!("received nested relationship request from '{vid}' (new identity for {sender}), thread-id '{thread_id}'");
}
ReceivedTspMessage::AcceptRelationship {
sender,
nested_vid: Some(vid),
} => {
info!("received accept nested relationship from '{vid}' (new identity for {sender})");
}
ReceivedTspMessage::CancelRelationship { sender } => {
info!("received cancel relationship from {}", sender);
info!("received cancel relationship from {sender}");
}
ReceivedTspMessage::ForwardRequest {
sender, next_hop, ..
} => {
info!(
"messaging forwarding request from {} to {}",
sender, next_hop
);
info!("messaging forwarding request from {sender} to {next_hop}",);
}
ReceivedTspMessage::PendingMessage {
unknown_vid,
Expand Down Expand Up @@ -405,20 +449,118 @@ async fn run() -> Result<(), Error> {
.verify_and_open(&unknown_vid, &mut payload)
.await?;

write_database(&vault, &vid_database, aliases.clone()).await?;

info!(
"{vid} is verified and added to the database {}",
&args.database
);
let _ = handle_message(message);
}
write_database(&vault, &vid_database, aliases.clone()).await?;

if one {
break;
}
}
}
Commands::Cancel {
sender_vid,
receiver_vid,
} => {
let sender_vid = aliases.get(&sender_vid).unwrap_or(&sender_vid);
let receiver_vid = aliases.get(&receiver_vid).unwrap_or(&receiver_vid);

if let Err(e) = vid_database
.send_relationship_cancel(sender_vid, receiver_vid)
.await
{
tracing::error!("error sending message from {sender_vid} to {receiver_vid}: {e}");

return Ok(());
}

info!("sent control message from {sender_vid} to {receiver_vid}",);
write_database(&vault, &vid_database, aliases.clone()).await?;
}
Commands::Request {
sender_vid,
receiver_vid,
nested,
} => {
let sender_vid = aliases.get(&sender_vid).unwrap_or(&sender_vid);
let receiver_vid = aliases.get(&receiver_vid).unwrap_or(&receiver_vid);

if nested {
match vid_database
.send_nested_relationship_request(sender_vid, receiver_vid)
.await
{
Ok(vid) => {
tracing::info!(
"sent a nested relationship request to {receiver_vid} with new identity '{}'",
vid.identifier()
);
}
Err(e) => {
tracing::error!(
"error sending message from {sender_vid} to {receiver_vid}: {e}"
);
return Ok(());
}
}
} else if let Err(e) = vid_database
.send_relationship_request(sender_vid, receiver_vid, None)
.await
{
tracing::error!("error sending message from {sender_vid} to {receiver_vid}: {e}");
return Ok(());
}

info!("sent control message from {sender_vid} to {receiver_vid}",);
write_database(&vault, &vid_database, aliases.clone()).await?;
}
Commands::Accept {
sender_vid,
receiver_vid,
thread_id,
nested,
} => {
let sender_vid = aliases.get(&sender_vid).unwrap_or(&sender_vid);
let receiver_vid = aliases.get(&receiver_vid).unwrap_or(&receiver_vid);

let mut digest: [u8; 32] = Default::default();
Base64UrlUnpadded::decode(&thread_id, &mut digest).unwrap();

if nested {
match vid_database
.send_nested_relationship_accept(sender_vid, receiver_vid, digest)
.await
{
Ok(vid) => {
tracing::info!(
"formed a nested relationship with {receiver_vid} with new identity '{}'",
vid.identifier()
);
}
Err(e) => {
tracing::error!(
"error sending message from {sender_vid} to {receiver_vid}: {e}"
);

return Ok(());
}
}
} else if let Err(e) = vid_database
.send_relationship_accept(sender_vid, receiver_vid, digest, None)
.await
{
tracing::error!("error sending message from {sender_vid} to {receiver_vid}: {e}");

return Ok(());
}

info!("sent control message from {sender_vid} to {receiver_vid}",);
write_database(&vault, &vid_database, aliases.clone()).await?;
}
}

vault.close().await?;
Expand Down
95 changes: 92 additions & 3 deletions tsp/src/async_store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use crate::{
},
error::Error,
store::Store,
ExportVid, PrivateVid,
ExportVid, OwnedVid, PrivateVid,
};
use futures::StreamExt;
use url::Url;
Expand Down Expand Up @@ -217,7 +217,7 @@ impl AsyncStore {

self.set_relation_status_for_vid(
receiver.identifier(),
RelationshipStatus::Unidirectional(thread_id),
RelationshipStatus::Unidirectional { thread_id },
)?;

Ok(())
Expand Down Expand Up @@ -247,7 +247,13 @@ impl AsyncStore {
crate::transport::send_message(&transport, &tsp_message).await?;
}

self.set_relation_status_for_vid(receiver, RelationshipStatus::Bidirectional(thread_id))?;
self.set_relation_status_for_vid(
receiver,
RelationshipStatus::Bidirectional {
thread_id,
outstanding_nested_thread_ids: Default::default(),
},
)?;

Ok(())
}
Expand Down Expand Up @@ -275,6 +281,89 @@ impl AsyncStore {
Ok(())
}

/// Send a nested relationship request to `receiver`, creating a new nested vid with `outer_sender` as a parent.
pub async fn send_nested_relationship_request(
&self,
parent_sender: &str,
receiver: &str,
) -> Result<OwnedVid, Error> {
let sender = self.inner.get_private_vid(parent_sender)?;
let receiver = self.inner.get_verified_vid(receiver)?;

let nested_vid = self.make_propositioning_vid(sender.identifier())?;

let (tsp_message, thread_id) = crate::crypto::seal_and_hash(
&*sender,
&*receiver,
None,
Payload::RequestNestedRelationship {
vid: nested_vid.vid().as_ref(),
},
)?;

self.inner
.add_nested_thread_id(receiver.identifier(), thread_id)?;

crate::transport::send_message(receiver.endpoint(), &tsp_message).await?;

Ok(nested_vid)
}

/// Accept a nested relationship with the (nested) VID identified by `nested_receiver`.
/// Generate a new nested VID that will have `parent_sender` as its parent.
/// `thread_id` must be the same as the one that was present in the relationship request.
/// Encodes the control message, encrypts, signs and sends a TSP message
pub async fn send_nested_relationship_accept(
&self,
parent_sender: &str,
nested_receiver: &str,
thread_id: Digest,
) -> Result<OwnedVid, Error> {
let nested_vid = self.make_propositioning_vid(parent_sender)?;
self.set_relation_for_vid(nested_vid.identifier(), Some(nested_receiver))?;
self.set_relation_for_vid(nested_receiver, Some(nested_vid.identifier()))?;

let receiver_vid = self.inner.get_vid(nested_receiver)?;
let parent_receiver = receiver_vid
.get_parent_vid()
.ok_or(Error::Relationship(format!(
"missing parent for {nested_receiver}"
)))?;

let (transport, tsp_message) = self.inner.seal_message_payload(
parent_sender,
parent_receiver,
None,
Payload::AcceptNestedRelationship {
thread_id,
vid: nested_vid.vid().as_ref(),
connect_to_vid: nested_receiver.as_ref(),
},
)?;

crate::transport::send_message(&transport, &tsp_message).await?;

self.set_relation_status_for_vid(
nested_receiver,
RelationshipStatus::Bidirectional {
thread_id,
outstanding_nested_thread_ids: Default::default(),
},
)?;

Ok(nested_vid)
}

fn make_propositioning_vid(&self, parent_vid: &str) -> Result<OwnedVid, Error> {
let transport = Url::from_file_path("/dev/null").expect("error generating a URL");

let vid = OwnedVid::new_did_peer(transport);
self.inner.add_private_vid(vid.clone())?;
self.set_parent_for_vid(vid.identifier(), Some(parent_vid))?;

Ok(vid)
}

/// Receive, open and forward a TSP message
/// This method is used by intermediary nodes to receive a TSP message,
/// open it and forward it to the next hop.
Expand Down
Loading

0 comments on commit c13817d

Please sign in to comment.