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