use rand::{thread_rng, Rng}; use mpstthree::binary::struct_trait::{end::End, recv::Recv, send::Send, session::Session}; use mpstthree::functionmpst::fork::fork_mpst; use mpstthree::meshedchannels::MeshedChannels; use mpstthree::role::broadcast::RoleBroadcast; use mpstthree::{checker_concat, checker_concat_impl}; use std::error::Error; use mpstthree::functionmpst::close::close_mpst; // Get roles use mpstthree::role::a::RoleA; use mpstthree::role::b::RoleB; use mpstthree::role::c::RoleC; use mpstthree::role::end::RoleEnd; // Get names use mpstthree::name::a::NameA; use mpstthree::name::b::NameB; use mpstthree::name::c::NameC; // Get recv functions use mpstthree::functionmpst::recv::recv_mpst_a_from_b; use mpstthree::functionmpst::recv::recv_mpst_b_from_a; use mpstthree::functionmpst::recv::recv_mpst_b_from_c; use mpstthree::functionmpst::recv::recv_mpst_c_from_b; // Get send functions use mpstthree::functionmpst::send::send_mpst_a_to_b; use mpstthree::functionmpst::send::send_mpst_b_to_a; use mpstthree::functionmpst::send::send_mpst_b_to_c; use mpstthree::functionmpst::send::send_mpst_c_to_b; use mpstthree::choose_mpst_a_to_all; use mpstthree::offer_mpst_b_to_a; use mpstthree::offer_mpst_c_to_a; use petgraph::dot::Dot; // Test our usecase // Simple types // Client = B → Y → A // Authenticator = C → Z → B // Server = A → X → C type BtoAClose = End; type BtoCClose = End; type BtoCVideo = Send>; type BtoAVideo = Recv>; type InitB = Recv>; type CtoBClose = ::Dual; type CtoAClose = End; type CtoBVideo = ::Dual; type RecursBtoA = Recv; type RecursCtoA = Recv; enum Branches0BtoA { End(MeshedChannels), Video(MeshedChannels), } enum Branches0CtoA { End(MeshedChannels), Video(MeshedChannels), } type Choose0fromAtoB = Send; type Choose0fromAtoC = Send; type InitA = Send>; // Stacks type StackBEnd = RoleEnd; type StackBVideo = RoleA>>>>; type StackBRecurs = RoleA; type StackBInit = RoleA>>; type StackCEnd = RoleEnd; type StackCVideo = RoleB>>; type StackCRecurs = RoleA; type StackARecurs = RoleBroadcast; type StackAFull = RoleB>; // Creating the MP sessions // For A type EndpointAEnd = MeshedChannels; type EndpointAVideo = MeshedChannels< Send>>, Send, RoleB>, NameA, >; type EndpointARecurs = MeshedChannels; type EndpointAFull = MeshedChannels; // For B type EndpointBRecurs = MeshedChannels; type EndpointBFull = MeshedChannels; // For C type EndpointCFull = MeshedChannels; // Functions related to endpoints fn server(s: EndpointCFull) -> Result<(), Box> { offer_mpst_c_to_a!(s, { Branches0CtoA::End(s) => { close_mpst(s) }, Branches0CtoA::Video(s) => { let (request, s) = recv_mpst_c_from_b(s)?; let s = send_mpst_c_to_b(request + 1, s); server(s) }, }) } fn authenticator(s: EndpointBFull) -> Result<(), Box> { let (id, s) = recv_mpst_b_from_a(s)?; let s = send_mpst_b_to_a(id + 1, s); authenticator_recurs(s) } fn authenticator_recurs(s: EndpointBRecurs) -> Result<(), Box> { offer_mpst_b_to_a!(s, { Branches0BtoA::End(s) => { close_mpst(s) }, Branches0BtoA::Video(s) => { let (request, s) = recv_mpst_b_from_a(s)?; let s = send_mpst_b_to_c(request + 1, s); let (video, s) = recv_mpst_b_from_c(s)?; let s = send_mpst_b_to_a(video + 1, s); authenticator_recurs(s) }, }) } fn client(s: EndpointAFull) -> Result<(), Box> { let mut rng = thread_rng(); let xs: Vec = (1..100).map(|_| rng.gen()).collect(); let s = send_mpst_a_to_b(0, s); let (_, s) = recv_mpst_a_from_b(s)?; client_recurs(s, xs, 1) } fn client_recurs(s: EndpointARecurs, mut xs: Vec, index: i32) -> Result<(), Box> { match xs.pop() { Option::Some(_) => { let s = choose_mpst_a_to_all!(s, Branches0BtoA::Video, Branches0CtoA::Video); let s = send_mpst_a_to_b(1, s); let (_, s) = recv_mpst_a_from_b(s)?; client_recurs(s, xs, index + 1) } Option::None => { let s = choose_mpst_a_to_all!(s, Branches0BtoA::End, Branches0CtoA::End); assert_eq!(index, 100); close_mpst(s) } } } ///////////////////////////////////////// pub fn run_a_usecase_recursive() { let (thread_a, thread_b, thread_c) = fork_mpst(client, authenticator, server); assert!(thread_a.join().is_ok()); assert!(thread_b.join().is_ok()); assert!(thread_c.join().is_ok()); } checker_concat_impl!( [Branches0BtoA, Video, Branches0CtoA, Video], [Branches0BtoA, End, Branches0CtoA, End] ); pub fn run_a_usecase_recursive_checker() { let (graphs, kmc) = checker_concat!( "", EndpointAFull, EndpointCFull, EndpointBFull => [ EndpointAVideo, Branches0BtoA, Video, Branches0CtoA, Video ], [ EndpointAEnd, Branches0BtoA, End, Branches0CtoA, End ] ) .unwrap(); ////////////// Test graph A let graph_a = &graphs["RoleA"]; assert_eq!( format!("{:?}", Dot::new(&graph_a)), "digraph {\n \ 0 [ label = \"\\\"0\\\"\" ]\n \ 1 [ label = \"\\\"1\\\"\" ]\n \ 2 [ label = \"\\\"2\\\"\" ]\n \ 3 [ label = \"\\\"2.1\\\"\" ]\n \ 4 [ label = \"\\\"2.1\\\"\" ]\n \ 5 [ label = \"\\\"2.2\\\"\" ]\n \ 0 -> 1 [ label = \"\\\"RoleA!RoleB: i32\\\"\" ]\n \ 1 -> 2 [ label = \"\\\"RoleA?RoleB: i32\\\"\" ]\n \ 2 -> 3 [ label = \"\\\"0\\\"\" ]\n \ 2 -> 4 [ label = \"\\\"RoleA!RoleB: i32\\\"\" ]\n \ 4 -> 5 [ label = \"\\\"RoleA?RoleB: i32\\\"\" ]\n \ 5 -> 2 [ label = \"\\\"µ\\\"\" ]\n\ }\n" ); ////////////// Test graph B let graph_b = &graphs["RoleB"]; assert_eq!( format!("{:?}", Dot::new(&graph_b)), "digraph {\n \ 0 [ label = \"\\\"0\\\"\" ]\n \ 1 [ label = \"\\\"1\\\"\" ]\n \ 2 [ label = \"\\\"2\\\"\" ]\n \ 3 [ label = \"\\\"2.1\\\"\" ]\n \ 4 [ label = \"\\\"2.1\\\"\" ]\n \ 5 [ label = \"\\\"2.2\\\"\" ]\n \ 6 [ label = \"\\\"2.3\\\"\" ]\n \ 7 [ label = \"\\\"2.4\\\"\" ]\n \ 0 -> 1 [ label = \"\\\"RoleB?RoleA: i32\\\"\" ]\n \ 1 -> 2 [ label = \"\\\"RoleB!RoleA: i32\\\"\" ]\n \ 2 -> 3 [ label = \"\\\"0\\\"\" ]\n \ 2 -> 4 [ label = \"\\\"RoleB?RoleA: i32\\\"\" ]\n \ 4 -> 5 [ label = \"\\\"RoleB!RoleC: i32\\\"\" ]\n \ 5 -> 6 [ label = \"\\\"RoleB?RoleC: i32\\\"\" ]\n \ 6 -> 7 [ label = \"\\\"RoleB!RoleA: i32\\\"\" ]\n \ 7 -> 2 [ label = \"\\\"µ\\\"\" ]\n\ }\n" ); ////////////// Test graph C let graph_c = &graphs["RoleC"]; assert_eq!( format!("{:?}", Dot::new(&graph_c)), "digraph {\n \ 0 [ label = \"\\\"0\\\"\" ]\n \ 1 [ label = \"\\\"0.1\\\"\" ]\n \ 2 [ label = \"\\\"0.1\\\"\" ]\n \ 3 [ label = \"\\\"0.2\\\"\" ]\n \ 0 -> 1 [ label = \"\\\"0\\\"\" ]\n \ 0 -> 2 [ label = \"\\\"RoleC?RoleB: i32\\\"\" ]\n \ 2 -> 3 [ label = \"\\\"RoleC!RoleB: i32\\\"\" ]\n \ 3 -> 0 [ label = \"\\\"µ\\\"\" ]\n\ }\n" ); ////////////// Test KMC output assert_eq!(kmc, None); }