-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathhello_net.rs
89 lines (73 loc) · 2.61 KB
/
hello_net.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
use std::future::Future;
use std::pin::Pin;
use tokio::io::{AsyncReadExt, AsyncWriteExt};
use tokio::net::{TcpListener, TcpStream};
#[derive(thiserror::Error, Debug, serde::Serialize, serde::Deserialize)]
enum MyError {}
struct Service;
impl marpc::RpcService for Service {
type Format = marpc::Json;
}
#[cfg(feature = "client")]
impl marpc::ClientRpcService for Service {
type ClientError = std::io::Error;
fn handle<'a>(
uri: &'static str,
payload: &'a [u8],
) -> Pin<Box<dyn 'a + Future<Output = Result<Vec<u8>, Self::ClientError>>>> {
Box::pin(async move {
let mut stream = TcpStream::connect("127.0.0.1:8080").await?;
let mut uri_buf = [0; 256];
(&mut uri_buf[0..uri.as_bytes().len()]).copy_from_slice(uri.as_bytes());
stream.write_all(&uri_buf).await?;
stream.write_all(payload).await?;
stream.shutdown().await?;
let mut buf = Vec::new();
stream.read_to_end(&mut buf).await?;
Ok(buf)
})
}
}
#[cfg(feature = "server")]
marpc::register_service!(Service with String);
#[cfg(feature = "server")]
async fn server(greeting: String) -> Result<(), Box<dyn std::error::Error>> {
let listener = TcpListener::bind("127.0.0.1:8080").await?;
loop {
let (mut socket, _) = listener.accept().await?;
let mut uri_buf = [0; 256];
socket.read_exact(&mut uri_buf).await?;
let uri = std::str::from_utf8(&uri_buf[0..uri_buf.iter().position(|b| *b == 0).unwrap()])?;
let mut buf = Vec::new();
socket.read_to_end(&mut buf).await?;
let res = marpc::handle_rpc::<Service>(uri, greeting.clone(), &buf).await?;
socket.write_all(&res).await?;
socket.shutdown().await?;
}
}
#[cfg(feature = "client")]
async fn client(name: String) -> Result<(), Box<dyn std::error::Error>> {
let full_greeting = say_hello(name).await?;
println!("{full_greeting}");
Ok(())
}
#[marpc::rpc(SayHello, uri = "/hello", service = Service)]
async fn say_hello(#[server] greeting: String, name: String) -> Result<String, MyError> {
Ok(format!("{greeting} {name}!"))
}
#[tokio::main(flavor = "current_thread")]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let args: Vec<_> = std::env::args().collect();
match &*args[1] {
#[cfg(feature = "client")]
"client" => {
client(args[2].clone()).await?;
}
#[cfg(feature = "server")]
"server" => {
server(args[2].clone()).await?;
}
_ => Err("Must be called as `client` or `server`")?,
}
Ok(())
}