1 use std::convert::TryFrom; 2 use tonic::{ 3 transport::{Endpoint, Server, Uri}, 4 Request, Response, Status, 5 }; 6 use tower::service_fn; 7 8 pub mod hello_world { 9 tonic::include_proto!("helloworld"); 10 } 11 12 use hello_world::{ 13 greeter_client::GreeterClient, 14 greeter_server::{Greeter, GreeterServer}, 15 HelloReply, HelloRequest, 16 }; 17 18 #[tokio::main] 19 async fn main() -> Result<(), Box<dyn std::error::Error>> { 20 let (client, server) = tokio::io::duplex(1024); 21 22 let greeter = MyGreeter::default(); 23 24 tokio::spawn(async move { 25 Server::builder() 26 .add_service(GreeterServer::new(greeter)) 27 .serve_with_incoming(futures::stream::iter(vec![Ok::<_, std::io::Error>(server)])) 28 .await 29 }); 30 31 // Move client to an option so we can _move_ the inner value 32 // on the first attempt to connect. All other attempts will fail. 33 let mut client = Some(client); 34 let channel = Endpoint::try_from("http://[::]:50051")? 35 .connect_with_connector(service_fn(move |_: Uri| { 36 let client = client.take(); 37 38 async move { 39 if let Some(client) = client { 40 Ok(client) 41 } else { 42 Err(std::io::Error::new( 43 std::io::ErrorKind::Other, 44 "Client already taken", 45 )) 46 } 47 } 48 })) 49 .await?; 50 51 let mut client = GreeterClient::new(channel); 52 53 let request = tonic::Request::new(HelloRequest { 54 name: "Tonic".into(), 55 }); 56 57 let response = client.say_hello(request).await?; 58 59 println!("RESPONSE={:?}", response); 60 61 Ok(()) 62 } 63 64 #[derive(Default)] 65 pub struct MyGreeter {} 66 67 #[tonic::async_trait] 68 impl Greeter for MyGreeter { 69 async fn say_hello( 70 &self, 71 request: Request<HelloRequest>, 72 ) -> Result<Response<HelloReply>, Status> { 73 println!("Got a request: {:?}", request); 74 75 let reply = hello_world::HelloReply { 76 message: format!("Hello {}!", request.into_inner().name), 77 }; 78 Ok(Response::new(reply)) 79 } 80 } 81