use mpstthree::binary::struct_trait::{end::End, recv::Recv, send::Send, session::Session}; use mpstthree::generate; use mpstthree::role::broadcast::RoleBroadcast; use mpstthree::role::end::RoleEnd; use rand::{thread_rng, Rng}; use std::error::Error; // See the folder scribble_protocols for the related Scribble protocol // Create new MeshedChannels for four participants generate!("rec_and_cancel", MeshedChannels, A, C, S); // Types // C0 type Choose0fromCtoA = Send; type Choose0fromCtoS = Send; // C1 type Choose1fromCtoA = ::Dual; type Choose1fromCtoS = ::Dual; // A enum Branching0fromCtoA { Select(MeshedChannels, NameA>), Loop( MeshedChannels< Recv>, Send, RoleC>>>, NameA, >, ), } type Choice0fromCtoA = Recv; enum Branching1fromCtoA { Yes(MeshedChannels, Send, RoleC>, NameA>), No(MeshedChannels, Send, RoleC>, NameA>), } type Choice1fromCtoA = Recv; // S enum Branching0fromCtoS { Select(MeshedChannels, NameS>), Loop(MeshedChannels, Choice0fromCtoS, RoleA>, NameS>), } type Choice0fromCtoS = Recv; enum Branching1fromCtoS { Yes( MeshedChannels< Recv, Recv>, RoleA>>, NameS, >, ), No(MeshedChannels, End, RoleA, NameS>), } type Choice1fromCtoS = Recv; // Creating the MP sessions // A type ChoiceA = MeshedChannels, NameA>; type EndpointA = MeshedChannels, NameA>; // C type ChoiceC = MeshedChannels; type ChoiceCYes = MeshedChannels, Send>, RoleA>>, NameC>; type ChoiceCNo = MeshedChannels, End, RoleA, NameC>; type EndpointC = MeshedChannels; type EndpointCLoop = MeshedChannels< Send>, Choose0fromCtoS, RoleA>, NameC, >; // S type ChoiceS = MeshedChannels, NameS>; type EndpointS = MeshedChannels, NameS>; // Functions // A fn endpoint_a(s: EndpointA) -> Result<(), Box> { offer_mpst!(s, { Branching0fromCtoA::Select(s) => { choice_a(s) }, Branching0fromCtoA::Loop(s) => { let (query, s) = s.recv()?; let s = s.send(query)?; let s = s.send(1)?; endpoint_a(s) }, }) } fn choice_a(s: ChoiceA) -> Result<(), Box> { offer_mpst!(s, { Branching1fromCtoA::Yes(s) => { let (yes, s) = s.recv()?; let s = s.send(yes)?; s.close() }, Branching1fromCtoA::No(s) => { let (no, s) = s.recv()?; let s = s.send(no)?; s.close() }, }) } fn endpoint_c_init(s: EndpointC) -> Result<(), Box> { endpoint_c(s, 100) } fn endpoint_c(s: EndpointC, loops: i32) -> Result<(), Box> { match loops { 0 => { let s = choose_mpst_c_to_all!(s, Branching0fromCtoA::Select, Branching0fromCtoS::Select); choice_c(s) } _ => { let s: EndpointCLoop = choose_mpst_c_to_all!(s, Branching0fromCtoA::Loop, Branching0fromCtoS::Loop); let s = s.send(1)?; let (_quote, s) = s.recv()?; endpoint_c(s, loops - 1) } } } fn choice_c(s: ChoiceC) -> Result<(), Box> { let choice: i32 = thread_rng().gen_range(1..3); if choice != 1 { let s: ChoiceCYes = choose_mpst_c_to_all!(s, Branching1fromCtoA::Yes, Branching1fromCtoS::Yes); let s = s.send(1)?; let s = s.send(1)?; let (_ack, s) = s.recv()?; s.close() } else { let s: ChoiceCNo = choose_mpst_c_to_all!(s, Branching1fromCtoA::No, Branching1fromCtoS::No); let s = s.send(0)?; s.close() } } fn endpoint_s(s: EndpointS) -> Result<(), Box> { offer_mpst!(s, { Branching0fromCtoS::Select(s) => { choice_s(s) }, Branching0fromCtoS::Loop(s) => { let (_dummy, s) = s.recv()?; endpoint_s(s) }, }) } fn choice_s(s: ChoiceS) -> Result<(), Box> { offer_mpst!(s, { Branching1fromCtoS::Yes(s) => { let (_yes, s) = s.recv()?; let (payment, s) = s.recv()?; let s = s.send(payment)?; s.close() }, Branching1fromCtoS::No(s) => { let (_no, s) = s.recv()?; s.close() }, }) } fn main() { let (thread_a, thread_c, thread_s) = fork_mpst(endpoint_a, endpoint_c_init, endpoint_s); thread_a.join().unwrap(); thread_c.join().unwrap(); thread_s.join().unwrap(); }