# Rustypipes [![Crates.io](https://img.shields.io/badge/crates.io-v0.1.1-orange.svg)](https://crates.io/crates/rustypipes) Current Version: 0.1.1 (12/01/2020) Developed by *Christian Visintin* Rustypipes is a Rust library to implement Octopipes clients and servers. ```sh cargo add rustypipes 0.1.1 ``` or ```toml [dependencies] rustypipes = "0.1.1" ``` - [Rustypipes](#rustypipes) - [Client Implementation](#client-implementation) - [Server Implementation](#server-implementation) - [Changelog](#changelog) - [0.1.1 (12/01/2020)](#011-12012020) - [License](#license) The library documentation can be found at --- ## Client Implementation Implementing an Octopipes Client is pretty much simple and requires only the following steps: Initialize the client ```rust let cap_pipe: String = String::from("/tmp/cap.fifo"); let mut client: rustypipes::OctopipesClient = rustypipes::OctopipesClient::new( String::from("myclient-123somerandomchars456"), cap_pipe, rustypipes::OctopipesProtocolVersion::Version1, ); ``` Subscribe to the server ```rust let my_groups: Vec = vec![String::from("myclient"), String::from("BROADCAST")]; match client.subscribe(&my_groups) { Ok(cap_error) => { match cap_error { rustypipes::OctopipesCapError::NoError => { println!("client subscribed (no CAP error)"); }, _ => panic!("client couldn't subscribe, CAP error: {}\n", cap_error) } }, Err(error) => panic!("Error while client was trying to subscribe to server: {}\n", error) } ``` Wait for incoming messages ```rust //Start client loop if let Err(error) = client.loop_start() { panic!("Couldn't start client loop: {}\n", error); } //... //In your main loop loop { //... //Get first available message match client.get_next_message() { Ok(recv) => { match recv { Some(message) => { println!("Received message from {}", message.origin.as_ref().unwrap()); //Handle message... }, None => println!("No message in client's inbox") } }, Err(error) => { panic!("Error while trying to get messages on client: {}\n", error) } } //... } ``` Send a message ```rust let mydata: Vec = vec![0x01, 0x02, 0x03, 0x04]; if let Err(error) = client.send(&String::from("SomeRemote"), mydata) { panic!("Error while trying to send data: {}\n", error); } ``` Then, when you're done, unsubscribe from server and terminate the client ```rust if let Err(error) = client.unsubscribe() { panic!("Error while client was trying to unsubscribe: {}\n", error); } ``` ## Server Implementation Rustypipes is designed to achieve the implementation of an Octopipes Server in the easiest and simplest way possible, saving up time and line of codes to the final developer. Initialize the Server ```rust let cap_pipe: String = String::from("/tmp/cap.fifo"); let client_folder: String = String::from("/tmp/clients/"); let mut server: rustypipes::OctopipesServer = rustypipes::OctopipesServer::new( rustypipes::OctopipesProtocolVersion::Version1, cap_pipe, client_folder, ); ``` Start the CAP listener the CAP listener will just start a thread which will listen on the CAP for new messages, once a new message is received this will be able to be retrieved with cap process functions as we'll see later. ```rust if let Err(error) = server.start_cap_listener() { panic!("Could not start CAP listener: {}", error); } ``` Server Main Loop These two simple functions will handle for you all the tasks the server has to achieve. Try to call this functions often (about each 100ms or less). ```rust loop { //This function will check if there's any message available on the CAP //If there's a message available it will handle the request for you automatically //If a new client subscribed, a new worker will start //If a client unsubscribed, its worker will be stopped //NOTE: process_cap_all can be used too, but cap_once should be preferred if let Err(error) = server.process_cap_once() { println!("Error while processing CAP: {}", error); } //This function will check for each worker if there is any message on their inbox //If a message is found, it'll be dispatched to the clients subscribed to that remote //NOTE: process_first and process_all can be used too, but process_once should be preferred if let Err((fault_client, error)) = server.process_once() { println!("Error while processing client '{}': {}", fault_client, error); } } ``` Terminate the server ```rust if let Err(error) = server.stop_server() { panic!("Could not stop Server: {}\n", error); } //You could also just call, since drop trait is implemented and stop the server gracefully //drop(server); ``` --- ## Changelog ### 0.1.1 (12/01/2020) - Added missing error description for "Write failed" --- ## License ```txt MIT License Copyright (c) 2019-2020 Christian Visintin Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ```