1mod acceptor;
2pub mod builder;
3pub mod channel;
4mod dispatch;
5pub mod pubsub_service;
6pub mod service;
7
8#[cfg(feature = "quic")]
9mod quic;
10
11#[cfg(feature = "http")]
12mod http;
13
14use std::{collections::HashMap, sync::Arc, time::Duration};
15
16use log::{debug, error, info};
17
18use karyon_core::{
19 async_runtime::Executor,
20 async_util::{select, timeout, AsyncQueue, Either, TaskGroup, TaskResult},
21};
22
23use karyon_net::{Endpoint, MessageRx, MessageTx};
24
25#[cfg(feature = "ws")]
26use karyon_net::layers::ws::WsLayer;
27#[cfg(feature = "tcp")]
28use karyon_net::tcp::{TcpConfig, TcpListener};
29#[cfg(feature = "tls")]
30use karyon_net::tls::TlsLayer;
31#[cfg(all(feature = "unix", target_family = "unix"))]
32use karyon_net::unix::UnixListener;
33
34use crate::{
35 codec::JsonRpcCodec,
36 error::{Error, Result},
37 message,
38 server::{
39 acceptor::{AsyncAcceptor, StreamAcceptor},
40 channel::NewNotification,
41 },
42};
43
44#[cfg(feature = "ws")]
45use crate::{codec::JsonRpcWsCodec, server::acceptor::WsAcceptor};
46
47pub use builder::ServerBuilder;
48pub use channel::Channel;
49pub use pubsub_service::{PubSubRPCMethod, PubSubRPCService};
50pub use service::{RPCMethod, RPCService};
51
52pub const INVALID_REQUEST_ERROR_MSG: &str = "Invalid request";
53pub const FAILED_TO_PARSE_ERROR_MSG: &str = "Failed to parse";
54pub const METHOD_NOT_FOUND_ERROR_MSG: &str = "Method not found";
55pub const UNSUPPORTED_JSONRPC_VERSION: &str = "Unsupported jsonrpc version";
56
57const CHANNEL_SUBSCRIPTION_BUFFER_SIZE: usize = 100;
58
59const RESPONSE_QUEUE_SIZE: usize = 256;
61
62pub(crate) struct ServerConfig {
63 pub endpoint: Endpoint,
64 #[cfg(feature = "tcp")]
65 pub tcp_config: TcpConfig,
66 #[cfg(feature = "tls")]
67 pub tls_config: Option<karyon_net::tls::ServerTlsConfig>,
68 #[cfg(feature = "quic")]
69 pub quic_config: Option<karyon_net::quic::ServerQuicConfig>,
70 pub services: HashMap<String, Arc<dyn RPCService + 'static>>,
71 pub pubsub_services: HashMap<String, Arc<dyn PubSubRPCService + 'static>>,
72 pub read_timeout: Option<Duration>,
75 #[cfg(any(feature = "tls", feature = "ws"))]
77 pub handshake_timeout: Duration,
78 pub notification_encoder: fn(NewNotification) -> message::Notification,
81}
82
83enum ServerBackend {
86 StreamAcceptor(Arc<dyn AsyncAcceptor>),
87 #[cfg(feature = "quic")]
88 QuicEndpoint(karyon_net::quic::QuicEndpoint),
89 #[cfg(feature = "http")]
90 Http(http::HttpServer),
91}
92
93pub struct Server {
95 backend: ServerBackend,
96 pub(crate) task_group: Arc<TaskGroup>,
97 pub(crate) config: ServerConfig,
98}
99
100impl Server {
101 pub fn start(self: Arc<Self>) {
102 self.task_group.spawn(self.clone().start_block());
103 }
104
105 pub async fn start_block(self: Arc<Self>) -> Result<()> {
106 if let Err(err) = self.accept_loop().await {
107 error!("Main accept loop stopped: {err}");
108 self.shutdown().await;
109 };
110 Ok(())
111 }
112
113 async fn accept_loop(self: &Arc<Self>) -> Result<()> {
114 match &self.backend {
115 ServerBackend::StreamAcceptor(acceptor) => loop {
118 match acceptor.accept().await {
119 Ok(stream) => {
120 let acceptor = acceptor.clone();
121 let server = self.clone();
122 self.task_group.spawn(async move {
123 if let Err(err) = acceptor.handle(stream, &server).await {
124 error!("Handle connection: {err}");
125 }
126 });
127 }
128 Err(err) => error!("Accept connection: {err}"),
129 }
130 },
131 #[cfg(feature = "quic")]
133 ServerBackend::QuicEndpoint(endpoint) => loop {
134 match endpoint.accept_incoming().await {
135 Ok(incoming) => self.handle_quic_incoming(incoming),
136 Err(err) => {
137 error!("Accept QUIC conn: {err}")
138 }
139 }
140 },
141 #[cfg(feature = "http")]
142 ServerBackend::Http(http_server) => {
143 http::accept_loop(self.clone(), http_server).await?;
144 Ok(())
145 }
146 }
147 }
148
149 pub fn local_endpoint(&self) -> Result<Endpoint> {
150 match &self.backend {
151 ServerBackend::StreamAcceptor(acceptor) => acceptor.local_endpoint(),
152 #[cfg(feature = "quic")]
153 ServerBackend::QuicEndpoint(endpoint) => endpoint.local_endpoint().map_err(Error::from),
154 #[cfg(feature = "http")]
155 ServerBackend::Http(http_server) => http_server.local_endpoint(),
156 }
157 }
158
159 pub async fn shutdown(&self) {
160 self.task_group.cancel().await;
161 }
162
163 pub(crate) fn handle_message_conn<R, W>(
167 self: &Arc<Self>,
168 reader: R,
169 writer: W,
170 peer: Option<Endpoint>,
171 ) where
172 R: MessageRx<Message = serde_json::Value> + Send + 'static,
173 W: MessageTx<Message = serde_json::Value> + Send + 'static,
174 {
175 debug!("Handle connection {peer:?}");
176
177 let (ch_tx, ch_rx) = async_channel::bounded(CHANNEL_SUBSCRIPTION_BUFFER_SIZE);
178 let channel = Channel::new(ch_tx);
179 let queue = AsyncQueue::new(RESPONSE_QUEUE_SIZE);
180
181 let writer_chan = channel.clone();
182 self.task_group.spawn_then(
183 stream_writer_task(
184 writer,
185 queue.clone(),
186 ch_rx,
187 self.config.notification_encoder,
188 ),
189 |result: TaskResult<Result<()>>| async move {
190 if let TaskResult::Completed(Err(err)) = result {
191 debug!("Writer stopped: {err}");
192 }
193 writer_chan.close();
194 },
195 );
196
197 let reader_chan = channel.clone();
198 let read_timeout = self.config.read_timeout;
199 self.task_group.spawn_then(
200 stream_reader_task(self.clone(), reader, queue, channel, read_timeout),
201 |result: TaskResult<Result<()>>| async move {
202 if let TaskResult::Completed(Err(err)) = result {
203 debug!("Connection {peer:?} dropped: {err}");
204 } else {
205 debug!("Connection {peer:?} dropped");
206 }
207 reader_chan.close();
208 },
209 );
210 }
211
212 async fn new_request(
213 self: &Arc<Self>,
214 queue: Arc<AsyncQueue<serde_json::Value>>,
215 channel: Arc<Channel>,
216 msg: serde_json::Value,
217 ) {
218 self.task_group.spawn_then(
219 request_task(self.clone(), queue, channel, msg),
220 |result: TaskResult<Result<()>>| async move {
221 if let TaskResult::Completed(Err(err)) = result {
222 error!("Handle request: {err}");
223 }
224 },
225 );
226 }
227
228 pub(super) async fn init<B, W>(
229 config: ServerConfig,
230 ex: Option<Executor>,
231 byte_codec: B,
232 ws_codec: W,
233 ) -> Result<Arc<Self>>
234 where
235 B: JsonRpcCodec,
236 W: WsCodec,
237 {
238 let task_group = Arc::new(match ex {
239 Some(ex) => TaskGroup::with_executor(ex),
240 None => TaskGroup::new(),
241 });
242
243 let backend = create_backend(&config, byte_codec, ws_codec).await?;
244 info!("RPC server listens to the endpoint: {}", config.endpoint);
245
246 Ok(Arc::new(Server {
247 backend,
248 task_group,
249 config,
250 }))
251 }
252}
253
254#[cfg(feature = "ws")]
258pub trait WsCodec: JsonRpcWsCodec {}
259#[cfg(feature = "ws")]
260impl<T: JsonRpcWsCodec> WsCodec for T {}
261
262#[cfg(not(feature = "ws"))]
263pub trait WsCodec: Clone + Send + Sync + 'static {}
264#[cfg(not(feature = "ws"))]
265impl<T: Clone + Send + Sync + 'static> WsCodec for T {}
266
267async fn create_backend<B, W>(
268 config: &ServerConfig,
269 byte_codec: B,
270 ws_codec: W,
271) -> Result<ServerBackend>
272where
273 B: JsonRpcCodec,
274 W: WsCodec,
275{
276 let endpoint = config.endpoint.clone();
277 match endpoint {
278 #[cfg(feature = "http")]
279 Endpoint::Http(..) => {
280 #[cfg(feature = "http3")]
281 let http_server = match config.quic_config.clone() {
282 Some(quic_cfg) => http::HttpServer::new_h3(&endpoint, quic_cfg).await?,
283 None => http::HttpServer::new(&endpoint).await?,
284 };
285 #[cfg(not(feature = "http3"))]
286 let http_server = http::HttpServer::new(&endpoint).await?;
287 Ok(ServerBackend::Http(http_server))
288 }
289 #[cfg(feature = "quic")]
290 Endpoint::Quic(..) => match &config.quic_config {
291 Some(conf) => {
292 let quic_endpoint =
293 karyon_net::quic::QuicEndpoint::listen(&endpoint, conf.clone()).await?;
294 Ok(ServerBackend::QuicEndpoint(quic_endpoint))
295 }
296 None => Err(Error::QUICConfigRequired),
297 },
298 #[cfg(feature = "tcp")]
299 Endpoint::Tcp(..) => {
300 let listener = TcpListener::bind(&endpoint, config.tcp_config.clone()).await?;
301 Ok(ServerBackend::StreamAcceptor(Arc::new(StreamAcceptor {
302 listener: Box::new(listener),
303 codec: byte_codec,
304 #[cfg(feature = "tls")]
305 tls: None,
306 #[cfg(feature = "tls")]
307 handshake_timeout: config.handshake_timeout,
308 })))
309 }
310 #[cfg(feature = "tls")]
311 Endpoint::Tls(..) => {
312 let tls_config = config.tls_config.as_ref().ok_or(Error::TLSConfigRequired)?;
313 let listener = TcpListener::bind(&endpoint, config.tcp_config.clone()).await?;
316 Ok(ServerBackend::StreamAcceptor(Arc::new(StreamAcceptor {
317 listener: Box::new(listener),
318 codec: byte_codec,
319 tls: Some(TlsLayer::server(tls_config.clone())),
320 handshake_timeout: config.handshake_timeout,
321 })))
322 }
323 #[cfg(feature = "ws")]
324 Endpoint::Ws(..) => {
325 let listener = TcpListener::bind(&endpoint, config.tcp_config.clone()).await?;
326 let layer = Arc::new(WsLayer::server(ws_codec));
327 Ok(ServerBackend::StreamAcceptor(Arc::new(WsAcceptor {
328 listener: Box::new(listener),
329 layer,
330 #[cfg(feature = "tls")]
331 tls: None,
332 handshake_timeout: config.handshake_timeout,
333 })))
334 }
335 #[cfg(all(feature = "ws", feature = "tls"))]
336 Endpoint::Wss(..) => {
337 let tls_config = config.tls_config.as_ref().ok_or(Error::TLSConfigRequired)?;
338 let listener = TcpListener::bind(&endpoint, config.tcp_config.clone()).await?;
339 let layer = Arc::new(WsLayer::server(ws_codec));
340 Ok(ServerBackend::StreamAcceptor(Arc::new(WsAcceptor {
341 listener: Box::new(listener),
342 layer,
343 tls: Some(TlsLayer::server(tls_config.clone())),
344 handshake_timeout: config.handshake_timeout,
345 })))
346 }
347 #[cfg(all(feature = "unix", target_family = "unix"))]
348 Endpoint::Unix(..) => {
349 let listener = UnixListener::bind(&endpoint)?;
350 Ok(ServerBackend::StreamAcceptor(Arc::new(StreamAcceptor {
351 listener: Box::new(listener),
352 codec: byte_codec,
353 #[cfg(feature = "tls")]
354 tls: None,
355 #[cfg(feature = "tls")]
356 handshake_timeout: config.handshake_timeout,
357 })))
358 }
359 _ => Err(Error::UnsupportedProtocol(endpoint.to_string())),
360 }
361}
362
363async fn stream_writer_task<W>(
364 mut writer: W,
365 queue: Arc<AsyncQueue<serde_json::Value>>,
366 ch_rx: async_channel::Receiver<NewNotification>,
367 notification_encoder: fn(NewNotification) -> message::Notification,
368) -> Result<()>
369where
370 W: MessageTx<Message = serde_json::Value> + Send,
371{
372 loop {
373 match select(queue.recv(), ch_rx.recv()).await {
374 Either::Left(res) => {
375 writer.send_msg(res).await?;
376 }
377 Either::Right(notification) => {
378 let nt = notification?;
379 let notification = notification_encoder(nt);
380 debug!("--> {notification}");
381 writer.send_msg(serde_json::json!(notification)).await?;
382 }
383 }
384 }
385}
386
387async fn stream_reader_task<R>(
388 server: Arc<Server>,
389 mut reader: R,
390 queue: Arc<AsyncQueue<serde_json::Value>>,
391 channel: Arc<Channel>,
392 read_timeout: Option<Duration>,
393) -> Result<()>
394where
395 R: MessageRx<Message = serde_json::Value> + Send,
396{
397 loop {
398 let msg = match read_timeout {
401 Some(t) => timeout(t, reader.recv_msg()).await??,
402 None => reader.recv_msg().await?,
403 };
404 server
405 .new_request(queue.clone(), channel.clone(), msg)
406 .await;
407 }
408}
409
410async fn request_task(
411 server: Arc<Server>,
412 queue: Arc<AsyncQueue<serde_json::Value>>,
413 channel: Arc<Channel>,
414 msg: serde_json::Value,
415) -> Result<()> {
416 let response = server.handle_request(Some(channel), msg).await;
417 debug!("--> {response}");
418 queue.push(serde_json::json!(response)).await;
419 Ok(())
420}