#![allow( clippy::type_complexity, clippy::too_many_arguments, clippy::large_enum_variant )] use mpstthree::binary::struct_trait::end::End; use mpstthree::binary_atmp::struct_trait::{recv::RecvTimed, send::SendTimed}; use mpstthree::generate_atmp; use mpstthree::role::broadcast::RoleBroadcast; use mpstthree::role::end::RoleEnd; use rand::{thread_rng, Rng}; use std::collections::HashMap; use std::error::Error; use std::time::Instant; // See the folder scribble_protocols for the related Scribble protocol generate_atmp!(MeshedChannels, A, C, S); // Payloads struct Start; struct Redirect; struct Login; struct Auth; struct Password; struct Success; struct Token; struct Fail; struct Received; // Types // A type Choose0fromAtoC = SendTimed; type Choose0fromAtoS = SendTimed; // C enum Branching0fromAtoC { Success( MeshedChannels< RecvTimed, SendTimed< Success, 'a', 0, true, 10, true, ' ', RecvTimed, >, RoleA>>, NameC, >, ), Fail( MeshedChannels< RecvTimed, SendTimed< Fail, 'a', 0, true, 10, true, ' ', RecvTimed, >, RoleA>>, NameC, >, ), } type Offer0fromCtoA = RecvTimed; // S enum Branching0fromAtoS { Success( MeshedChannels< SendTimed< Token, 'a', 0, true, 10, true, ' ', RecvTimed, >, RecvTimed< Success, 'a', 0, true, 10, true, ' ', SendTimed, >, RoleC>>>, NameS, >, ), Fail( MeshedChannels< End, RecvTimed< Fail, 'a', 0, true, 10, true, ' ', SendTimed, >, RoleC>, NameS, >, ), } type Offer0fromStoA = RecvTimed; // Creating the MP sessions // A type EndpointASuccess = MeshedChannels< SendTimed, RecvTimed< Token, 'a', 0, true, 10, true, ' ', SendTimed, >, RoleC>>, NameA, >; type EndpointAFail = MeshedChannels, End, RoleC, NameA>; type EndpointA = MeshedChannels< RecvTimed< Login, 'a', 0, true, 10, true, ' ', SendTimed< Auth, 'a', 0, true, 10, true, ' ', RecvTimed, >, >, Choose0fromAtoS, RoleC>>, NameA, >; // C type EndpointC = MeshedChannels< SendTimed< Login, 'a', 0, true, 10, true, ' ', RecvTimed< Auth, 'a', 0, true, 10, true, ' ', SendTimed, >, >, SendTimed< Start, 'a', 0, true, 10, true, ' ', RecvTimed, >, RoleS>>>>>, NameC, >; // S type EndpointS = MeshedChannels< Offer0fromStoA, RecvTimed< Start, 'a', 0, true, 10, true, ' ', SendTimed, >, RoleC>>, NameS, >; // Functions fn endpoint_a(s: EndpointA, all_clocks: &mut HashMap) -> Result<(), Box> { all_clocks.insert('a', Instant::now()); let (_, s) = s.recv(all_clocks)?; let s = s.send(Auth {}, all_clocks)?; let (_, s) = s.recv(all_clocks)?; let expected: i32 = thread_rng().gen_range(1..=3); if 1 == expected { let s: EndpointASuccess = choose_mpst_a_to_all!( s, all_clocks, Branching0fromAtoC::Success, Branching0fromAtoS::Success ); let s = s.send(Success {}, all_clocks)?; let (_, s) = s.recv(all_clocks)?; let s = s.send(Token {}, all_clocks)?; s.close() } else { let s: EndpointAFail = choose_mpst_a_to_all!( s, all_clocks, Branching0fromAtoC::Fail, Branching0fromAtoS::Fail ); let s = s.send(Fail {}, all_clocks)?; s.close() } } fn endpoint_c(s: EndpointC, all_clocks: &mut HashMap) -> Result<(), Box> { all_clocks.insert('a', Instant::now()); let s = s.send(Start {}, all_clocks)?; let (_, s) = s.recv(all_clocks)?; let s = s.send(Login {}, all_clocks)?; let (_, s) = s.recv(all_clocks)?; let s = s.send(Password {}, all_clocks)?; offer_mpst!(s, all_clocks, { Branching0fromAtoC::Success(s) => { let (_, s) = s.recv(all_clocks)?; let s = s.send(Success { }, all_clocks)?; let (_, s) = s.recv(all_clocks)?; s.close() }, Branching0fromAtoC::Fail(s) => { let (_, s) = s.recv(all_clocks)?; let s = s.send(Fail { }, all_clocks)?; let (_, s) = s.recv(all_clocks)?; s.close() }, }) } fn endpoint_s(s: EndpointS, all_clocks: &mut HashMap) -> Result<(), Box> { all_clocks.insert('a', Instant::now()); let (_, s) = s.recv(all_clocks)?; let s = s.send(Redirect {}, all_clocks)?; offer_mpst!(s, all_clocks, { Branching0fromAtoS::Success(s) => { let (_, s) = s.recv(all_clocks)?; let s = s.send(Token { }, all_clocks)?; let (_, s) = s.recv(all_clocks)?; let s = s.send(Token { }, all_clocks)?; s.close() }, Branching0fromAtoS::Fail(s) => { let (_, s) = s.recv(all_clocks)?; let s = s.send(Received { }, all_clocks)?; s.close() }, }) } fn main() { let (thread_a, thread_c, thread_s) = fork_mpst(endpoint_a, endpoint_c, endpoint_s); thread_a.join().unwrap(); thread_c.join().unwrap(); thread_s.join().unwrap(); }