ntex_server/net/
service.rs1use std::fmt;
2
3use ntex_service::{Ctx, Service, cfg::SharedCfg};
4use ntex_util::{HashMap, future::join_all, services::Counter};
5
6use crate::ServerConfiguration;
7
8use super::accept::{AcceptNotify, AcceptorCommand};
9use super::factory::{FactoryServiceType, NetService};
10use super::state::StateFactory;
11use super::{MAX_CONNS_COUNTER, Token, socket::Connection};
12
13pub struct StreamServer<St> {
15 accept: AcceptNotify,
16 state: Box<dyn StateFactory<St> + Send>,
17 services: Vec<FactoryServiceType<St>>,
18}
19
20impl<St: Clone> StreamServer<St> {
21 pub(crate) fn new(
22 accept: AcceptNotify,
23 state: Box<dyn StateFactory<St> + Send>,
24 services: Vec<FactoryServiceType<St>>,
25 ) -> Self {
26 Self {
27 accept,
28 state,
29 services,
30 }
31 }
32}
33
34impl<St> fmt::Debug for StreamServer<St> {
35 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
36 f.debug_struct("StreamServer")
37 .field("services", &self.services.len())
38 .finish()
39 }
40}
41
42impl<St: Clone + 'static> ServerConfiguration for StreamServer<St> {
44 type Item = Connection;
45 type Service = StreamService;
46
47 async fn create(&self) -> Result<Self::Service, &'static str> {
49 let state = self.state.create().await?;
51
52 let mut tokens = HashMap::default();
54 let mut services = Vec::new();
55
56 for info in &self.services {
57 for (svc, _, svc_tokens) in info.create(state.clone()).await? {
58 services.push(svc);
59 let idx = services.len() - 1;
60 for (token, cfg) in &svc_tokens {
61 tokens.insert(*token, (idx, cfg.clone()));
62 }
63 }
64 }
65
66 Ok(StreamService {
67 services,
68 tokens,
69 conns: MAX_CONNS_COUNTER.with(Clone::clone),
70 })
71 }
72
73 fn pause(&self) {
75 self.accept.send(AcceptorCommand::Pause);
76 }
77
78 fn resume(&self) {
80 self.accept.send(AcceptorCommand::Resume);
81 }
82
83 fn terminate(&self) {
85 self.accept.send(AcceptorCommand::Terminate);
86 }
87
88 async fn stop(&self) {
90 let (tx, rx) = oneshot::channel();
91 self.accept.send(AcceptorCommand::Stop(tx));
92 let _ = rx.await;
93 }
94}
95
96impl<St> Clone for StreamServer<St> {
97 fn clone(&self) -> Self {
98 Self {
99 state: self.state.clo(),
100 accept: self.accept.clone(),
101 services: self.services.iter().map(|s| s.clo()).collect(),
102 }
103 }
104}
105
106pub struct StreamService {
107 tokens: HashMap<Token, (usize, SharedCfg)>,
108 services: Vec<Box<dyn NetService>>,
109 conns: Counter,
110}
111
112impl fmt::Debug for StreamService {
113 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
114 f.debug_struct("StreamService")
115 .field("tokens", &self.tokens)
116 .field("conns", &self.conns)
117 .finish()
118 }
119}
120
121impl Service<(), Connection> for StreamService {
122 type Res = ();
123 type Error = ();
124
125 async fn ready(&self, _: Ctx<'_, Self, ()>) -> Result<(), Self::Error> {
126 if !self.conns.is_available() {
127 self.conns.available().await;
128 }
129 for (idx, svc) in self.services.iter().enumerate() {
130 if svc.ready().await.is_err() {
131 for (idx_, cfg) in self.tokens.values() {
132 if idx == *idx_ {
133 log::error!("{}: Service readiness has failed", cfg.tag());
134 break;
135 }
136 }
137 return Err(());
138 }
139 }
140
141 Ok(())
142 }
143
144 async fn shutdown(&self, _: Ctx<'_, Self, ()>) {
145 let _ = join_all(self.services.iter().map(|s| s.shutdown())).await;
146 log::info!(
147 "Worker service shutdown, {} connections",
148 super::num_connections()
149 );
150 }
151
152 #[allow(clippy::unused_async_trait_impl)]
153 async fn call(&self, con: Connection, _: Ctx<'_, Self, ()>) -> Result<(), ()> {
154 if let Some((idx, cfg)) = self.tokens.get(&con.token) {
155 let stream = con.io.convert(cfg.clone()).map_err(|e| {
156 log::error!("Cannot convert to an async io stream: {e}");
157 })?;
158
159 self.services[*idx].call(stream, self.conns.get());
160 Ok(())
161 } else {
162 log::error!("Cannot get handler service for connection: {con:?}");
163 Err(())
164 }
165 }
166}