#![cfg_attr(not(unix), allow(unused_imports))] use futures::stream::TryStreamExt; use std::path::Path; #[cfg(unix)] use tokio::net::UnixListener; use tonic::{transport::Server, Request, Response, Status}; pub mod hello_world { tonic::include_proto!("helloworld"); } use hello_world::{ greeter_server::{Greeter, GreeterServer}, HelloReply, HelloRequest, }; #[derive(Default)] pub struct MyGreeter {} #[tonic::async_trait] impl Greeter for MyGreeter { async fn say_hello( &self, request: Request, ) -> Result, Status> { println!("Got a request: {:?}", request); let reply = hello_world::HelloReply { message: format!("Hello {}!", request.into_inner().name), }; Ok(Response::new(reply)) } } #[cfg(unix)] #[tokio::main] async fn main() -> Result<(), Box> { let path = "/tmp/tonic/helloworld"; tokio::fs::create_dir_all(Path::new(path).parent().unwrap()).await?; let mut uds = UnixListener::bind(path)?; let greeter = MyGreeter::default(); Server::builder() .add_service(GreeterServer::new(greeter)) .serve_with_incoming(uds.incoming().map_ok(unix::UnixStream)) .await?; Ok(()) } #[cfg(unix)] mod unix { use std::{ pin::Pin, task::{Context, Poll}, }; use tokio::io::{AsyncRead, AsyncWrite}; use tonic::transport::server::Connected; #[derive(Debug)] pub struct UnixStream(pub tokio::net::UnixStream); impl Connected for UnixStream {} impl AsyncRead for UnixStream { fn poll_read( mut self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &mut [u8], ) -> Poll> { Pin::new(&mut self.0).poll_read(cx, buf) } } impl AsyncWrite for UnixStream { fn poll_write( mut self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &[u8], ) -> Poll> { Pin::new(&mut self.0).poll_write(cx, buf) } fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { Pin::new(&mut self.0).poll_flush(cx) } fn poll_shutdown( mut self: Pin<&mut Self>, cx: &mut Context<'_>, ) -> Poll> { Pin::new(&mut self.0).poll_shutdown(cx) } } } #[cfg(not(unix))] fn main() { panic!("The `uds` example only works on unix systems!"); }