1use log;
19use std::net::TcpListener;
20use std::sync::{Arc, Mutex};
21use threadpool::ThreadPool;
22
23use thrift::protocol::{
24 TInputProtocol, TInputProtocolFactory, TOutputProtocol, TOutputProtocolFactory,
25};
26use thrift::server::TProcessor;
27use thrift::transport::{TIoChannel, TReadTransportFactory, TWriteTransportFactory};
28use thrift::{ApplicationError, ApplicationErrorKind};
29
30use rustls::ServerSession as RusTLSServerSession;
31use rustls::StreamOwned as RusTLSStream;
32use rustls::{RootCertStore, ServerConfig, ServerSession};
33
34use super::{TLSStream, TLSTTcpChannel, X509Credentials};
35
36type ConnectionHook = fn(TLSStream<ServerSession>);
37
38pub struct TLSTServer<PRC, RTF, IPF, WTF, OPF>
50where
51 PRC: TProcessor + Send + Sync + 'static,
52 RTF: TReadTransportFactory + 'static,
53 IPF: TInputProtocolFactory + 'static,
54 WTF: TWriteTransportFactory + 'static,
55 OPF: TOutputProtocolFactory + 'static,
56{
57 r_trans_factory: RTF,
58 i_proto_factory: IPF,
59 w_trans_factory: WTF,
60 o_proto_factory: OPF,
61 processor: Arc<PRC>,
62 worker_pool: ThreadPool,
63 tls_config: Arc<ServerConfig>,
64 connection_hook: Option<ConnectionHook>,
65}
66
67impl<PRC, RTF, IPF, WTF, OPF> TLSTServer<PRC, RTF, IPF, WTF, OPF>
68where
69 PRC: TProcessor + Send + Sync + 'static,
70 RTF: TReadTransportFactory + 'static,
71 IPF: TInputProtocolFactory + 'static,
72 WTF: TWriteTransportFactory + 'static,
73 OPF: TOutputProtocolFactory + 'static,
74{
75 pub fn new(
90 read_transport_factory: RTF,
91 input_protocol_factory: IPF,
92 write_transport_factory: WTF,
93 output_protocol_factory: OPF,
94 processor: PRC,
95 num_workers: usize,
96 key_pair: X509Credentials,
97 root_cert_store: Option<RootCertStore>,
98 require_client_auth: bool,
99 connection_hook: Option<ConnectionHook>,
100 ) -> TLSTServer<PRC, RTF, IPF, WTF, OPF> {
101 TLSTServer {
102 r_trans_factory: read_transport_factory,
103 i_proto_factory: input_protocol_factory,
104 w_trans_factory: write_transport_factory,
105 o_proto_factory: output_protocol_factory,
106 processor: Arc::new(processor),
107 worker_pool: ThreadPool::with_name("Thrift service processor".to_owned(), num_workers),
108 tls_config: super::make_tls_server_config(
109 key_pair,
110 root_cert_store,
111 require_client_auth,
112 ),
113 connection_hook: connection_hook,
114 }
115 }
116
117 pub fn listen(&mut self, listen_address: &str) -> thrift::Result<()> {
127 let listener = TcpListener::bind(listen_address)?;
128 for stream in listener.incoming() {
129 match stream {
130 Ok(s) => {
131 let tls_session = RusTLSServerSession::new(&self.tls_config);
132 let so = RusTLSStream::new(tls_session, s);
133 let ts = Arc::new(Mutex::new(so));
134 let (i_prot, o_prot) = self.new_protocols_for_connection(ts.clone())?;
135 let processor = self.processor.clone();
136 let ch = self.connection_hook;
137 self.worker_pool.execute(move || {
138 if ch.is_some() {
139 ch.unwrap()(ts)
140 }
141 handle_incoming_connection(processor, i_prot, o_prot)
142 });
143 }
144 Err(e) => {
145 log::warn!("failed to accept remote connection with error {:?}", e);
146 }
147 }
148 }
149
150 Err(thrift::Error::Application(ApplicationError {
151 kind: ApplicationErrorKind::Unknown,
152 message: "aborted listen loop".into(),
153 }))
154 }
155
156 fn new_protocols_for_connection(
157 &mut self,
158 stream: TLSStream<RusTLSServerSession>,
159 ) -> thrift::Result<(
160 Box<dyn TInputProtocol + Send>,
161 Box<dyn TOutputProtocol + Send>,
162 )> {
163 let channel = TLSTTcpChannel::with_stream(stream);
165
166 let (r_chan, w_chan) = channel.split()?;
169
170 let r_tran = self.r_trans_factory.create(Box::new(r_chan));
172 let i_prot = self.i_proto_factory.create(r_tran);
173
174 let w_tran = self.w_trans_factory.create(Box::new(w_chan));
176 let o_prot = self.o_proto_factory.create(w_tran);
177
178 Ok((i_prot, o_prot))
179 }
180}
181
182fn handle_incoming_connection<PRC>(
183 processor: Arc<PRC>,
184 i_prot: Box<dyn TInputProtocol>,
185 o_prot: Box<dyn TOutputProtocol>,
186) where
187 PRC: TProcessor,
188{
189 let mut i_prot = i_prot;
190 let mut o_prot = o_prot;
191 loop {
192 let r = processor.process(&mut *i_prot, &mut *o_prot);
193 if let Err(e) = r {
194 log::debug!("processor completed with error: {:?}", e);
195 break;
196 }
197 }
198}