use mpstthree::binary::struct_trait::{end::End, recv::Recv, send::Send}; use mpstthree::role::broadcast::RoleBroadcast; use mpstthree::role::end::RoleEnd; use mpstthree::{checker_concat, checker_concat_impl, generate}; use rand::{thread_rng, Rng}; use std::error::Error; // Create new MeshedChannels for four participants generate!("rec_and_cancel", MeshedChannels, A, B, C); type AtoCClose = End; type AtoBClose = End; type AtoBVideo = Send>; type AtoCVideo = Recv>; type InitA = Recv>; type BtoAClose = End; type BtoCClose = End; type BtoAVideo = Recv>; type RecursAtoC = Recv; type RecursBtoC = Recv; enum Branches0AtoC { End(MeshedChannels), Video(MeshedChannels), } enum Branches0BtoC { End(MeshedChannels), Video(MeshedChannels), } type Choose0fromCtoA = Send; type Choose0fromCtoB = Send; type InitC = Send>; // Stacks type StackAEnd = RoleEnd; type StackAVideo = RoleC>>>>; type StackARecurs = RoleC; type StackAInit = RoleC>>; type StackBEnd = RoleEnd; type StackBVideo = RoleA>>; type StackBRecurs = RoleC; type StackCRecurs = RoleBroadcast; type StackCFull = RoleA>; // Creating the MP sessions // For C type EndpointCEnd = MeshedChannels; type EndpointCVideo = MeshedChannels< Send>, Choose0fromCtoB, RoleA>, NameC, >; type EndpointCRecurs = MeshedChannels; type EndpointCFull = MeshedChannels; // For A type EndpointARecurs = MeshedChannels; type EndpointAFull = MeshedChannels; // For B type EndpointBRecurs = MeshedChannels; // Functions related to endpoints fn server(s: EndpointBRecurs) -> Result<(), Box> { offer_mpst!(s, { Branches0BtoC::End(s) => { s.close() }, Branches0BtoC::Video(s) => { let (request, s) = s.recv()?; let s = s.send(request + 1)?; server(s) }, }) } fn authenticator(s: EndpointAFull) -> Result<(), Box> { let (id, s) = s.recv()?; let s = s.send(id + 1)?; authenticator_recurs(s) } fn authenticator_recurs(s: EndpointARecurs) -> Result<(), Box> { offer_mpst!(s, { Branches0AtoC::End(s) => { s.close() }, Branches0AtoC::Video(s) => { let (request, s) = s.recv()?; let s = s.send(request + 1)?; let (video, s) = s.recv()?; let s = s.send(video + 1)?; authenticator_recurs(s) }, }) } fn client(s: EndpointCFull) -> Result<(), Box> { let mut rng = thread_rng(); let xs: Vec = (1..100).map(|_| rng.gen()).collect(); let s = s.send(0)?; let (_, s) = s.recv()?; client_recurs(s, xs) } fn client_recurs(s: EndpointCRecurs, mut xs: Vec) -> Result<(), Box> { match xs.pop() { Option::Some(_) => { let s: EndpointCVideo = choose_mpst_c_to_all!(s, Branches0AtoC::Video, Branches0BtoC::Video); let s = s.send(1)?; let (_, s) = s.recv()?; client_recurs(s, xs) } Option::None => { let s: EndpointCEnd = choose_mpst_c_to_all!(s, Branches0AtoC::End, Branches0BtoC::End); s.close() } } } ///////////////////////////////////////// checker_concat_impl!( [Branches0AtoC, Video, Branches0BtoC, Video,], [Branches0AtoC, End, Branches0BtoC, End,] ); // Check for bottom-up approach fn checking() { let _ = checker_concat!( "video_stream", EndpointAFull, EndpointCFull, EndpointBRecurs => [ EndpointCVideo, Branches0AtoC, Video, Branches0BtoC, Video, ], [ EndpointCEnd, Branches0AtoC, End, Branches0BtoC, End, ] ) .unwrap(); } ///////////////////////////////////////// fn main() { checking(); let (thread_a, thread_s, thread_c) = fork_mpst(authenticator, server, client); thread_a.join().unwrap(); thread_s.join().unwrap(); thread_c.join().unwrap(); }