diff --git a/Cargo.toml b/Cargo.toml index 62e12c3b..24149af3 100755 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,9 +7,11 @@ authors = ["ntr "] rand = "0.5.4" uuid = { version = "0.5", features = ["serde", "v4"] } tokio = "0.1" -tokio-io = "0.1" +tokio-core = "0.1" futures = "0.1" bytes = "0.4" serde = "1" serde_derive = "1" serde_cbor = "0.9" +tarpc = "0.12.0" +tarpc-plugins = "0.4.0" diff --git a/README.md b/README.md index d1ec8ef4..6f73373e 100755 --- a/README.md +++ b/README.md @@ -1,5 +1,11 @@ # Cryps ("creeps") // Creeptography +## Setup + +``` +rustup default nightly-2018-06-09-x86_64-unknown-linux-gnu +``` + ## Items ## Rolling diff --git a/src/main.rs b/src/main.rs index 33de0441..5f8cc37a 100755 --- a/src/main.rs +++ b/src/main.rs @@ -1,14 +1,17 @@ +// needed by tarpc until it becomes stable +#![feature(plugin, use_extern_macros, proc_macro_path_invoc)] +#![plugin(tarpc_plugins)] + +extern crate tokio_core; +#[macro_use] extern crate futures; +#[macro_use] extern crate tarpc; + extern crate serde; extern crate serde_cbor; -#[macro_use] -extern crate serde_derive; +#[macro_use] extern crate serde_derive; -extern crate tokio; -extern crate bytes; extern crate rand; extern crate uuid; -#[macro_use] -extern crate futures; mod cryp; mod combat; @@ -16,29 +19,8 @@ mod battle; mod skill; mod net; +use net::server; + fn main() { - -} - -// use tokio::net::TcpListener; -// use tokio::prelude::*; - -// use std::net::SocketAddr; - -// use net::{process}; - -// fn main() { -// let addr = "0.0.0.0:40000".to_string(); -// let addr = addr.parse::().unwrap(); - -// let listener = TcpListener::bind(&addr).unwrap(); -// println!("Listening on: {}", addr); - -// let done = listener.incoming() -// .map_err(|e| println!("failed to accept socket; error = {:?}", e)) -// .for_each(|socket| { -// process(socket) -// }); - -// tokio::run(done); -// } + server() +} \ No newline at end of file diff --git a/src/net.rs b/src/net.rs index df516551..ba85bd37 100644 --- a/src/net.rs +++ b/src/net.rs @@ -1,189 +1,43 @@ -use bytes::{BytesMut, Bytes, BufMut}; -use futures::future::{self, Either}; -use futures::sync::mpsc; -use tokio::io; -use tokio::net::TcpStream; -use tokio::prelude::*; +use futures::Future; +use tarpc::future::{client, server}; +use tarpc::future::client::ClientExt; +use tarpc::util::{FirstSocketAddr, Never}; +use tokio_core::reactor; -use cryp::{Cryp}; -use skill::{Skill}; +service! { + rpc hello(name: String) -> String; +} -// struct Line { -// socket: TcpStream, -// rd: BytesMut, -// wr: BytesMut, -// } +#[derive(Clone)] +struct HelloServer; -// impl Line { -// /// Create a new `lines` codec backed by the socket -// fn new(socket: TcpStream) -> Line { -// Line { -// socket, -// rd: BytesMut::new(), -// wr: BytesMut::new(), -// } -// } +impl FutureService for HelloServer { + type HelloFut = Result; -// /// Buffer a Line. -// /// -// /// This writes the Line to an internal buffer. Calls to `poll_flush` will -// /// attempt to flush this buffer to the socket. -// fn buffer(&mut self, line: &[u8]) { -// // Ensure the buffer has capacity. Ideally this would not be unbounded, -// // but to keep the example simple, we will not limit this. -// self.wr.reserve(line.len()); + fn hello(&self, name: String) -> Self::HelloFut { + Ok(format!("Hello, {}!", name)) + } +} -// // Push the line onto the end of the write buffer. -// // -// // The `put` function is from the `BufMut` trait. -// self.wr.put(line); -// } +pub fn server() { + let mut reactor = reactor::Core::new().unwrap(); + let (mut handle, server) = HelloServer + .listen( + "localhost:10000".first_socket_addr(), + &reactor.handle(), + server::Options::default(), + ) + .unwrap(); + handle.wait(); + reactor.handle().spawn(server); -// /// Flush the write buffer to the socket -// fn poll_flush(&mut self) -> Poll<(), io::Error> { -// // As long as there is buffered data to write, try to write it. -// while !self.wr.is_empty() { -// // Try to write some bytes to the socket -// let n = try_ready!(self.socket.poll_write(&self.wr)); - -// // As long as the wr is not empty, a successful write should -// // never write 0 bytes. -// assert!(n > 0); - -// // This discards the first `n` bytes of the buffer. -// let _ = self.wr.split_to(n); -// } - -// // Buffer is empty, everything written -// Ok(Async::Ready(())) -// } - -// /// Read data from the socket. -// /// -// /// This only returns `Ready` when the socket has closed. -// fn fill_read_buf(&mut self) -> Poll<(), io::Error> { -// loop { -// // Ensure the read buffer has capacity. -// // This might result in an internal allocation. -// self.rd.reserve(1024); - -// // Read data into the buffer. -// let n = try_ready!(self.socket.read_buf(&mut self.rd)); - -// if n == 0 { -// return Ok(Async::Ready(())); -// } -// } -// } -// } - - -// impl Stream for Line { -// type Item = BytesMut; -// type Error = io::Error; - -// fn poll(&mut self) -> Poll, Self::Error> { -// // First, read any new data that might have been received off the socket -// let sock_closed = self.fill_read_buf()?.is_ready(); - -// // Now, try finding line endings -// let pos = self.rd.windows(2).enumerate() -// .find(|&(_, bytes)| bytes == b"\r\n") -// .map(|(i, _)| i); - -// if let Some(pos) = pos { -// // Remove the line from the read buffer and set it to `line`. -// let mut line = self.rd.split_to(pos + 2); - -// // Drop the trailing \r\n -// line.split_off(pos); - -// // Return the line -// return Ok(Async::Ready(Some(line))); -// } - - -// if sock_closed { -// Ok(Async::Ready(None)) -// } else { -// Ok(Async::NotReady) -// } -// } -// } - - -// fn generate() -> Cryp { -// let a = Cryp::new() -// .named("pronounced \"creeep\"".to_string()) -// .level(8) -// .learn(Skill::Stoney) -// .create(); - -// a -// } - -// pub fn process(socket: TcpStream) { -// // Wrap the socket with the `lines` codec that we wrote above. -// // -// // By doing this, we can operate at the Line level instead of doing raw byte -// // manipulation. -// let lines = lines::new(socket); - -// // The first Line is treated as the client's name. The client is not added -// // to the set of connected peers until this Line is received. -// // -// // We use the `into_future` combinator to extract the first item from the -// // lines stream. `into_future` takes a `Stream` and converts it to a future -// // of `(first, rest)` where `rest` is the original stream instance. -// let connection = lines.into_future() -// // `into_future` doesn't have the right error type, so map the error to -// // make it work. -// .map_err(|(e, _)| e) -// // Process the first received Line as the client's name. -// .and_then(|(name, lines)| { -// // If `name` is `None`, then the client disconnected without -// // actually sending a Line of data. -// // -// // Since the connection is closed, there is no further work that we -// // need to do. So, we just terminate processing by returning -// // `future::ok()`. -// // -// // The problem is that only a single future type can be returned -// // from a combinator closure, but we want to return both -// // `future::ok()` and `Peer` (below). -// // -// // This is a common problem, so the `futures` crate solves this by -// // providing the `Either` helper enum that allows creating a single -// // return type that covers two concrete future types. -// let name = match name { -// Some(name) => name, -// None => { -// // The remote client closed the connection without sending -// // any data. -// return Either::A(future::ok(())); -// } -// }; - -// println!("`{:?}` is joining the chat", name); - -// // Create the peer. -// // -// // This is also a future that processes the connection, only -// // completing when the socket closes. -// let peer = Peer::new( -// name, -// state, -// lines); - -// // Wrap `peer` with `Either::B` to make the return type fit. -// Either::B(peer) -// }) -// // Task futures have an error of type `()`, this ensures we handle the -// // error. We do this by printing the error to STDOUT. -// .map_err(|e| { -// println!("connection error = {:?}", e); -// }); - -// // Spawn the task. Internally, this submits the task to a thread pool. -// tokio::spawn(connection); -// } \ No newline at end of file + // let options = client::Options::default().handle(reactor.handle()); + // reactor + // .run( + // FutureClient::connect(handle.addr(), options) + // .map_err(|e| panic!("{:?}", e)) + // .and_then(|client| client.hello("Mom".to_string())) + // .map(|resp| println!("{}", resp)), + // ) + // .unwrap(); +} \ No newline at end of file