-
Notifications
You must be signed in to change notification settings - Fork 1k
/
server.rs
117 lines (98 loc) · 3.4 KB
/
server.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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
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 }))
}
}