hyperlane/server/impl.rs
1use crate::*;
2
3/// Provides a default implementation for ServerInner.
4impl Default for ServerInner {
5 /// Creates a new ServerInner instance with default values.
6 ///
7 /// # Returns
8 ///
9 /// - `Self` - A new instance with default configuration.
10 #[inline(always)]
11 fn default() -> Self {
12 Self {
13 config: ServerConfigInner::default(),
14 task_panic: vec![],
15 request_error: vec![],
16 route_matcher: RouteMatcher::new(),
17 request_middleware: vec![],
18 response_middleware: vec![],
19 }
20 }
21}
22
23/// Implements the `PartialEq` trait for `ServerInner`.
24///
25/// This allows for comparing two `ServerInner` instances for equality.
26impl PartialEq for ServerInner {
27 /// Checks if two `ServerInner` instances are equal.
28 ///
29 /// # Arguments
30 ///
31 /// - `&Self`- The other `ServerInner` instance to compare against.
32 ///
33 /// # Returns
34 ///
35 /// - `bool`- `true` if the instances are equal, `false` otherwise.
36 fn eq(&self, other: &Self) -> bool {
37 self.config == other.config
38 && self.route_matcher == other.route_matcher
39 && self.task_panic.len() == other.task_panic.len()
40 && self.request_error.len() == other.request_error.len()
41 && self.request_middleware.len() == other.request_middleware.len()
42 && self.response_middleware.len() == other.response_middleware.len()
43 && self
44 .task_panic
45 .iter()
46 .zip(other.task_panic.iter())
47 .all(|(a, b)| Arc::ptr_eq(a, b))
48 && self
49 .request_error
50 .iter()
51 .zip(other.request_error.iter())
52 .all(|(a, b)| Arc::ptr_eq(a, b))
53 && self
54 .request_middleware
55 .iter()
56 .zip(other.request_middleware.iter())
57 .all(|(a, b)| Arc::ptr_eq(a, b))
58 && self
59 .response_middleware
60 .iter()
61 .zip(other.response_middleware.iter())
62 .all(|(a, b)| Arc::ptr_eq(a, b))
63 }
64}
65
66/// Implements the `Eq` trait for `ServerInner`.
67///
68/// This indicates that `ServerInner` has a total equality relation.
69impl Eq for ServerInner {}
70
71/// Implements the `PartialEq` trait for `Server`.
72///
73/// This allows for comparing two `Server` instances for equality.
74impl PartialEq for Server {
75 /// Checks if two `Server` instances are equal.
76 ///
77 /// # Arguments
78 ///
79 /// - `&Self`- The other `Server` instance to compare against.
80 ///
81 /// # Returns
82 ///
83 /// - `bool`- `true` if the instances are equal, `false` otherwise.
84 #[inline(always)]
85 fn eq(&self, other: &Self) -> bool {
86 if Arc::ptr_eq(self.get_0(), other.get_0()) {
87 return true;
88 }
89 if let (Ok(s), Ok(o)) = (self.get_0().try_read(), other.get_0().try_read()) {
90 *s == *o
91 } else {
92 false
93 }
94 }
95}
96
97/// Implements the `Eq` trait for `Server`.
98///
99/// This indicates that `Server` has a total equality relation.
100impl Eq for Server {}
101
102/// Manages the state for handling a single connection, including the stream and context.
103///
104/// This struct provides a convenient way to pass around the necessary components
105/// for processing a request or WebSocket frame.
106impl HandlerState {
107 /// Creates a new HandlerState instance.
108 ///
109 /// # Arguments
110 ///
111 /// - `&'a ArcRwLockStream` - The network stream.
112 /// - `RequestConfig` - The request config.
113 ///
114 /// # Returns
115 ///
116 /// - `Self` - The newly created hook state.
117 #[inline(always)]
118 pub(super) fn new(stream: ArcRwLockStream, request_config: RequestConfig) -> Self {
119 Self {
120 stream,
121 request_config,
122 }
123 }
124}
125
126/// Represents the server, providing methods to configure and run it.
127///
128/// This struct wraps the `ServerInner` configuration and routing logic,
129/// offering a high-level API for setting up the HTTP and WebSocket server.
130impl Server {
131 /// Creates a new Server instance with default settings.
132 ///
133 /// # Returns
134 ///
135 /// - `Self` - A new Server instance.
136 pub async fn new() -> Self {
137 let server: ServerInner = ServerInner::default();
138 Self(arc_rwlock(server))
139 }
140
141 /// Creates a new Server instance from a configuration.
142 ///
143 /// # Arguments
144 ///
145 /// - `ServerConfig` - The server configuration.
146 ///
147 /// # Returns
148 ///
149 /// - `Self` - A new Server instance.
150 pub async fn from(config: ServerConfig) -> Self {
151 let server: Self = Self::new().await;
152 server.config(config).await;
153 server
154 }
155
156 /// Acquires a read lock on the inner server data.
157 ///
158 /// # Returns
159 ///
160 /// - `ServerStateReadGuard` - The read guard for ServerInner.
161 pub(super) async fn read(&self) -> ServerStateReadGuard<'_> {
162 self.get_0().read().await
163 }
164
165 /// Acquires a write lock on the inner server data.
166 ///
167 /// # Returns
168 ///
169 /// - `ServerStateWriteGuard` - The write guard for ServerInner.
170 async fn write(&self) -> ServerStateWriteGuard<'_> {
171 self.get_0().write().await
172 }
173
174 /// Gets the route matcher.
175 ///
176 /// # Returns
177 /// - `RouteMatcher` - The route matcher.
178 pub async fn get_route_matcher(&self) -> RouteMatcher {
179 self.read().await.get_route_matcher().clone()
180 }
181
182 /// Registers a hook into the server's processing pipeline.
183 ///
184 /// This function dispatches the provided `HookType` to the appropriate
185 /// internal hook collection based on its variant. The hook will be executed
186 /// at the corresponding stage of request processing according to its type:
187 /// - `Panic`: Added to panic handlers for error recovery
188 /// - `RequestError`: Added to request error handlers
189 /// - `RequestMiddleware`: Added to pre-route middleware chain
190 /// - `Route`: Registered as a route handler for the specified path
191 /// - `ResponseMiddleware`: Added to post-route middleware chain
192 ///
193 /// # Arguments
194 ///
195 /// - `HookType` - The `HookType` instance containing the hook configuration and factory.
196 pub async fn handle_hook(&self, hook: HookType) {
197 match hook {
198 HookType::TaskPanic(_, hook) => {
199 self.write().await.get_mut_task_panic().push(hook());
200 }
201 HookType::RequestError(_, hook) => {
202 self.write().await.get_mut_request_error().push(hook());
203 }
204 HookType::RequestMiddleware(_, hook) => {
205 self.write().await.get_mut_request_middleware().push(hook());
206 }
207 HookType::Route(path, hook) => {
208 self.write()
209 .await
210 .get_mut_route_matcher()
211 .add(path, hook())
212 .unwrap();
213 }
214 HookType::ResponseMiddleware(_, hook) => {
215 self.write()
216 .await
217 .get_mut_response_middleware()
218 .push(hook());
219 }
220 };
221 }
222
223 /// Sets the server configuration from a string.
224 ///
225 /// # Arguments
226 ///
227 /// - `C: ToString` - The configuration.
228 ///
229 /// # Returns
230 ///
231 /// - `&Self` - Reference to self for method chaining.
232 pub async fn config_str<C: ToString>(&self, config_str: C) -> &Self {
233 let config: ServerConfig = ServerConfig::from_json_str(&config_str.to_string()).unwrap();
234 self.write().await.set_config(config.get_inner().await);
235 self
236 }
237
238 /// Sets the server configuration.
239 ///
240 /// # Arguments
241 ///
242 /// - `ServerConfig` - The server configuration.
243 ///
244 /// # Returns
245 ///
246 /// - `&Self` - Reference to self for method chaining.
247 pub async fn config(&self, config: ServerConfig) -> &Self {
248 self.write().await.set_config(config.get_inner().await);
249 self
250 }
251
252 /// Registers a task panic handler to the processing pipeline.
253 ///
254 /// This method allows registering task panic handlers that implement the `ServerHook` trait,
255 /// which will be executed when a panic occurs during request processing.
256 ///
257 /// # Type Parameters
258 ///
259 /// - `ServerHook` - The task panic handler type that implements `ServerHook`.
260 ///
261 /// # Returns
262 ///
263 /// - `&Self` - Reference to self for method chaining.
264 pub async fn task_panic<S>(&self) -> &Self
265 where
266 S: ServerHook,
267 {
268 self.write()
269 .await
270 .get_mut_task_panic()
271 .push(server_hook_factory::<S>());
272 self
273 }
274
275 /// Registers a request error handler to the processing pipeline.
276 ///
277 /// This method allows registering request error handlers that implement the `ServerHook` trait,
278 /// which will be executed when a request error occurs during HTTP request processing.
279 ///
280 /// # Type Parameters
281 ///
282 /// - `ServerHook` - The request error handler type that implements `ServerHook`.
283 ///
284 /// # Returns
285 ///
286 /// - `&Self` - Reference to self for method chaining.
287 pub async fn request_error<S>(&self) -> &Self
288 where
289 S: ServerHook,
290 {
291 self.write()
292 .await
293 .get_mut_request_error()
294 .push(server_hook_factory::<S>());
295 self
296 }
297
298 /// Registers a route hook for a specific path.
299 ///
300 /// This method allows registering route handlers that implement the `ServerHook` trait,
301 /// providing type safety and better code organization.
302 ///
303 /// # Type Parameters
304 ///
305 /// - `ServerHook` - The route hook type that implements `ServerHook`.
306 ///
307 /// # Arguments
308 ///
309 /// - `path` - The route path pattern.
310 ///
311 /// # Returns
312 ///
313 /// - `&Self` - Reference to self for method chaining.
314 pub async fn route<S>(&self, path: impl ToString) -> &Self
315 where
316 S: ServerHook,
317 {
318 self.write()
319 .await
320 .get_mut_route_matcher()
321 .add(&path.to_string(), server_hook_factory::<S>())
322 .unwrap();
323 self
324 }
325
326 /// Registers request middleware to the processing pipeline.
327 ///
328 /// This method allows registering middleware that implements the `ServerHook` trait,
329 /// which will be executed before route handlers for every incoming request.
330 ///
331 /// # Type Parameters
332 ///
333 /// - `ServerHook` - The middleware type that implements `ServerHook`.
334 ///
335 /// # Returns
336 ///
337 /// - `&Self` - Reference to self for method chaining.
338 pub async fn request_middleware<S>(&self) -> &Self
339 where
340 S: ServerHook,
341 {
342 self.write()
343 .await
344 .get_mut_request_middleware()
345 .push(server_hook_factory::<S>());
346 self
347 }
348
349 /// Registers response middleware to the processing pipeline.
350 ///
351 /// This method allows registering middleware that implements the `ServerHook` trait,
352 /// which will be executed after route handlers for every outgoing response.
353 ///
354 /// # Type Parameters
355 ///
356 /// - `ServerHook` - The middleware type that implements `ServerHook`.
357 ///
358 /// # Returns
359 ///
360 /// - `&Self` - Reference to self for method chaining.
361 pub async fn response_middleware<S>(&self) -> &Self
362 where
363 S: ServerHook,
364 {
365 self.write()
366 .await
367 .get_mut_response_middleware()
368 .push(server_hook_factory::<S>());
369 self
370 }
371
372 /// Formats the host and port into a bindable address string.
373 ///
374 /// # Arguments
375 ///
376 /// - `H: ToString` - The host address.
377 /// - `u16` - The port number.
378 ///
379 /// # Returns
380 ///
381 /// - `String` - The formatted address string.
382 #[inline(always)]
383 pub fn format_host_port<H: ToString>(host: H, port: u16) -> String {
384 format!("{}{COLON}{port}", host.to_string())
385 }
386
387 /// Flushes the standard output stream.
388 ///
389 /// # Returns
390 ///
391 /// - `io::Result<()>` - The result of the flush operation.
392 #[inline(always)]
393 pub fn try_flush_stdout() -> io::Result<()> {
394 stdout().flush()
395 }
396
397 /// Flushes the standard error stream.
398 ///
399 /// # Panics
400 ///
401 /// This function will panic if the flush operation fails.
402 #[inline(always)]
403 pub fn flush_stdout() {
404 stdout().flush().unwrap();
405 }
406
407 /// Flushes the standard error stream.
408 ///
409 /// # Returns
410 ///
411 /// - `io::Result<()>` - The result of the flush operation.
412 #[inline(always)]
413 pub fn try_flush_stderr() -> io::Result<()> {
414 stderr().flush()
415 }
416
417 /// Flushes the standard error stream.
418 ///
419 /// # Panics
420 ///
421 /// This function will panic if the flush operation fails.
422 #[inline(always)]
423 pub fn flush_stderr() {
424 stderr().flush().unwrap();
425 }
426
427 /// Flushes both the standard output and error streams.
428 ///
429 /// # Returns
430 ///
431 /// - `io::Result<()>` - The result of the flush operation.
432 #[inline(always)]
433 pub fn try_flush_stdout_and_stderr() -> io::Result<()> {
434 Self::try_flush_stdout()?;
435 Self::try_flush_stderr()
436 }
437
438 /// Flushes both the standard output and error streams.
439 ///
440 /// # Panics
441 ///
442 /// This function will panic if either flush operation fails.
443 #[inline(always)]
444 pub fn flush_stdout_and_stderr() {
445 Self::flush_stdout();
446 Self::flush_stderr();
447 }
448
449 /// Handles a panic that has been captured and associated with a specific request `Context`.
450 ///
451 /// This function is invoked when a panic occurs within a task that has access to the request
452 /// context, such as a route hook or middleware. It ensures that the panic information is
453 /// recorded in the `Context` and then passed to the server's configured panic hook for
454 /// processing.
455 ///
456 /// By associating the panic with the context, the hook can access request-specific details
457 /// to provide more meaningful error logging and responses.
458 ///
459 /// # Arguments
460 ///
461 /// - `&Context` - The context of the request during which the panic occurred.
462 /// - `&PanicData` - The captured panic information.
463 async fn handle_panic_with_context(&self, ctx: &Context, panic: &PanicData) {
464 let panic_clone: PanicData = panic.clone();
465 ctx.cancel_aborted().await.set_task_panic(panic_clone).await;
466 for hook in self.read().await.get_task_panic().iter() {
467 Box::pin(self.task_handler(ctx, hook, false)).await;
468 if ctx.get_aborted().await {
469 return;
470 }
471 }
472 }
473
474 /// Handles a panic that occurred within a spawned Tokio task.
475 ///
476 /// It extracts the panic information from the `JoinError` and processes it.
477 ///
478 /// # Arguments
479 ///
480 /// - `&Context` - The context associated with the task.
481 /// - `JoinError` - The `JoinError` returned from the panicked task.
482 async fn handle_task_panic(&self, ctx: &Context, join_error: JoinError) {
483 let panic: PanicData = PanicData::from_join_error(join_error);
484 ctx.set_response_status_code(HttpStatus::InternalServerError.code())
485 .await;
486 self.handle_panic_with_context(ctx, &panic).await;
487 }
488
489 /// Spawns a task handler for a given context and hook.
490 ///
491 /// # Arguments
492 ///
493 /// - `&Context` - The context of the request.
494 /// - `&ServerHookHandler` - The hook to execute.
495 /// - `bool` - Whether to handle panics that occur during execution.
496 async fn task_handler(&self, ctx: &Context, hook: &ServerHookHandler, progress: bool) {
497 if let Err(join_error) = spawn(hook(ctx)).await
498 && join_error.is_panic()
499 {
500 if progress {
501 Box::pin(self.handle_task_panic(ctx, join_error)).await;
502 } else {
503 eprintln!("Panic occurred in panic handler: {:?}", join_error);
504 let _ = Self::try_flush_stdout_and_stderr();
505 }
506 }
507 }
508
509 /// Creates and binds a `TcpListener` based on the server's configuration.
510 ///
511 /// # Returns
512 ///
513 /// - `Result<TcpListener, ServerError>` - A `Result` containing the bound `TcpListener` on success,
514 /// or a `ServerError` on failure.
515 async fn create_tcp_listener(&self) -> Result<TcpListener, ServerError> {
516 let config: ServerConfigInner = self.read().await.get_config().clone();
517 let host: String = config.get_host().clone();
518 let port: u16 = *config.get_port();
519 let addr: String = Self::format_host_port(host, port);
520 TcpListener::bind(&addr)
521 .await
522 .map_err(|error| ServerError::TcpBind(error.to_string()))
523 }
524
525 /// Enters a loop to accept incoming TCP connections and spawn handlers for them.
526 ///
527 /// # Arguments
528 ///
529 /// - `&TcpListener` - A reference to the `TcpListener` to accept connections from.
530 ///
531 /// # Returns
532 ///
533 /// - `Result<(), ServerError>` - A `Result` which is typically `Ok(())` unless an unrecoverable
534 /// error occurs.
535 async fn accept_connections(&self, tcp_listener: &TcpListener) -> Result<(), ServerError> {
536 while let Ok((stream, _socket_addr)) = tcp_listener.accept().await {
537 self.configure_stream(&stream).await;
538 let stream: ArcRwLockStream = ArcRwLockStream::from_stream(stream);
539 self.spawn_connection_handler(stream).await;
540 }
541 Ok(())
542 }
543
544 /// Configures socket options for a newly accepted `TcpStream`.
545 ///
546 /// This applies settings like `TCP_NODELAY`, and `IP_TTL` from the server's configuration.
547 ///
548 /// # Arguments
549 ///
550 /// - `&TcpStream` - A reference to the `TcpStream` to configure.
551 async fn configure_stream(&self, stream: &TcpStream) {
552 let server_inner: ServerStateReadGuard = self.read().await;
553 let config: &ServerConfigInner = server_inner.get_config();
554 if let Some(nodelay) = config.get_nodelay() {
555 let _ = stream.set_nodelay(*nodelay);
556 }
557 if let Some(ttl) = config.get_ttl() {
558 let _ = stream.set_ttl(*ttl);
559 }
560 }
561
562 /// Spawns a new asynchronous task to handle a single client connection.
563 ///
564 /// # Arguments
565 ///
566 /// - `ArcRwLockStream` - The thread-safe stream representing the client connection.
567 async fn spawn_connection_handler(&self, stream: ArcRwLockStream) {
568 let server: Server = self.clone();
569 let request_config: RequestConfig = *self.read().await.get_config().get_request_config();
570 spawn(async move {
571 server.handle_connection(stream, request_config).await;
572 });
573 }
574
575 /// Handles errors that occur while processing HTTP requests.
576 ///
577 /// # Arguments
578 ///
579 /// - `&Context` - The request context.
580 /// - `&RequestError` - The error that occurred.
581 pub async fn handle_request_error(&self, ctx: &Context, error: &RequestError) {
582 ctx.cancel_aborted()
583 .await
584 .set_request_error_data(error.clone())
585 .await;
586 for hook in self.read().await.get_request_error().iter() {
587 self.task_handler(ctx, hook, true).await;
588 if ctx.get_aborted().await {
589 return;
590 }
591 }
592 }
593
594 /// Handles a single client connection, determining whether it's an HTTP or WebSocket request.
595 ///
596 /// It reads the initial request from the stream and dispatches it to the appropriate hook.
597 ///
598 /// # Arguments
599 ///
600 /// - `ArcRwLockStream` - The stream for the client connection.
601 /// - `request_config` - The request config to use for reading the initial HTTP request.
602 async fn handle_connection(&self, stream: ArcRwLockStream, request_config: RequestConfig) {
603 match Request::http_from_stream(&stream, &request_config).await {
604 Ok(request) => {
605 let hook: HandlerState = HandlerState::new(stream, request_config);
606 self.handle_http_requests(&hook, &request).await;
607 }
608 Err(error) => {
609 self.handle_request_error(&stream.into(), &error).await;
610 }
611 }
612 }
613
614 /// The core request handling pipeline.
615 ///
616 /// This function orchestrates the execution of request middleware, the route hook,
617 /// and response middleware. It supports both function-based and trait-based handlers.
618 ///
619 /// # Arguments
620 ///
621 /// - `&HandlerState` - The `HandlerState` for the current connection.
622 /// - `&Request` - The incoming request to be processed.
623 ///
624 /// # Returns
625 ///
626 /// - `bool` - A boolean indicating whether the connection should be kept alive.
627 async fn request_hook(&self, state: &HandlerState, request: &Request) -> bool {
628 let route: &str = request.get_path();
629 let ctx: &Context = &Context::new(state.get_stream(), request);
630 let keep_alive: bool = request.is_enable_keep_alive();
631 if self.handle_request_middleware(ctx).await {
632 return ctx.is_keep_alive(keep_alive).await;
633 }
634 if self.handle_route_matcher(ctx, route).await {
635 return ctx.is_keep_alive(keep_alive).await;
636 }
637 if self.handle_response_middleware(ctx).await {
638 return ctx.is_keep_alive(keep_alive).await;
639 }
640 if let Some(panic) = ctx.try_get_task_panic_data().await {
641 ctx.set_response_status_code(HttpStatus::InternalServerError.code())
642 .await;
643 self.handle_panic_with_context(ctx, &panic).await;
644 }
645 ctx.is_keep_alive(keep_alive).await
646 }
647
648 /// Handles subsequent HTTP requests on a persistent (keep-alive) connection.
649 ///
650 /// # Arguments
651 ///
652 /// - `&HandlerState` - The `HandlerState` for the current connection.
653 /// - `&Request` - The initial request that established the keep-alive connection.
654 async fn handle_http_requests(&self, state: &HandlerState, request: &Request) {
655 if !self.request_hook(state, request).await {
656 return;
657 }
658 let stream: &ArcRwLockStream = state.get_stream();
659 let request_config: &RequestConfig = state.get_request_config();
660 loop {
661 match Request::http_from_stream(stream, request_config).await {
662 Ok(new_request) => {
663 if !self.request_hook(state, &new_request).await {
664 return;
665 }
666 }
667 Err(error) => {
668 self.handle_request_error(&state.get_stream().into(), &error)
669 .await;
670 return;
671 }
672 }
673 }
674 }
675
676 /// Executes trait-based request middleware in sequence.
677 ///
678 /// # Arguments
679 ///
680 /// - `&Context` - The request context.
681 ///
682 /// # Returns
683 ///
684 /// - `bool` - `true` if the lifecycle was aborted, `false` otherwise.
685 pub(super) async fn handle_request_middleware(&self, ctx: &Context) -> bool {
686 for hook in self.read().await.get_request_middleware().iter() {
687 self.task_handler(ctx, hook, true).await;
688 if ctx.get_aborted().await {
689 return true;
690 }
691 }
692 false
693 }
694
695 /// Executes a trait-based route hook if one matches.
696 ///
697 /// # Arguments
698 ///
699 /// - `&Context` - The request context.
700 /// - `&str` - The request path to match.
701 ///
702 /// # Returns
703 ///
704 /// - `bool` - `true` if the lifecycle was aborted, `false` otherwise.
705 pub(super) async fn handle_route_matcher(&self, ctx: &Context, path: &str) -> bool {
706 if let Some(hook) = self
707 .read()
708 .await
709 .get_route_matcher()
710 .try_resolve_route(ctx, path)
711 .await
712 {
713 self.task_handler(ctx, &hook, true).await;
714 if ctx.get_aborted().await {
715 return true;
716 }
717 }
718 false
719 }
720
721 /// Executes trait-based response middleware in sequence.
722 ///
723 /// # Arguments
724 ///
725 /// - `&Context` - The request context.
726 ///
727 /// # Returns
728 ///
729 /// - `bool` - `true` if the lifecycle was aborted, `false` otherwise.
730 pub(super) async fn handle_response_middleware(&self, ctx: &Context) -> bool {
731 for hook in self.read().await.get_response_middleware().iter() {
732 self.task_handler(ctx, hook, true).await;
733 if ctx.get_aborted().await {
734 return true;
735 }
736 }
737 false
738 }
739
740 /// Starts the server, binds to the configured address, and begins listening for connections.
741 ///
742 /// This is the main entry point to launch the server. It will initialize the panic hook,
743 /// create a TCP listener, and then enter the connection acceptance loop in a background task.
744 ///
745 /// # Returns
746 ///
747 /// Returns a `Result` containing a shutdown function on success.
748 /// Calling this function will shut down the server by aborting its main task.
749 /// Returns an error if the server fails to start.
750 pub async fn run(&self) -> Result<ServerControlHook, ServerError> {
751 let tcp_listener: TcpListener = self.create_tcp_listener().await?;
752 let server: Server = self.clone();
753 let (wait_sender, wait_receiver) = channel(());
754 let (shutdown_sender, mut shutdown_receiver) = channel(());
755 let accept_connections: JoinHandle<()> = spawn(async move {
756 let _ = server.accept_connections(&tcp_listener).await;
757 let _ = wait_sender.send(());
758 });
759 let wait_hook: SharedAsyncTaskFactory<()> = Arc::new(move || {
760 let mut wait_receiver_clone: Receiver<()> = wait_receiver.clone();
761 Box::pin(async move {
762 let _ = wait_receiver_clone.changed().await;
763 })
764 });
765 let shutdown_hook: SharedAsyncTaskFactory<()> = Arc::new(move || {
766 let shutdown_sender_clone: Sender<()> = shutdown_sender.clone();
767 Box::pin(async move {
768 let _ = shutdown_sender_clone.send(());
769 })
770 });
771 spawn(async move {
772 let _ = shutdown_receiver.changed().await;
773 accept_connections.abort();
774 });
775 let mut server_control_hook: ServerControlHook = ServerControlHook::default();
776 server_control_hook.set_shutdown_hook(shutdown_hook);
777 server_control_hook.set_wait_hook(wait_hook);
778 Ok(server_control_hook)
779 }
780}