itsi-server 0.1.1 → 0.1.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of itsi-server might be problematic. Click here for more details.

Files changed (143) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +5 -0
  3. data/CODE_OF_CONDUCT.md +7 -0
  4. data/Cargo.lock +4417 -0
  5. data/Cargo.toml +7 -0
  6. data/README.md +4 -0
  7. data/Rakefile +8 -1
  8. data/_index.md +6 -0
  9. data/exe/itsi +94 -45
  10. data/ext/itsi_error/Cargo.toml +2 -0
  11. data/ext/itsi_error/src/from.rs +68 -0
  12. data/ext/itsi_error/src/lib.rs +18 -34
  13. data/ext/itsi_error/target/debug/build/clang-sys-da71b0344e568175/out/common.rs +355 -0
  14. data/ext/itsi_error/target/debug/build/clang-sys-da71b0344e568175/out/dynamic.rs +276 -0
  15. data/ext/itsi_error/target/debug/build/clang-sys-da71b0344e568175/out/macros.rs +49 -0
  16. data/ext/itsi_error/target/debug/build/rb-sys-49f554618693db24/out/bindings-0.9.110-mri-arm64-darwin23-3.4.2.rs +8865 -0
  17. data/ext/itsi_error/target/debug/incremental/itsi_error-1mmt5sux7jb0i/s-h510z7m8v9-0bxu7yd.lock +0 -0
  18. data/ext/itsi_error/target/debug/incremental/itsi_error-2vn3jey74oiw0/s-h5113n0e7e-1v5qzs6.lock +0 -0
  19. data/ext/itsi_error/target/debug/incremental/itsi_error-37uv9dicz7awp/s-h510ykifhe-0tbnep2.lock +0 -0
  20. data/ext/itsi_error/target/debug/incremental/itsi_error-37uv9dicz7awp/s-h510yyocpj-0tz7ug7.lock +0 -0
  21. data/ext/itsi_error/target/debug/incremental/itsi_error-37uv9dicz7awp/s-h510z0xc8g-14ol18k.lock +0 -0
  22. data/ext/itsi_error/target/debug/incremental/itsi_error-3g5qf4y7d54uj/s-h5113n0e7d-1trk8on.lock +0 -0
  23. data/ext/itsi_error/target/debug/incremental/itsi_error-3lpfftm45d3e2/s-h510z7m8r3-1pxp20o.lock +0 -0
  24. data/ext/itsi_error/target/debug/incremental/itsi_error-3o4qownhl3d7n/s-h510ykifek-1uxasnk.lock +0 -0
  25. data/ext/itsi_error/target/debug/incremental/itsi_error-3o4qownhl3d7n/s-h510yyocki-11u37qm.lock +0 -0
  26. data/ext/itsi_error/target/debug/incremental/itsi_error-3o4qownhl3d7n/s-h510z0xc93-0pmy0zm.lock +0 -0
  27. data/ext/itsi_instrument_entry/Cargo.toml +15 -0
  28. data/ext/itsi_instrument_entry/src/lib.rs +31 -0
  29. data/ext/itsi_rb_helpers/Cargo.toml +3 -0
  30. data/ext/itsi_rb_helpers/src/heap_value.rs +139 -0
  31. data/ext/itsi_rb_helpers/src/lib.rs +140 -10
  32. data/ext/itsi_rb_helpers/target/debug/build/clang-sys-da71b0344e568175/out/common.rs +355 -0
  33. data/ext/itsi_rb_helpers/target/debug/build/clang-sys-da71b0344e568175/out/dynamic.rs +276 -0
  34. data/ext/itsi_rb_helpers/target/debug/build/clang-sys-da71b0344e568175/out/macros.rs +49 -0
  35. data/ext/itsi_rb_helpers/target/debug/build/rb-sys-eb9ed4ff3a60f995/out/bindings-0.9.110-mri-arm64-darwin23-3.4.2.rs +8865 -0
  36. data/ext/itsi_rb_helpers/target/debug/incremental/itsi_rb_helpers-040pxg6yhb3g3/s-h5113n7a1b-03bwlt4.lock +0 -0
  37. data/ext/itsi_rb_helpers/target/debug/incremental/itsi_rb_helpers-131g1u4dzkt1a/s-h51113xnh3-1eik1ip.lock +0 -0
  38. data/ext/itsi_rb_helpers/target/debug/incremental/itsi_rb_helpers-131g1u4dzkt1a/s-h5111704jj-0g4rj8x.lock +0 -0
  39. data/ext/itsi_rb_helpers/target/debug/incremental/itsi_rb_helpers-1q2d3drtxrzs5/s-h5113n79yl-0bxcqc5.lock +0 -0
  40. data/ext/itsi_rb_helpers/target/debug/incremental/itsi_rb_helpers-374a9h7ovycj0/s-h51113xoox-10de2hp.lock +0 -0
  41. data/ext/itsi_rb_helpers/target/debug/incremental/itsi_rb_helpers-374a9h7ovycj0/s-h5111704w7-0vdq7gq.lock +0 -0
  42. data/ext/itsi_scheduler/Cargo.toml +24 -0
  43. data/ext/itsi_scheduler/src/itsi_scheduler/io_helpers.rs +56 -0
  44. data/ext/itsi_scheduler/src/itsi_scheduler/io_waiter.rs +44 -0
  45. data/ext/itsi_scheduler/src/itsi_scheduler/timer.rs +44 -0
  46. data/ext/itsi_scheduler/src/itsi_scheduler.rs +308 -0
  47. data/ext/itsi_scheduler/src/lib.rs +38 -0
  48. data/ext/itsi_server/Cargo.lock +2956 -0
  49. data/ext/itsi_server/Cargo.toml +73 -13
  50. data/ext/itsi_server/extconf.rb +1 -1
  51. data/ext/itsi_server/src/env.rs +43 -0
  52. data/ext/itsi_server/src/lib.rs +100 -40
  53. data/ext/itsi_server/src/ruby_types/itsi_body_proxy/big_bytes.rs +109 -0
  54. data/ext/itsi_server/src/ruby_types/itsi_body_proxy/mod.rs +141 -0
  55. data/ext/itsi_server/src/ruby_types/itsi_grpc_request.rs +147 -0
  56. data/ext/itsi_server/src/ruby_types/itsi_grpc_response.rs +19 -0
  57. data/ext/itsi_server/src/ruby_types/itsi_grpc_stream/mod.rs +216 -0
  58. data/ext/itsi_server/src/ruby_types/itsi_http_request.rs +282 -0
  59. data/ext/itsi_server/src/ruby_types/itsi_http_response.rs +388 -0
  60. data/ext/itsi_server/src/ruby_types/itsi_server/file_watcher.rs +225 -0
  61. data/ext/itsi_server/src/ruby_types/itsi_server/itsi_server_config.rs +355 -0
  62. data/ext/itsi_server/src/ruby_types/itsi_server.rs +82 -0
  63. data/ext/itsi_server/src/ruby_types/mod.rs +55 -0
  64. data/ext/itsi_server/src/server/bind.rs +75 -31
  65. data/ext/itsi_server/src/server/bind_protocol.rs +37 -0
  66. data/ext/itsi_server/src/server/byte_frame.rs +32 -0
  67. data/ext/itsi_server/src/server/cache_store.rs +74 -0
  68. data/ext/itsi_server/src/server/io_stream.rs +104 -0
  69. data/ext/itsi_server/src/server/itsi_service.rs +172 -0
  70. data/ext/itsi_server/src/server/lifecycle_event.rs +12 -0
  71. data/ext/itsi_server/src/server/listener.rs +332 -132
  72. data/ext/itsi_server/src/server/middleware_stack/middleware.rs +153 -0
  73. data/ext/itsi_server/src/server/middleware_stack/middlewares/allow_list.rs +47 -0
  74. data/ext/itsi_server/src/server/middleware_stack/middlewares/auth_api_key.rs +58 -0
  75. data/ext/itsi_server/src/server/middleware_stack/middlewares/auth_basic.rs +82 -0
  76. data/ext/itsi_server/src/server/middleware_stack/middlewares/auth_jwt.rs +321 -0
  77. data/ext/itsi_server/src/server/middleware_stack/middlewares/cache_control.rs +139 -0
  78. data/ext/itsi_server/src/server/middleware_stack/middlewares/compression.rs +300 -0
  79. data/ext/itsi_server/src/server/middleware_stack/middlewares/cors.rs +287 -0
  80. data/ext/itsi_server/src/server/middleware_stack/middlewares/deny_list.rs +48 -0
  81. data/ext/itsi_server/src/server/middleware_stack/middlewares/error_response.rs +127 -0
  82. data/ext/itsi_server/src/server/middleware_stack/middlewares/etag.rs +191 -0
  83. data/ext/itsi_server/src/server/middleware_stack/middlewares/grpc_service.rs +72 -0
  84. data/ext/itsi_server/src/server/middleware_stack/middlewares/header_interpretation.rs +85 -0
  85. data/ext/itsi_server/src/server/middleware_stack/middlewares/intrusion_protection.rs +195 -0
  86. data/ext/itsi_server/src/server/middleware_stack/middlewares/log_requests.rs +82 -0
  87. data/ext/itsi_server/src/server/middleware_stack/middlewares/mod.rs +82 -0
  88. data/ext/itsi_server/src/server/middleware_stack/middlewares/proxy.rs +216 -0
  89. data/ext/itsi_server/src/server/middleware_stack/middlewares/rate_limit.rs +124 -0
  90. data/ext/itsi_server/src/server/middleware_stack/middlewares/redirect.rs +76 -0
  91. data/ext/itsi_server/src/server/middleware_stack/middlewares/request_headers.rs +43 -0
  92. data/ext/itsi_server/src/server/middleware_stack/middlewares/response_headers.rs +34 -0
  93. data/ext/itsi_server/src/server/middleware_stack/middlewares/ruby_app.rs +93 -0
  94. data/ext/itsi_server/src/server/middleware_stack/middlewares/static_assets.rs +162 -0
  95. data/ext/itsi_server/src/server/middleware_stack/middlewares/string_rewrite.rs +158 -0
  96. data/ext/itsi_server/src/server/middleware_stack/middlewares/token_source.rs +12 -0
  97. data/ext/itsi_server/src/server/middleware_stack/mod.rs +315 -0
  98. data/ext/itsi_server/src/server/mod.rs +15 -2
  99. data/ext/itsi_server/src/server/process_worker.rs +229 -0
  100. data/ext/itsi_server/src/server/rate_limiter.rs +565 -0
  101. data/ext/itsi_server/src/server/request_job.rs +11 -0
  102. data/ext/itsi_server/src/server/serve_strategy/cluster_mode.rs +337 -0
  103. data/ext/itsi_server/src/server/serve_strategy/mod.rs +30 -0
  104. data/ext/itsi_server/src/server/serve_strategy/single_mode.rs +421 -0
  105. data/ext/itsi_server/src/server/signal.rs +93 -0
  106. data/ext/itsi_server/src/server/static_file_server.rs +984 -0
  107. data/ext/itsi_server/src/server/thread_worker.rs +444 -0
  108. data/ext/itsi_server/src/server/tls/locked_dir_cache.rs +132 -0
  109. data/ext/itsi_server/src/server/tls.rs +187 -60
  110. data/ext/itsi_server/src/server/types.rs +43 -0
  111. data/ext/itsi_tracing/Cargo.toml +5 -0
  112. data/ext/itsi_tracing/src/lib.rs +225 -7
  113. data/ext/itsi_tracing/target/debug/incremental/itsi_tracing-0994n8rpvvt9m/s-h510hfz1f6-1kbycmq.lock +0 -0
  114. data/ext/itsi_tracing/target/debug/incremental/itsi_tracing-0bob7bf4yq34i/s-h5113125h5-0lh4rag.lock +0 -0
  115. data/ext/itsi_tracing/target/debug/incremental/itsi_tracing-2fcodulrxbbxo/s-h510h2infk-0hp5kjw.lock +0 -0
  116. data/ext/itsi_tracing/target/debug/incremental/itsi_tracing-2iak63r1woi1l/s-h510h2in4q-0kxfzw1.lock +0 -0
  117. data/ext/itsi_tracing/target/debug/incremental/itsi_tracing-2kk4qj9gn5dg2/s-h5113124kv-0enwon2.lock +0 -0
  118. data/ext/itsi_tracing/target/debug/incremental/itsi_tracing-2mwo0yas7dtw4/s-h510hfz1ha-1udgpei.lock +0 -0
  119. data/lib/itsi/http_request.rb +87 -0
  120. data/lib/itsi/http_response.rb +39 -0
  121. data/lib/itsi/server/Itsi.rb +119 -0
  122. data/lib/itsi/server/config/dsl.rb +506 -0
  123. data/lib/itsi/server/config.rb +131 -0
  124. data/lib/itsi/server/default_app/default_app.rb +38 -0
  125. data/lib/itsi/server/default_app/index.html +91 -0
  126. data/lib/itsi/server/grpc_interface.rb +213 -0
  127. data/lib/itsi/server/rack/handler/itsi.rb +27 -0
  128. data/lib/itsi/server/rack_interface.rb +94 -0
  129. data/lib/itsi/server/scheduler_interface.rb +21 -0
  130. data/lib/itsi/server/scheduler_mode.rb +10 -0
  131. data/lib/itsi/server/signal_trap.rb +29 -0
  132. data/lib/itsi/server/version.rb +1 -1
  133. data/lib/itsi/server.rb +90 -9
  134. data/lib/itsi/standard_headers.rb +86 -0
  135. metadata +122 -31
  136. data/ext/itsi_server/src/request/itsi_request.rs +0 -143
  137. data/ext/itsi_server/src/request/mod.rs +0 -1
  138. data/ext/itsi_server/src/server/itsi_ca/itsi_ca.crt +0 -32
  139. data/ext/itsi_server/src/server/itsi_ca/itsi_ca.key +0 -52
  140. data/ext/itsi_server/src/server/itsi_server.rs +0 -182
  141. data/ext/itsi_server/src/server/transfer_protocol.rs +0 -23
  142. data/ext/itsi_server/src/stream_writer/mod.rs +0 -21
  143. data/lib/itsi/request.rb +0 -39
@@ -1,61 +1,184 @@
1
1
  use super::bind::{Bind, BindAddress};
2
- use super::transfer_protocol::TransferProtocol;
3
- use hyper_util::rt::TokioIo;
4
- use itsi_error::Result;
2
+ use super::bind_protocol::BindProtocol;
3
+ use super::io_stream::IoStream;
4
+ use super::serve_strategy::single_mode::RunningPhase;
5
+ use super::tls::ItsiTlsAcceptor;
6
+ use itsi_error::{ItsiError, Result};
5
7
  use itsi_tracing::info;
6
8
  use socket2::{Domain, Protocol, Socket, Type};
7
- use std::net::{IpAddr, SocketAddr, TcpListener as StdTcpListener};
8
- use std::pin::Pin;
9
+ use std::fmt::Display;
10
+ use std::net::{IpAddr, SocketAddr, TcpListener};
11
+ use std::os::fd::{AsRawFd, FromRawFd, RawFd};
9
12
  use std::sync::Arc;
10
- use std::{os::unix::net::UnixListener as StdUnixListener, path::PathBuf};
11
- use tokio::net::{unix, TcpListener, TcpStream, UnixListener, UnixStream};
13
+ use std::{os::unix::net::UnixListener, path::PathBuf};
14
+ use tokio::net::TcpListener as TokioTcpListener;
15
+ use tokio::net::UnixListener as TokioUnixListener;
16
+ use tokio::net::{unix, TcpStream, UnixStream};
17
+ use tokio::sync::watch::Receiver;
12
18
  use tokio_rustls::TlsAcceptor;
13
-
14
- pub(crate) trait IoStream:
15
- tokio::io::AsyncRead + tokio::io::AsyncWrite + Send + Unpin
16
- {
17
- }
18
- impl<T: tokio::io::AsyncRead + tokio::io::AsyncWrite + Send + Unpin> IoStream for T {}
19
+ use tokio_stream::StreamExt;
20
+ use tracing::error;
19
21
 
20
22
  pub(crate) enum Listener {
21
23
  Tcp(TcpListener),
22
- TcpTls((TcpListener, TlsAcceptor)),
24
+ TcpTls((TcpListener, ItsiTlsAcceptor)),
23
25
  Unix(UnixListener),
24
- UnixTls((UnixListener, TlsAcceptor)),
26
+ UnixTls((UnixListener, ItsiTlsAcceptor)),
25
27
  }
26
28
 
27
- enum Stream {
28
- TcpStream((TcpStream, SocketAddr)),
29
- UnixStream((UnixStream, unix::SocketAddr)),
29
+ pub(crate) enum TokioListener {
30
+ Tcp(TokioTcpListener),
31
+ TcpTls(TokioTcpListener, ItsiTlsAcceptor),
32
+ Unix(TokioUnixListener),
33
+ UnixTls(TokioUnixListener, ItsiTlsAcceptor),
30
34
  }
31
35
 
32
- #[derive(Clone, Debug)]
33
- pub enum SockAddr {
34
- Tcp(Arc<SocketAddr>),
35
- Unix(Arc<unix::SocketAddr>),
36
+ #[derive(Debug, Clone)]
37
+ pub struct ListenerInfo {
38
+ pub host: String,
39
+ pub port: u16,
40
+ pub scheme: String,
36
41
  }
37
- impl std::fmt::Display for SockAddr {
38
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
42
+
43
+ impl TokioListener {
44
+ pub fn listener_info(&self) -> ListenerInfo {
39
45
  match self {
40
- SockAddr::Tcp(socket_addr) => write!(f, "{}", socket_addr.ip().to_canonical()),
41
- SockAddr::Unix(socket_addr) => match socket_addr.as_pathname() {
42
- Some(path) => write!(f, "{:?}", path),
43
- None => write!(f, ""),
46
+ TokioListener::Tcp(listener) => ListenerInfo {
47
+ host: listener
48
+ .local_addr()
49
+ .unwrap()
50
+ .ip()
51
+ .to_canonical()
52
+ .to_string(),
53
+ port: listener.local_addr().unwrap().port(),
54
+ scheme: "http".to_string(),
55
+ },
56
+ TokioListener::TcpTls(listener, _) => ListenerInfo {
57
+ host: listener
58
+ .local_addr()
59
+ .unwrap()
60
+ .ip()
61
+ .to_canonical()
62
+ .to_string(),
63
+ port: listener.local_addr().unwrap().port(),
64
+ scheme: "https".to_string(),
65
+ },
66
+ TokioListener::Unix(listener) => ListenerInfo {
67
+ host: listener
68
+ .local_addr()
69
+ .unwrap()
70
+ .as_pathname()
71
+ .unwrap()
72
+ .to_str()
73
+ .unwrap()
74
+ .to_owned(),
75
+ port: 0,
76
+ scheme: "unix".to_string(),
77
+ },
78
+ TokioListener::UnixTls(listener, _) => ListenerInfo {
79
+ host: listener
80
+ .local_addr()
81
+ .unwrap()
82
+ .as_pathname()
83
+ .unwrap()
84
+ .to_str()
85
+ .unwrap()
86
+ .to_owned(),
87
+ port: 0,
88
+ scheme: "ssl".to_string(),
44
89
  },
45
90
  }
46
91
  }
47
- }
48
92
 
49
- impl Listener {
50
- pub(crate) async fn accept(&self) -> Result<(TokioIo<Pin<Box<dyn IoStream>>>, SockAddr)> {
93
+ pub(crate) async fn accept(&self) -> Result<IoStream> {
51
94
  match self {
52
- Listener::Tcp(listener) => Listener::accept_tcp(listener).await,
53
- Listener::TcpTls((listener, acceptor)) => {
54
- Listener::accept_tls(listener, acceptor).await
95
+ TokioListener::Tcp(listener) => TokioListener::accept_tcp(listener).await,
96
+ TokioListener::TcpTls(listener, acceptor) => {
97
+ TokioListener::accept_tls(listener, acceptor).await
98
+ }
99
+ TokioListener::Unix(listener) => TokioListener::accept_unix(listener).await,
100
+ TokioListener::UnixTls(listener, acceptor) => {
101
+ TokioListener::accept_unix_tls(listener, acceptor).await
102
+ }
103
+ }
104
+ }
105
+
106
+ async fn accept_tcp(listener: &TokioTcpListener) -> Result<IoStream> {
107
+ let tcp_stream = listener.accept().await?;
108
+ Self::to_tokio_io(Stream::TcpStream(tcp_stream), None).await
109
+ }
110
+
111
+ pub async fn spawn_state_task(&self, mut shutdown_receiver: Receiver<RunningPhase>) {
112
+ if let TokioListener::TcpTls(
113
+ _,
114
+ ItsiTlsAcceptor::Automatic(_acme_acceptor, state, _server_config),
115
+ ) = self
116
+ {
117
+ let mut state = state.lock().await;
118
+ loop {
119
+ tokio::select! {
120
+ stream_event = StreamExt::next(&mut *state) => {
121
+ match stream_event {
122
+ Some(event) => info!("ACME Event: {:?}", event),
123
+ None => error!("Received no acme event"),
124
+ }
125
+ },
126
+ _ = shutdown_receiver.changed() => {
127
+ break;
128
+ }
129
+ }
55
130
  }
56
- Listener::Unix(stream) => Listener::accept_unix(stream).await,
57
- Listener::UnixTls((listener, acceptor)) => {
58
- Listener::accept_unix_tls(listener, acceptor).await
131
+ }
132
+ }
133
+
134
+ async fn accept_tls(
135
+ listener: &TokioTcpListener,
136
+ acceptor: &ItsiTlsAcceptor,
137
+ ) -> Result<IoStream> {
138
+ let tcp_stream = listener.accept().await?;
139
+ match acceptor {
140
+ ItsiTlsAcceptor::Manual(tls_acceptor) => {
141
+ Self::to_tokio_io(Stream::TcpStream(tcp_stream), Some(tls_acceptor)).await
142
+ }
143
+ ItsiTlsAcceptor::Automatic(acme_acceptor, _, rustls_config) => {
144
+ let accept_future = acme_acceptor.accept(tcp_stream.0);
145
+ match accept_future.await {
146
+ Ok(None) => Err(ItsiError::Pass()),
147
+ Ok(Some(start_handshake)) => {
148
+ let tls_stream = start_handshake.into_stream(rustls_config.clone()).await?;
149
+ Ok(IoStream::TcpTls {
150
+ stream: tls_stream,
151
+ addr: SockAddr::Tcp(Arc::new(tcp_stream.1)),
152
+ })
153
+ }
154
+ Err(error) => {
155
+ error!(error = format!("{:?}", error));
156
+ Err(ItsiError::Pass())
157
+ }
158
+ }
159
+ }
160
+ }
161
+ }
162
+
163
+ async fn accept_unix(listener: &TokioUnixListener) -> Result<IoStream> {
164
+ let unix_stream = listener.accept().await?;
165
+ Self::to_tokio_io(Stream::UnixStream(unix_stream), None).await
166
+ }
167
+
168
+ async fn accept_unix_tls(
169
+ listener: &TokioUnixListener,
170
+ acceptor: &ItsiTlsAcceptor,
171
+ ) -> Result<IoStream> {
172
+ let unix_stream = listener.accept().await?;
173
+ match acceptor {
174
+ ItsiTlsAcceptor::Manual(tls_acceptor) => {
175
+ Self::to_tokio_io(Stream::UnixStream(unix_stream), Some(tls_acceptor)).await
176
+ }
177
+ ItsiTlsAcceptor::Automatic(_, _, _) => {
178
+ error!("Automatic TLS not supported on Unix sockets");
179
+ Err(ItsiError::UnsupportedProtocol(
180
+ "Automatic TLS on Unix Sockets".to_owned(),
181
+ ))
59
182
  }
60
183
  }
61
184
  }
@@ -63,156 +186,233 @@ impl Listener {
63
186
  async fn to_tokio_io(
64
187
  input_stream: Stream,
65
188
  tls_acceptor: Option<&TlsAcceptor>,
66
- ) -> Result<(TokioIo<Pin<Box<dyn IoStream>>>, SockAddr)> {
189
+ ) -> Result<IoStream> {
67
190
  match tls_acceptor {
68
191
  Some(acceptor) => match input_stream {
69
192
  Stream::TcpStream((tcp_stream, socket_address)) => {
70
193
  match acceptor.accept(tcp_stream).await {
71
- Ok(tls_stream) => Ok((
72
- TokioIo::new(Box::pin(tls_stream) as Pin<Box<dyn IoStream>>),
73
- SockAddr::Tcp(Arc::new(socket_address)),
74
- )),
194
+ Ok(tls_stream) => Ok(IoStream::TcpTls {
195
+ stream: tls_stream,
196
+ addr: SockAddr::Tcp(Arc::new(socket_address)),
197
+ }),
75
198
  Err(err) => Err(err.into()),
76
199
  }
77
200
  }
78
201
  Stream::UnixStream((unix_stream, socket_address)) => {
79
202
  match acceptor.accept(unix_stream).await {
80
- Ok(tls_stream) => Ok((
81
- TokioIo::new(Box::pin(tls_stream) as Pin<Box<dyn IoStream>>),
82
- SockAddr::Unix(Arc::new(socket_address)),
83
- )),
203
+ Ok(tls_stream) => Ok(IoStream::UnixTls {
204
+ stream: tls_stream,
205
+ addr: SockAddr::Unix(Arc::new(socket_address)),
206
+ }),
84
207
  Err(err) => Err(err.into()),
85
208
  }
86
209
  }
87
210
  },
88
211
  None => match input_stream {
89
- Stream::TcpStream((tcp_stream, socket_address)) => Ok((
90
- TokioIo::new(Box::pin(tcp_stream) as Pin<Box<dyn IoStream>>),
91
- SockAddr::Tcp(Arc::new(socket_address)),
92
- )),
93
- Stream::UnixStream((unix_stream, socket_address)) => Ok((
94
- TokioIo::new(Box::pin(unix_stream) as Pin<Box<dyn IoStream>>),
95
- SockAddr::Unix(Arc::new(socket_address)),
96
- )),
212
+ Stream::TcpStream((tcp_stream, socket_address)) => Ok(IoStream::Tcp {
213
+ stream: tcp_stream,
214
+ addr: SockAddr::Tcp(Arc::new(socket_address)),
215
+ }),
216
+ Stream::UnixStream((unix_stream, socket_address)) => Ok(IoStream::Unix {
217
+ stream: unix_stream,
218
+ addr: SockAddr::Unix(Arc::new(socket_address)),
219
+ }),
97
220
  },
98
221
  }
99
222
  }
223
+ }
100
224
 
101
- async fn accept_tcp(
102
- listener: &TcpListener,
103
- ) -> Result<(TokioIo<Pin<Box<dyn IoStream>>>, SockAddr)> {
104
- let tcp_stream = listener.accept().await?;
105
- Self::to_tokio_io(Stream::TcpStream(tcp_stream), None).await
106
- }
107
-
108
- async fn accept_tls(
109
- listener: &TcpListener,
110
- acceptor: &TlsAcceptor,
111
- ) -> Result<(TokioIo<Pin<Box<dyn IoStream>>>, SockAddr)> {
112
- let tcp_stream = listener.accept().await?;
113
- Self::to_tokio_io(Stream::TcpStream(tcp_stream), Some(acceptor)).await
114
- }
225
+ enum Stream {
226
+ TcpStream((TcpStream, SocketAddr)),
227
+ UnixStream((UnixStream, unix::SocketAddr)),
228
+ }
115
229
 
116
- async fn accept_unix(
117
- listener: &UnixListener,
118
- ) -> Result<(TokioIo<Pin<Box<dyn IoStream>>>, SockAddr)> {
119
- let unix_stream = listener.accept().await?;
120
- Self::to_tokio_io(Stream::UnixStream(unix_stream), None).await
230
+ #[derive(Clone, Debug)]
231
+ pub enum SockAddr {
232
+ Tcp(Arc<SocketAddr>),
233
+ Unix(Arc<unix::SocketAddr>),
234
+ }
235
+ impl std::fmt::Display for SockAddr {
236
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
237
+ match self {
238
+ SockAddr::Tcp(socket_addr) => write!(f, "{}", socket_addr.ip().to_canonical()),
239
+ SockAddr::Unix(socket_addr) => match socket_addr.as_pathname() {
240
+ Some(path) => write!(f, "{:?}", path),
241
+ None => write!(f, ""),
242
+ },
243
+ }
121
244
  }
245
+ }
246
+ impl Display for Listener {
247
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
248
+ match self {
249
+ Listener::Tcp(listener) | Listener::TcpTls((listener, _)) => write!(
250
+ f,
251
+ "{}",
252
+ listener
253
+ .local_addr()
254
+ .map(|addr| addr.to_string())
255
+ .unwrap_or_else(|_| "".to_string())
256
+ ),
122
257
 
123
- async fn accept_unix_tls(
124
- listener: &UnixListener,
125
- acceptor: &TlsAcceptor,
126
- ) -> Result<(TokioIo<Pin<Box<dyn IoStream>>>, SockAddr)> {
127
- let unix_stream = listener.accept().await?;
128
- Self::to_tokio_io(Stream::UnixStream(unix_stream), Some(acceptor)).await
258
+ Listener::Unix(listener) | Listener::UnixTls((listener, _)) => write!(
259
+ f,
260
+ "{}",
261
+ listener
262
+ .local_addr()
263
+ .map(|addr| addr
264
+ .as_pathname()
265
+ .map(|path| path.to_str().unwrap_or("").to_owned())
266
+ .unwrap_or_default())
267
+ .unwrap_or_else(|_| "".to_string())
268
+ ),
269
+ }
129
270
  }
271
+ }
130
272
 
131
- pub(crate) fn scheme(&self) -> String {
273
+ impl Listener {
274
+ pub fn into_tokio_listener(self) -> TokioListener {
132
275
  match self {
133
- Listener::Tcp(_) => "http".to_string(),
134
- Listener::TcpTls(_) => "https".to_string(),
135
- Listener::Unix(_) => "http".to_string(),
136
- Listener::UnixTls(_) => "https".to_string(),
276
+ Listener::Tcp(listener) => {
277
+ TokioListener::Tcp(TokioTcpListener::from_std(listener).unwrap())
278
+ }
279
+ Listener::TcpTls((listener, acceptor)) => TokioListener::TcpTls(
280
+ TokioTcpListener::from_std(listener).unwrap(),
281
+ acceptor.clone(),
282
+ ),
283
+ Listener::Unix(listener) => {
284
+ TokioListener::Unix(TokioUnixListener::from_std(listener).unwrap())
285
+ }
286
+ Listener::UnixTls((listener, acceptor)) => TokioListener::UnixTls(
287
+ TokioUnixListener::from_std(listener).unwrap(),
288
+ acceptor.clone(),
289
+ ),
137
290
  }
138
291
  }
139
292
 
140
- pub(crate) fn port(&self) -> u16 {
293
+ /// Handover information when using exec to hand over the listener to a replacement process.
294
+ pub fn handover(&self) -> Result<(String, i32)> {
141
295
  match self {
142
- Listener::Tcp(listener) => listener.local_addr().unwrap().port(),
143
- Listener::TcpTls((listener, _)) => listener.local_addr().unwrap().port(),
144
- Listener::Unix(_) => 0,
145
- Listener::UnixTls(_) => 0,
296
+ Listener::Tcp(listener) => {
297
+ let addr = listener.local_addr()?;
298
+ Ok((
299
+ format!("tcp://{}:{}", addr.ip().to_canonical(), addr.port()),
300
+ listener.as_raw_fd(),
301
+ ))
302
+ }
303
+ Listener::TcpTls((listener, _)) => {
304
+ let addr = listener.local_addr()?;
305
+ Ok((
306
+ format!("tcp://{}:{}", addr.ip().to_canonical(), addr.port()),
307
+ listener.as_raw_fd(),
308
+ ))
309
+ }
310
+ Listener::Unix(listener) => {
311
+ let addr = listener.local_addr()?;
312
+ Ok((
313
+ format!("unix://{}", addr.as_pathname().unwrap().to_str().unwrap()),
314
+ listener.as_raw_fd(),
315
+ ))
316
+ }
317
+ Listener::UnixTls((listener, _)) => {
318
+ let addr = listener.local_addr()?;
319
+ Ok((
320
+ format!("unix://{}", addr.as_pathname().unwrap().to_str().unwrap()),
321
+ listener.as_raw_fd(),
322
+ ))
323
+ }
146
324
  }
147
325
  }
148
326
 
149
- pub(crate) fn host(&self) -> String {
150
- match self {
151
- Listener::Tcp(listener) => listener.local_addr().unwrap().ip().to_string(),
152
- Listener::TcpTls((listener, _)) => listener.local_addr().unwrap().ip().to_string(),
153
- Listener::Unix(_) => "unix".to_string(),
154
- Listener::UnixTls(_) => "unix".to_string(),
155
- }
327
+ pub fn inherit_fd(bind: Bind, fd: RawFd) -> Result<Self> {
328
+ let bound = match bind.address {
329
+ BindAddress::Ip(_) => match bind.protocol {
330
+ BindProtocol::Http => Listener::Tcp(revive_tcp_socket(fd)?),
331
+ BindProtocol::Https => {
332
+ let tcp_listener = revive_tcp_socket(fd)?;
333
+ Listener::TcpTls((tcp_listener, bind.tls_config.unwrap()))
334
+ }
335
+ _ => unreachable!(),
336
+ },
337
+ BindAddress::UnixSocket(_) => match bind.tls_config {
338
+ Some(tls_config) => Listener::UnixTls((revive_unix_socket(fd)?, tls_config)),
339
+ None => Listener::Unix(revive_unix_socket(fd)?),
340
+ },
341
+ };
342
+ Ok(bound)
156
343
  }
157
344
  }
158
345
 
159
- impl From<Bind> for Listener {
160
- fn from(bind: Bind) -> Self {
161
- match bind.address {
346
+ impl TryFrom<Bind> for Listener {
347
+ type Error = itsi_error::ItsiError;
348
+
349
+ fn try_from(bind: Bind) -> std::result::Result<Self, Self::Error> {
350
+ let bound = match bind.address {
162
351
  BindAddress::Ip(addr) => match bind.protocol {
163
- TransferProtocol::Http => Listener::Tcp(
164
- TcpListener::from_std(connect_tcp_socket(addr, bind.port.unwrap())).unwrap(),
165
- ),
166
- TransferProtocol::Https => {
167
- let tcp_listener =
168
- TcpListener::from_std(connect_tcp_socket(addr, bind.port.unwrap()))
169
- .unwrap();
170
- let tls_acceptor = TlsAcceptor::from(Arc::new(bind.tls_config.unwrap()));
171
- Listener::TcpTls((tcp_listener, tls_acceptor))
352
+ BindProtocol::Http => Listener::Tcp(connect_tcp_socket(addr, bind.port.unwrap())?),
353
+ BindProtocol::Https => {
354
+ let tcp_listener = connect_tcp_socket(addr, bind.port.unwrap())?;
355
+ Listener::TcpTls((tcp_listener, bind.tls_config.unwrap()))
172
356
  }
173
357
  _ => unreachable!(),
174
358
  },
175
359
  BindAddress::UnixSocket(path) => match bind.tls_config {
176
- Some(tls_config) => {
177
- let tls_acceptor = TlsAcceptor::from(Arc::new(tls_config));
178
- Listener::UnixTls((
179
- UnixListener::from_std(connect_unix_socket(&path)).unwrap(),
180
- tls_acceptor,
181
- ))
182
- }
183
- None => Listener::Unix(UnixListener::from_std(connect_unix_socket(&path)).unwrap()),
360
+ Some(tls_config) => Listener::UnixTls((connect_unix_socket(&path)?, tls_config)),
361
+ None => Listener::Unix(connect_unix_socket(&path)?),
184
362
  },
185
- }
363
+ };
364
+ Ok(bound)
186
365
  }
187
366
  }
188
367
 
189
- fn connect_tcp_socket(addr: IpAddr, port: u16) -> StdTcpListener {
368
+ fn revive_tcp_socket(fd: RawFd) -> Result<TcpListener> {
369
+ let socket = unsafe { Socket::from_raw_fd(fd) };
370
+ socket.set_reuse_port(true).ok();
371
+ socket.set_reuse_address(true).ok();
372
+ socket.set_nonblocking(true).ok();
373
+ socket.set_nodelay(true).ok();
374
+ socket.set_recv_buffer_size(262_144).ok();
375
+ socket.set_cloexec(true)?;
376
+ socket.listen(1024)?;
377
+ Ok(socket.into())
378
+ }
379
+
380
+ fn revive_unix_socket(fd: RawFd) -> Result<UnixListener> {
381
+ let socket = unsafe { Socket::from_raw_fd(fd) };
382
+ socket.set_nonblocking(true).ok();
383
+ socket.listen(1024)?;
384
+ socket.set_cloexec(true)?;
385
+
386
+ Ok(socket.into())
387
+ }
388
+
389
+ fn connect_tcp_socket(addr: IpAddr, port: u16) -> Result<TcpListener> {
190
390
  let domain = match addr {
191
391
  IpAddr::V4(_) => Domain::IPV4,
192
392
  IpAddr::V6(_) => Domain::IPV6,
193
393
  };
194
- let socket = Socket::new(domain, Type::STREAM, Some(Protocol::TCP)).unwrap();
394
+ let socket = Socket::new(domain, Type::STREAM, Some(Protocol::TCP))?;
195
395
  let socket_address: SocketAddr = SocketAddr::new(addr, port);
196
- socket.set_reuse_address(true).ok();
197
396
  socket.set_reuse_port(true).ok();
397
+ socket.set_reuse_address(true).ok();
198
398
  socket.set_nonblocking(true).ok();
199
399
  socket.set_nodelay(true).ok();
200
- socket.set_recv_buffer_size(1_048_576).ok();
201
- info!("Binding to {}", socket_address);
202
- socket.bind(&socket_address.into()).unwrap();
203
- socket.listen(1024).unwrap();
204
- socket.into()
400
+ socket.set_recv_buffer_size(262_144).ok();
401
+ socket.set_only_v6(false).ok();
402
+ socket.bind(&socket_address.into())?;
403
+ socket.listen(1024)?;
404
+ Ok(socket.into())
205
405
  }
206
406
 
207
- fn connect_unix_socket(path: &PathBuf) -> StdUnixListener {
407
+ fn connect_unix_socket(path: &PathBuf) -> Result<UnixListener> {
208
408
  let _ = std::fs::remove_file(path);
209
- let socket = Socket::new(Domain::UNIX, Type::STREAM, None).unwrap();
409
+ let socket = Socket::new(Domain::UNIX, Type::STREAM, None)?;
210
410
  socket.set_nonblocking(true).ok();
211
- let socket_address = socket2::SockAddr::unix(path).unwrap();
212
411
 
213
- info!("Binding to {:?}", path);
214
- socket.bind(&socket_address).unwrap();
215
- socket.listen(1024).unwrap();
412
+ let socket_address = socket2::SockAddr::unix(path)?;
413
+
414
+ socket.bind(&socket_address)?;
415
+ socket.listen(1024)?;
216
416
 
217
- socket.into()
417
+ Ok(socket.into())
218
418
  }