118 lines
3.4 KiB
Rust
118 lines
3.4 KiB
Rust
pub mod pb {
|
|
tonic::include_proto!("/grpc.examples.unaryecho");
|
|
}
|
|
|
|
use hyper::server::conn::Http;
|
|
use pb::{EchoRequest, EchoResponse};
|
|
use std::sync::Arc;
|
|
use tokio::net::TcpListener;
|
|
use tokio_rustls::{
|
|
rustls::{Certificate, PrivateKey, ServerConfig},
|
|
TlsAcceptor,
|
|
};
|
|
use tonic::{transport::Server, Request, Response, Status};
|
|
use tower_http::ServiceBuilderExt;
|
|
|
|
#[tokio::main]
|
|
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|
let data_dir = std::path::PathBuf::from_iter([std::env!("CARGO_MANIFEST_DIR"), "data"]);
|
|
let certs = {
|
|
let fd = std::fs::File::open(data_dir.join("tls/server.pem"))?;
|
|
let mut buf = std::io::BufReader::new(&fd);
|
|
rustls_pemfile::certs(&mut buf)?
|
|
.into_iter()
|
|
.map(Certificate)
|
|
.collect()
|
|
};
|
|
let key = {
|
|
let fd = std::fs::File::open(data_dir.join("tls/server.key"))?;
|
|
let mut buf = std::io::BufReader::new(&fd);
|
|
rustls_pemfile::pkcs8_private_keys(&mut buf)?
|
|
.into_iter()
|
|
.map(PrivateKey)
|
|
.next()
|
|
.unwrap()
|
|
|
|
// let key = std::fs::read(data_dir.join("tls/server.key"))?;
|
|
// PrivateKey(key)
|
|
};
|
|
|
|
let mut tls = ServerConfig::builder()
|
|
.with_safe_defaults()
|
|
.with_no_client_auth()
|
|
.with_single_cert(certs, key)?;
|
|
tls.alpn_protocols = vec![b"h2".to_vec()];
|
|
|
|
let server = EchoServer::default();
|
|
|
|
let svc = Server::builder()
|
|
.add_service(pb::echo_server::EchoServer::new(server))
|
|
.into_service();
|
|
|
|
let mut http = Http::new();
|
|
http.http2_only(true);
|
|
|
|
let listener = TcpListener::bind("[::1]:50051").await?;
|
|
let tls_acceptor = TlsAcceptor::from(Arc::new(tls));
|
|
|
|
loop {
|
|
let (conn, addr) = match listener.accept().await {
|
|
Ok(incoming) => incoming,
|
|
Err(e) => {
|
|
eprintln!("Error accepting connection: {}", e);
|
|
continue;
|
|
}
|
|
};
|
|
|
|
let http = http.clone();
|
|
let tls_acceptor = tls_acceptor.clone();
|
|
let svc = svc.clone();
|
|
|
|
tokio::spawn(async move {
|
|
let mut certificates = Vec::new();
|
|
|
|
let conn = tls_acceptor
|
|
.accept_with(conn, |info| {
|
|
if let Some(certs) = info.peer_certificates() {
|
|
for cert in certs {
|
|
certificates.push(cert.clone());
|
|
}
|
|
}
|
|
})
|
|
.await
|
|
.unwrap();
|
|
|
|
let svc = tower::ServiceBuilder::new()
|
|
.add_extension(Arc::new(ConnInfo { addr, certificates }))
|
|
.service(svc);
|
|
|
|
http.serve_connection(conn, svc).await.unwrap();
|
|
});
|
|
}
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
struct ConnInfo {
|
|
addr: std::net::SocketAddr,
|
|
certificates: Vec<Certificate>,
|
|
}
|
|
|
|
type EchoResult<T> = Result<Response<T>, Status>;
|
|
|
|
#[derive(Default)]
|
|
pub struct EchoServer;
|
|
|
|
#[tonic::async_trait]
|
|
impl pb::echo_server::Echo for EchoServer {
|
|
async fn unary_echo(&self, request: Request<EchoRequest>) -> EchoResult<EchoResponse> {
|
|
let conn_info = request.extensions().get::<Arc<ConnInfo>>().unwrap();
|
|
println!(
|
|
"Got a request from: {:?} with certs: {:?}",
|
|
conn_info.addr, conn_info.certificates
|
|
);
|
|
|
|
let message = request.into_inner().message;
|
|
Ok(Response::new(EchoResponse { message }))
|
|
}
|
|
}
|