itsi-scheduler 0.2.22-aarch64-linux

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.
Files changed (149) hide show
  1. checksums.yaml +7 -0
  2. data/.rubocop.yml +8 -0
  3. data/Cargo.lock +997 -0
  4. data/Cargo.toml +7 -0
  5. data/Rakefile +39 -0
  6. data/ext/itsi_acme/Cargo.toml +86 -0
  7. data/ext/itsi_acme/examples/high_level.rs +63 -0
  8. data/ext/itsi_acme/examples/high_level_warp.rs +52 -0
  9. data/ext/itsi_acme/examples/low_level.rs +87 -0
  10. data/ext/itsi_acme/examples/low_level_axum.rs +66 -0
  11. data/ext/itsi_acme/src/acceptor.rs +81 -0
  12. data/ext/itsi_acme/src/acme.rs +354 -0
  13. data/ext/itsi_acme/src/axum.rs +86 -0
  14. data/ext/itsi_acme/src/cache.rs +39 -0
  15. data/ext/itsi_acme/src/caches/boxed.rs +80 -0
  16. data/ext/itsi_acme/src/caches/composite.rs +69 -0
  17. data/ext/itsi_acme/src/caches/dir.rs +106 -0
  18. data/ext/itsi_acme/src/caches/mod.rs +11 -0
  19. data/ext/itsi_acme/src/caches/no.rs +78 -0
  20. data/ext/itsi_acme/src/caches/test.rs +136 -0
  21. data/ext/itsi_acme/src/config.rs +172 -0
  22. data/ext/itsi_acme/src/https_helper.rs +69 -0
  23. data/ext/itsi_acme/src/incoming.rs +142 -0
  24. data/ext/itsi_acme/src/jose.rs +161 -0
  25. data/ext/itsi_acme/src/lib.rs +142 -0
  26. data/ext/itsi_acme/src/resolver.rs +59 -0
  27. data/ext/itsi_acme/src/state.rs +424 -0
  28. data/ext/itsi_error/Cargo.lock +368 -0
  29. data/ext/itsi_error/Cargo.toml +12 -0
  30. data/ext/itsi_error/src/lib.rs +140 -0
  31. data/ext/itsi_instrument_entry/Cargo.toml +15 -0
  32. data/ext/itsi_instrument_entry/src/lib.rs +31 -0
  33. data/ext/itsi_rb_helpers/Cargo.lock +355 -0
  34. data/ext/itsi_rb_helpers/Cargo.toml +11 -0
  35. data/ext/itsi_rb_helpers/src/heap_value.rs +139 -0
  36. data/ext/itsi_rb_helpers/src/lib.rs +232 -0
  37. data/ext/itsi_scheduler/Cargo.toml +24 -0
  38. data/ext/itsi_scheduler/extconf.rb +11 -0
  39. data/ext/itsi_scheduler/src/itsi_scheduler/io_helpers.rs +56 -0
  40. data/ext/itsi_scheduler/src/itsi_scheduler/io_waiter.rs +44 -0
  41. data/ext/itsi_scheduler/src/itsi_scheduler/timer.rs +44 -0
  42. data/ext/itsi_scheduler/src/itsi_scheduler.rs +320 -0
  43. data/ext/itsi_scheduler/src/lib.rs +39 -0
  44. data/ext/itsi_server/Cargo.lock +2956 -0
  45. data/ext/itsi_server/Cargo.toml +94 -0
  46. data/ext/itsi_server/src/default_responses/mod.rs +14 -0
  47. data/ext/itsi_server/src/env.rs +43 -0
  48. data/ext/itsi_server/src/lib.rs +154 -0
  49. data/ext/itsi_server/src/prelude.rs +2 -0
  50. data/ext/itsi_server/src/ruby_types/itsi_body_proxy/big_bytes.rs +116 -0
  51. data/ext/itsi_server/src/ruby_types/itsi_body_proxy/mod.rs +149 -0
  52. data/ext/itsi_server/src/ruby_types/itsi_grpc_call.rs +346 -0
  53. data/ext/itsi_server/src/ruby_types/itsi_grpc_response_stream/mod.rs +265 -0
  54. data/ext/itsi_server/src/ruby_types/itsi_http_request.rs +399 -0
  55. data/ext/itsi_server/src/ruby_types/itsi_http_response.rs +447 -0
  56. data/ext/itsi_server/src/ruby_types/itsi_server/file_watcher.rs +545 -0
  57. data/ext/itsi_server/src/ruby_types/itsi_server/itsi_server_config.rs +650 -0
  58. data/ext/itsi_server/src/ruby_types/itsi_server.rs +102 -0
  59. data/ext/itsi_server/src/ruby_types/mod.rs +48 -0
  60. data/ext/itsi_server/src/server/binds/bind.rs +204 -0
  61. data/ext/itsi_server/src/server/binds/bind_protocol.rs +37 -0
  62. data/ext/itsi_server/src/server/binds/listener.rs +485 -0
  63. data/ext/itsi_server/src/server/binds/mod.rs +4 -0
  64. data/ext/itsi_server/src/server/binds/tls/locked_dir_cache.rs +132 -0
  65. data/ext/itsi_server/src/server/binds/tls.rs +278 -0
  66. data/ext/itsi_server/src/server/byte_frame.rs +32 -0
  67. data/ext/itsi_server/src/server/frame_stream.rs +143 -0
  68. data/ext/itsi_server/src/server/http_message_types.rs +230 -0
  69. data/ext/itsi_server/src/server/io_stream.rs +128 -0
  70. data/ext/itsi_server/src/server/lifecycle_event.rs +12 -0
  71. data/ext/itsi_server/src/server/middleware_stack/middleware.rs +170 -0
  72. data/ext/itsi_server/src/server/middleware_stack/middlewares/allow_list.rs +63 -0
  73. data/ext/itsi_server/src/server/middleware_stack/middlewares/auth_api_key.rs +94 -0
  74. data/ext/itsi_server/src/server/middleware_stack/middlewares/auth_basic.rs +93 -0
  75. data/ext/itsi_server/src/server/middleware_stack/middlewares/auth_jwt.rs +343 -0
  76. data/ext/itsi_server/src/server/middleware_stack/middlewares/cache_control.rs +151 -0
  77. data/ext/itsi_server/src/server/middleware_stack/middlewares/compression.rs +329 -0
  78. data/ext/itsi_server/src/server/middleware_stack/middlewares/cors.rs +300 -0
  79. data/ext/itsi_server/src/server/middleware_stack/middlewares/csp.rs +193 -0
  80. data/ext/itsi_server/src/server/middleware_stack/middlewares/deny_list.rs +64 -0
  81. data/ext/itsi_server/src/server/middleware_stack/middlewares/error_response/default_responses.rs +188 -0
  82. data/ext/itsi_server/src/server/middleware_stack/middlewares/error_response.rs +168 -0
  83. data/ext/itsi_server/src/server/middleware_stack/middlewares/etag.rs +183 -0
  84. data/ext/itsi_server/src/server/middleware_stack/middlewares/header_interpretation.rs +82 -0
  85. data/ext/itsi_server/src/server/middleware_stack/middlewares/intrusion_protection.rs +209 -0
  86. data/ext/itsi_server/src/server/middleware_stack/middlewares/log_requests.rs +133 -0
  87. data/ext/itsi_server/src/server/middleware_stack/middlewares/max_body.rs +47 -0
  88. data/ext/itsi_server/src/server/middleware_stack/middlewares/mod.rs +122 -0
  89. data/ext/itsi_server/src/server/middleware_stack/middlewares/proxy.rs +407 -0
  90. data/ext/itsi_server/src/server/middleware_stack/middlewares/rate_limit.rs +155 -0
  91. data/ext/itsi_server/src/server/middleware_stack/middlewares/redirect.rs +54 -0
  92. data/ext/itsi_server/src/server/middleware_stack/middlewares/request_headers.rs +54 -0
  93. data/ext/itsi_server/src/server/middleware_stack/middlewares/response_headers.rs +51 -0
  94. data/ext/itsi_server/src/server/middleware_stack/middlewares/ruby_app.rs +138 -0
  95. data/ext/itsi_server/src/server/middleware_stack/middlewares/static_assets.rs +269 -0
  96. data/ext/itsi_server/src/server/middleware_stack/middlewares/static_response.rs +62 -0
  97. data/ext/itsi_server/src/server/middleware_stack/middlewares/string_rewrite.rs +218 -0
  98. data/ext/itsi_server/src/server/middleware_stack/middlewares/token_source.rs +31 -0
  99. data/ext/itsi_server/src/server/middleware_stack/mod.rs +381 -0
  100. data/ext/itsi_server/src/server/mod.rs +14 -0
  101. data/ext/itsi_server/src/server/process_worker.rs +247 -0
  102. data/ext/itsi_server/src/server/redirect_type.rs +26 -0
  103. data/ext/itsi_server/src/server/request_job.rs +11 -0
  104. data/ext/itsi_server/src/server/serve_strategy/acceptor.rs +100 -0
  105. data/ext/itsi_server/src/server/serve_strategy/cluster_mode.rs +411 -0
  106. data/ext/itsi_server/src/server/serve_strategy/mod.rs +31 -0
  107. data/ext/itsi_server/src/server/serve_strategy/single_mode.rs +449 -0
  108. data/ext/itsi_server/src/server/signal.rs +129 -0
  109. data/ext/itsi_server/src/server/size_limited_incoming.rs +107 -0
  110. data/ext/itsi_server/src/server/thread_worker.rs +504 -0
  111. data/ext/itsi_server/src/services/cache_store.rs +74 -0
  112. data/ext/itsi_server/src/services/itsi_http_service.rs +270 -0
  113. data/ext/itsi_server/src/services/mime_types.rs +2896 -0
  114. data/ext/itsi_server/src/services/mod.rs +6 -0
  115. data/ext/itsi_server/src/services/password_hasher.rs +89 -0
  116. data/ext/itsi_server/src/services/rate_limiter.rs +609 -0
  117. data/ext/itsi_server/src/services/static_file_server.rs +1400 -0
  118. data/ext/itsi_tracing/Cargo.lock +274 -0
  119. data/ext/itsi_tracing/Cargo.toml +17 -0
  120. data/ext/itsi_tracing/src/lib.rs +370 -0
  121. data/itsi-scheduler-100.png +0 -0
  122. data/lib/itsi/schedule_refinement.rb +96 -0
  123. data/lib/itsi/scheduler/3.1/itsi_scheduler.so +0 -0
  124. data/lib/itsi/scheduler/3.2/itsi_scheduler.so +0 -0
  125. data/lib/itsi/scheduler/3.3/itsi_scheduler.so +0 -0
  126. data/lib/itsi/scheduler/3.4/itsi_scheduler.so +0 -0
  127. data/lib/itsi/scheduler/4.0/itsi_scheduler.so +0 -0
  128. data/lib/itsi/scheduler/native_extension.rb +34 -0
  129. data/lib/itsi/scheduler/version.rb +7 -0
  130. data/lib/itsi/scheduler.rb +153 -0
  131. data/vendor/rb-sys-build/.cargo-ok +1 -0
  132. data/vendor/rb-sys-build/.cargo_vcs_info.json +6 -0
  133. data/vendor/rb-sys-build/Cargo.lock +294 -0
  134. data/vendor/rb-sys-build/Cargo.toml +71 -0
  135. data/vendor/rb-sys-build/Cargo.toml.orig +32 -0
  136. data/vendor/rb-sys-build/LICENSE-APACHE +190 -0
  137. data/vendor/rb-sys-build/LICENSE-MIT +21 -0
  138. data/vendor/rb-sys-build/src/bindings/sanitizer.rs +185 -0
  139. data/vendor/rb-sys-build/src/bindings/stable_api.rs +247 -0
  140. data/vendor/rb-sys-build/src/bindings/wrapper.h +71 -0
  141. data/vendor/rb-sys-build/src/bindings.rs +280 -0
  142. data/vendor/rb-sys-build/src/cc.rs +421 -0
  143. data/vendor/rb-sys-build/src/lib.rs +12 -0
  144. data/vendor/rb-sys-build/src/rb_config/flags.rs +101 -0
  145. data/vendor/rb-sys-build/src/rb_config/library.rs +132 -0
  146. data/vendor/rb-sys-build/src/rb_config/search_path.rs +57 -0
  147. data/vendor/rb-sys-build/src/rb_config.rs +906 -0
  148. data/vendor/rb-sys-build/src/utils.rs +53 -0
  149. metadata +210 -0
@@ -0,0 +1,485 @@
1
+ use crate::prelude::*;
2
+ use crate::ruby_types::itsi_server::itsi_server_config::SocketOpts;
3
+ use crate::server::io_stream::IoStream;
4
+ use crate::server::serve_strategy::single_mode::RunningPhase;
5
+
6
+ use super::bind::{Bind, BindAddress};
7
+ use super::bind_protocol::BindProtocol;
8
+
9
+ use super::tls::ItsiTlsAcceptor;
10
+ use itsi_error::{ItsiError, Result};
11
+ use itsi_tracing::info;
12
+ use socket2::{Domain, Protocol, SockRef, Socket, Type};
13
+ use std::fmt::Display;
14
+ use std::net::{IpAddr, SocketAddr, TcpListener};
15
+ use std::os::fd::{AsRawFd, FromRawFd, RawFd};
16
+ use std::sync::Arc;
17
+ use std::{os::unix::net::UnixListener, path::PathBuf};
18
+ use tokio::net::TcpListener as TokioTcpListener;
19
+ use tokio::net::UnixListener as TokioUnixListener;
20
+ use tokio::net::{unix, TcpStream, UnixStream};
21
+ use tokio::sync::watch::Receiver;
22
+ use tokio_rustls::TlsAcceptor;
23
+ use tokio_stream::StreamExt;
24
+
25
+ pub(crate) enum Listener {
26
+ Tcp(TcpListener),
27
+ TcpTls((TcpListener, ItsiTlsAcceptor)),
28
+ Unix(UnixListener),
29
+ UnixTls((UnixListener, ItsiTlsAcceptor)),
30
+ }
31
+
32
+ pub(crate) enum TokioListener {
33
+ Tcp(TokioTcpListener),
34
+ TcpTls(TokioTcpListener, ItsiTlsAcceptor),
35
+ Unix(TokioUnixListener),
36
+ UnixTls(TokioUnixListener, ItsiTlsAcceptor),
37
+ }
38
+
39
+ #[derive(Debug, Clone)]
40
+ pub struct ListenerInfo {
41
+ pub host: String,
42
+ pub port: u16,
43
+ pub scheme: String,
44
+ }
45
+
46
+ impl TokioListener {
47
+ pub fn listener_info(&self) -> ListenerInfo {
48
+ match self {
49
+ TokioListener::Tcp(listener) => ListenerInfo {
50
+ host: listener
51
+ .local_addr()
52
+ .unwrap()
53
+ .ip()
54
+ .to_canonical()
55
+ .to_string(),
56
+ port: listener.local_addr().unwrap().port(),
57
+ scheme: "http".to_string(),
58
+ },
59
+ TokioListener::TcpTls(listener, _) => ListenerInfo {
60
+ host: listener
61
+ .local_addr()
62
+ .unwrap()
63
+ .ip()
64
+ .to_canonical()
65
+ .to_string(),
66
+ port: listener.local_addr().unwrap().port(),
67
+ scheme: "https".to_string(),
68
+ },
69
+ TokioListener::Unix(listener) => ListenerInfo {
70
+ host: listener
71
+ .local_addr()
72
+ .unwrap()
73
+ .as_pathname()
74
+ .unwrap()
75
+ .to_str()
76
+ .unwrap()
77
+ .to_owned(),
78
+ port: 0,
79
+ scheme: "unix".to_string(),
80
+ },
81
+ TokioListener::UnixTls(listener, _) => ListenerInfo {
82
+ host: listener
83
+ .local_addr()
84
+ .unwrap()
85
+ .as_pathname()
86
+ .unwrap()
87
+ .to_str()
88
+ .unwrap()
89
+ .to_owned(),
90
+ port: 0,
91
+ scheme: "ssl".to_string(),
92
+ },
93
+ }
94
+ }
95
+
96
+ pub(crate) async fn accept(&self) -> Result<IoStream> {
97
+ match self {
98
+ TokioListener::Tcp(listener) => TokioListener::accept_tcp(listener).await,
99
+ TokioListener::TcpTls(listener, acceptor) => {
100
+ TokioListener::accept_tls(listener, acceptor).await
101
+ }
102
+ TokioListener::Unix(listener) => TokioListener::accept_unix(listener).await,
103
+ TokioListener::UnixTls(listener, acceptor) => {
104
+ TokioListener::accept_unix_tls(listener, acceptor).await
105
+ }
106
+ }
107
+ }
108
+
109
+ async fn accept_tcp(listener: &TokioTcpListener) -> Result<IoStream> {
110
+ let tcp_stream = listener.accept().await?;
111
+ Self::to_tokio_io(Stream::TcpStream(tcp_stream), None).await
112
+ }
113
+
114
+ pub async fn spawn_acme_event_task(&self, mut shutdown_receiver: Receiver<RunningPhase>) {
115
+ if let TokioListener::TcpTls(
116
+ _,
117
+ ItsiTlsAcceptor::Automatic(_acme_acceptor, state, _server_config),
118
+ ) = self
119
+ {
120
+ let mut state = state.lock().await;
121
+ loop {
122
+ tokio::select! {
123
+ stream_event = StreamExt::next(&mut *state) => {
124
+ match stream_event {
125
+ Some(event) => info!("ACME Event: {:?}", event),
126
+ None => error!("Received no acme event"),
127
+ }
128
+ },
129
+ _ = shutdown_receiver.changed() => {
130
+ break;
131
+ }
132
+ }
133
+ }
134
+ }
135
+ }
136
+
137
+ async fn accept_tls(
138
+ listener: &TokioTcpListener,
139
+ acceptor: &ItsiTlsAcceptor,
140
+ ) -> Result<IoStream> {
141
+ let tcp_stream = listener.accept().await?;
142
+ match acceptor {
143
+ ItsiTlsAcceptor::Manual(tls_acceptor) => {
144
+ Self::to_tokio_io(Stream::TcpStream(tcp_stream), Some(tls_acceptor)).await
145
+ }
146
+ ItsiTlsAcceptor::Automatic(acme_acceptor, _, rustls_config) => {
147
+ let accept_future = acme_acceptor.accept(tcp_stream.0);
148
+ match accept_future.await {
149
+ Ok(None) => Err(ItsiError::Pass),
150
+ Ok(Some(start_handshake)) => {
151
+ let tls_stream = start_handshake.into_stream(rustls_config.clone()).await?;
152
+ Ok(IoStream::TcpTls {
153
+ stream: tls_stream,
154
+ addr: SockAddr::Tcp(Arc::new(tcp_stream.1)),
155
+ })
156
+ }
157
+ Err(error) => {
158
+ error!(error = format!("{:?}", error));
159
+ Err(ItsiError::Pass)
160
+ }
161
+ }
162
+ }
163
+ }
164
+ }
165
+
166
+ async fn accept_unix(listener: &TokioUnixListener) -> Result<IoStream> {
167
+ let unix_stream = listener.accept().await?;
168
+ Self::to_tokio_io(Stream::UnixStream(unix_stream), None).await
169
+ }
170
+
171
+ async fn accept_unix_tls(
172
+ listener: &TokioUnixListener,
173
+ acceptor: &ItsiTlsAcceptor,
174
+ ) -> Result<IoStream> {
175
+ let unix_stream = listener.accept().await?;
176
+ match acceptor {
177
+ ItsiTlsAcceptor::Manual(tls_acceptor) => {
178
+ Self::to_tokio_io(Stream::UnixStream(unix_stream), Some(tls_acceptor)).await
179
+ }
180
+ ItsiTlsAcceptor::Automatic(_, _, _) => {
181
+ error!("Automatic TLS not supported on Unix sockets");
182
+ Err(ItsiError::UnsupportedProtocol(
183
+ "Automatic TLS on Unix Sockets".to_owned(),
184
+ ))
185
+ }
186
+ }
187
+ }
188
+
189
+ async fn to_tokio_io(
190
+ input_stream: Stream,
191
+ tls_acceptor: Option<&TlsAcceptor>,
192
+ ) -> Result<IoStream> {
193
+ match tls_acceptor {
194
+ Some(acceptor) => match input_stream {
195
+ Stream::TcpStream((tcp_stream, socket_address)) => {
196
+ match acceptor.accept(tcp_stream).await {
197
+ Ok(tls_stream) => Ok(IoStream::TcpTls {
198
+ stream: tls_stream,
199
+ addr: SockAddr::Tcp(Arc::new(socket_address)),
200
+ }),
201
+ Err(err) => Err(err.into()),
202
+ }
203
+ }
204
+ Stream::UnixStream((unix_stream, socket_address)) => {
205
+ match acceptor.accept(unix_stream).await {
206
+ Ok(tls_stream) => Ok(IoStream::UnixTls {
207
+ stream: tls_stream,
208
+ addr: SockAddr::Unix(Arc::new(socket_address)),
209
+ }),
210
+ Err(err) => Err(err.into()),
211
+ }
212
+ }
213
+ },
214
+ None => match input_stream {
215
+ Stream::TcpStream((tcp_stream, socket_address)) => Ok(IoStream::Tcp {
216
+ stream: tcp_stream,
217
+ addr: SockAddr::Tcp(Arc::new(socket_address)),
218
+ }),
219
+ Stream::UnixStream((unix_stream, socket_address)) => Ok(IoStream::Unix {
220
+ stream: unix_stream,
221
+ addr: SockAddr::Unix(Arc::new(socket_address)),
222
+ }),
223
+ },
224
+ }
225
+ }
226
+ }
227
+
228
+ enum Stream {
229
+ TcpStream((TcpStream, SocketAddr)),
230
+ UnixStream((UnixStream, unix::SocketAddr)),
231
+ }
232
+
233
+ #[derive(Clone, Debug)]
234
+ pub enum SockAddr {
235
+ Tcp(Arc<SocketAddr>),
236
+ Unix(Arc<unix::SocketAddr>),
237
+ }
238
+ impl std::fmt::Display for SockAddr {
239
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
240
+ match self {
241
+ SockAddr::Tcp(socket_addr) => write!(f, "{}", socket_addr.ip().to_canonical()),
242
+ SockAddr::Unix(socket_addr) => match socket_addr.as_pathname() {
243
+ Some(path) => write!(f, "{:?}", path),
244
+ None => write!(f, ""),
245
+ },
246
+ }
247
+ }
248
+ }
249
+ impl Display for Listener {
250
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
251
+ match self {
252
+ Listener::Tcp(listener) | Listener::TcpTls((listener, _)) => write!(
253
+ f,
254
+ "{}",
255
+ listener
256
+ .local_addr()
257
+ .map(|addr| addr.to_string())
258
+ .unwrap_or_else(|_| "".to_string())
259
+ ),
260
+
261
+ Listener::Unix(listener) | Listener::UnixTls((listener, _)) => write!(
262
+ f,
263
+ "{}",
264
+ listener
265
+ .local_addr()
266
+ .map(|addr| addr
267
+ .as_pathname()
268
+ .map(|path| path.to_str().unwrap_or("").to_owned())
269
+ .unwrap_or_default())
270
+ .unwrap_or_else(|_| "".to_string())
271
+ ),
272
+ }
273
+ }
274
+ }
275
+
276
+ impl Listener {
277
+ pub fn rebind_listener(listener: TcpListener) -> TcpListener {
278
+ let sock = SockRef::from(&listener);
279
+ let (reuse_address, reuse_port) = (
280
+ sock.reuse_address().unwrap_or(true),
281
+ sock.reuse_port().unwrap_or(true),
282
+ );
283
+
284
+ if !reuse_address || !reuse_port {
285
+ return listener;
286
+ }
287
+
288
+ let (ip, port) = sock
289
+ .local_addr()
290
+ .unwrap()
291
+ .as_socket()
292
+ .map(|addr| (addr.ip(), addr.port()))
293
+ .unwrap();
294
+
295
+ let socket_opts = SocketOpts {
296
+ reuse_address: sock.reuse_address().unwrap_or(true), // default: true
297
+ reuse_port: sock.reuse_port().unwrap_or(false), // default: false
298
+ nodelay: sock.nodelay().unwrap_or(false), // default: false
299
+ recv_buffer_size: sock.recv_buffer_size().unwrap_or(0),
300
+ send_buffer_size: sock.send_buffer_size().unwrap_or(0),
301
+ listen_backlog: 1024, // cannot query – pick sane default
302
+ };
303
+
304
+ connect_tcp_socket(ip, port, &socket_opts).unwrap()
305
+ }
306
+
307
+ pub fn into_tokio_listener(self, should_rebind: bool) -> TokioListener {
308
+ match self {
309
+ Listener::Tcp(mut listener) => {
310
+ if should_rebind {
311
+ listener = Listener::rebind_listener(listener);
312
+ }
313
+ TokioListener::Tcp(TokioTcpListener::from_std(listener).unwrap())
314
+ }
315
+ Listener::TcpTls((mut listener, acceptor)) => {
316
+ if should_rebind {
317
+ listener = Listener::rebind_listener(listener);
318
+ }
319
+ TokioListener::TcpTls(
320
+ TokioTcpListener::from_std(listener).unwrap(),
321
+ acceptor.clone(),
322
+ )
323
+ }
324
+ Listener::Unix(listener) => {
325
+ TokioListener::Unix(TokioUnixListener::from_std(listener).unwrap())
326
+ }
327
+ Listener::UnixTls((listener, acceptor)) => TokioListener::UnixTls(
328
+ TokioUnixListener::from_std(listener).unwrap(),
329
+ acceptor.clone(),
330
+ ),
331
+ }
332
+ }
333
+
334
+ /// Handover information when using exec to hand over the listener to a replacement process.
335
+ pub fn handover(&self) -> Result<(String, i32)> {
336
+ match self {
337
+ Listener::Tcp(listener) => {
338
+ let addr = listener.local_addr()?;
339
+ Ok((
340
+ format!("tcp://{}:{}", addr.ip().to_canonical(), addr.port()),
341
+ listener.as_raw_fd(),
342
+ ))
343
+ }
344
+ Listener::TcpTls((listener, _)) => {
345
+ let addr = listener.local_addr()?;
346
+ Ok((
347
+ format!("tcp://{}:{}", addr.ip().to_canonical(), addr.port()),
348
+ listener.as_raw_fd(),
349
+ ))
350
+ }
351
+ Listener::Unix(listener) => {
352
+ let addr = listener.local_addr()?;
353
+ Ok((
354
+ format!("unix://{}", addr.as_pathname().unwrap().to_str().unwrap()),
355
+ listener.as_raw_fd(),
356
+ ))
357
+ }
358
+ Listener::UnixTls((listener, _)) => {
359
+ let addr = listener.local_addr()?;
360
+ Ok((
361
+ format!("unix://{}", addr.as_pathname().unwrap().to_str().unwrap()),
362
+ listener.as_raw_fd(),
363
+ ))
364
+ }
365
+ }
366
+ }
367
+
368
+ pub fn inherit_fd(bind: Bind, fd: RawFd, socket_opts: &SocketOpts) -> Result<Self> {
369
+ let bound = match bind.address {
370
+ BindAddress::Ip(_) => match bind.protocol {
371
+ BindProtocol::Http => Listener::Tcp(revive_tcp_socket(fd, socket_opts)?),
372
+ BindProtocol::Https => {
373
+ let tcp_listener = revive_tcp_socket(fd, socket_opts)?;
374
+ Listener::TcpTls((
375
+ tcp_listener,
376
+ bind.tls_config.unwrap().build_acceptor().unwrap(),
377
+ ))
378
+ }
379
+ _ => unreachable!(),
380
+ },
381
+ BindAddress::UnixSocket(_) => match bind.tls_config {
382
+ Some(tls_config) => Listener::UnixTls((
383
+ revive_unix_socket(fd, socket_opts)?,
384
+ tls_config.build_acceptor().unwrap(),
385
+ )),
386
+ None => Listener::Unix(revive_unix_socket(fd, socket_opts)?),
387
+ },
388
+ };
389
+ Ok(bound)
390
+ }
391
+ }
392
+
393
+ impl Listener {
394
+ pub fn build(bind: Bind, socket_opts: &SocketOpts) -> Result<Self> {
395
+ let bound = match bind.address {
396
+ BindAddress::Ip(addr) => match bind.protocol {
397
+ BindProtocol::Http => {
398
+ Listener::Tcp(connect_tcp_socket(addr, bind.port.unwrap(), socket_opts)?)
399
+ }
400
+ BindProtocol::Https => {
401
+ let tcp_listener = connect_tcp_socket(addr, bind.port.unwrap(), socket_opts)?;
402
+ Listener::TcpTls((
403
+ tcp_listener,
404
+ bind.tls_config.unwrap().build_acceptor().unwrap(),
405
+ ))
406
+ }
407
+ _ => unreachable!(),
408
+ },
409
+ BindAddress::UnixSocket(path) => match bind.tls_config {
410
+ Some(tls_config) => Listener::UnixTls((
411
+ connect_unix_socket(&path, socket_opts)?,
412
+ tls_config.build_acceptor().unwrap(),
413
+ )),
414
+ None => Listener::Unix(connect_unix_socket(&path, socket_opts)?),
415
+ },
416
+ };
417
+ Ok(bound)
418
+ }
419
+ }
420
+
421
+ fn revive_tcp_socket(fd: RawFd, socket_opts: &SocketOpts) -> Result<TcpListener> {
422
+ let socket = unsafe { Socket::from_raw_fd(fd) };
423
+ socket.set_reuse_port(socket_opts.reuse_port).ok();
424
+ socket.set_reuse_address(socket_opts.reuse_address).ok();
425
+ socket.set_nonblocking(true).ok();
426
+ socket.set_nodelay(socket_opts.nodelay).ok();
427
+ socket
428
+ .set_recv_buffer_size(socket_opts.recv_buffer_size)
429
+ .ok();
430
+ socket.set_cloexec(true)?;
431
+ socket.listen(socket_opts.listen_backlog as i32)?;
432
+ Ok(socket.into())
433
+ }
434
+
435
+ fn revive_unix_socket(fd: RawFd, socket_opts: &SocketOpts) -> Result<UnixListener> {
436
+ let socket = unsafe { Socket::from_raw_fd(fd) };
437
+ socket.set_nonblocking(true).ok();
438
+ socket.listen(socket_opts.listen_backlog as i32)?;
439
+ socket.set_cloexec(true)?;
440
+
441
+ Ok(socket.into())
442
+ }
443
+
444
+ fn connect_tcp_socket(addr: IpAddr, port: u16, socket_opts: &SocketOpts) -> Result<TcpListener> {
445
+ let domain = match addr {
446
+ IpAddr::V4(_) => Domain::IPV4,
447
+ IpAddr::V6(_) => Domain::IPV6,
448
+ };
449
+ let socket = Socket::new(domain, Type::STREAM, Some(Protocol::TCP))?;
450
+ let socket_address: SocketAddr = SocketAddr::new(addr, port);
451
+ socket.set_reuse_address(socket_opts.reuse_address).ok();
452
+ socket.set_reuse_port(socket_opts.reuse_port).ok();
453
+ socket.set_nonblocking(true).ok();
454
+ socket.set_nodelay(socket_opts.nodelay).ok();
455
+ socket
456
+ .set_send_buffer_size(socket_opts.send_buffer_size)
457
+ .ok();
458
+ socket
459
+ .set_recv_buffer_size(socket_opts.recv_buffer_size)
460
+ .ok();
461
+ socket.set_only_v6(false).ok();
462
+ if let Err(e) = socket.bind(&socket_address.into()) {
463
+ error!("Failed to bind socket: {}", e);
464
+ };
465
+ if let Err(e) = socket.listen(socket_opts.listen_backlog as i32) {
466
+ error!("Failed to listen on socket: {}", e);
467
+ };
468
+ Ok(socket.into())
469
+ }
470
+
471
+ fn connect_unix_socket(path: &PathBuf, socket_opts: &SocketOpts) -> Result<UnixListener> {
472
+ let _ = std::fs::remove_file(path);
473
+ let socket = Socket::new(Domain::UNIX, Type::STREAM, None)?;
474
+ socket.set_nonblocking(true).ok();
475
+
476
+ let socket_address = socket2::SockAddr::unix(path)?;
477
+
478
+ if let Err(e) = socket.bind(&socket_address) {
479
+ error!("Failed to bind socket: {}", e);
480
+ };
481
+ if let Err(e) = socket.listen(socket_opts.listen_backlog as i32) {
482
+ error!("Failed to listen on socket: {}", e);
483
+ };
484
+ Ok(socket.into())
485
+ }
@@ -0,0 +1,4 @@
1
+ pub mod bind;
2
+ pub mod bind_protocol;
3
+ pub mod listener;
4
+ pub mod tls;
@@ -0,0 +1,132 @@
1
+ use async_trait::async_trait;
2
+ use fs2::FileExt;
3
+ use itsi_acme::caches::DirCache;
4
+ use itsi_acme::{AccountCache, CertCache};
5
+ use parking_lot::Mutex;
6
+ use std::fs::{self, OpenOptions};
7
+ use std::io::Error as IoError;
8
+ use std::path::{Path, PathBuf};
9
+
10
+ use crate::env::ITSI_ACME_LOCK_FILE_NAME;
11
+
12
+ /// A wrapper around DirCache that locks a file before writing cert/account data.
13
+ pub struct LockedDirCache<P: AsRef<Path> + Send + Sync> {
14
+ inner: DirCache<P>,
15
+ lock_path: PathBuf,
16
+ current_lock: Mutex<Option<std::fs::File>>,
17
+ }
18
+
19
+ impl<P: AsRef<Path> + Send + Sync> LockedDirCache<P> {
20
+ pub fn new(dir: P) -> Self {
21
+ let dir_path = dir.as_ref().to_path_buf();
22
+ std::fs::create_dir_all(&dir_path).unwrap();
23
+ let lock_path = dir_path.join(&*ITSI_ACME_LOCK_FILE_NAME);
24
+ Self::touch_file(&lock_path).expect("Failed to create lock file");
25
+
26
+ Self {
27
+ inner: DirCache::new(dir),
28
+ lock_path,
29
+ current_lock: Mutex::new(None),
30
+ }
31
+ }
32
+
33
+ fn touch_file(path: &PathBuf) -> std::io::Result<()> {
34
+ if let Some(parent) = path.parent() {
35
+ fs::create_dir_all(parent)?;
36
+ }
37
+ fs::OpenOptions::new()
38
+ .create(true)
39
+ .write(true)
40
+ .truncate(true)
41
+ .open(path)?;
42
+ Ok(())
43
+ }
44
+
45
+ fn lock_exclusive(&self) -> Result<(), IoError> {
46
+ if self.current_lock.lock().is_some() {
47
+ return Ok(());
48
+ }
49
+
50
+ if let Some(parent) = self.lock_path.parent() {
51
+ std::fs::create_dir_all(parent)?;
52
+ }
53
+ let lockfile = OpenOptions::new()
54
+ .create(true)
55
+ .write(true)
56
+ .truncate(true)
57
+ .open(&self.lock_path)?;
58
+ lockfile.lock_exclusive()?;
59
+ *self.current_lock.lock() = Some(lockfile);
60
+ Ok(())
61
+ }
62
+
63
+ fn unlock(&self) -> Result<(), IoError> {
64
+ self.current_lock.lock().take();
65
+ Ok(())
66
+ }
67
+ }
68
+
69
+ #[async_trait]
70
+ impl<P: AsRef<Path> + Send + Sync> CertCache for LockedDirCache<P> {
71
+ type EC = IoError;
72
+
73
+ async fn load_cert(
74
+ &self,
75
+ domains: &[String],
76
+ directory_url: &str,
77
+ ) -> Result<Option<Vec<u8>>, Self::EC> {
78
+ self.lock_exclusive()?;
79
+ let result = self.inner.load_cert(domains, directory_url).await;
80
+
81
+ if let Ok(Some(_)) = result {
82
+ self.unlock()?;
83
+ }
84
+
85
+ result
86
+ }
87
+
88
+ async fn store_cert(
89
+ &self,
90
+ domains: &[String],
91
+ directory_url: &str,
92
+ cert: &[u8],
93
+ ) -> Result<(), Self::EC> {
94
+ // Acquire the lock before storing
95
+ self.lock_exclusive()?;
96
+
97
+ // Perform the store operation
98
+ let result = self.inner.store_cert(domains, directory_url, cert).await;
99
+
100
+ if let Ok(()) = result {
101
+ self.unlock()?;
102
+ }
103
+ result
104
+ }
105
+ }
106
+
107
+ #[async_trait]
108
+ impl<P: AsRef<Path> + Send + Sync> AccountCache for LockedDirCache<P> {
109
+ type EA = IoError;
110
+
111
+ async fn load_account(
112
+ &self,
113
+ contact: &[String],
114
+ directory_url: &str,
115
+ ) -> Result<Option<Vec<u8>>, Self::EA> {
116
+ self.lock_exclusive()?;
117
+ self.inner.load_account(contact, directory_url).await
118
+ }
119
+
120
+ async fn store_account(
121
+ &self,
122
+ contact: &[String],
123
+ directory_url: &str,
124
+ account: &[u8],
125
+ ) -> Result<(), Self::EA> {
126
+ self.lock_exclusive()?;
127
+
128
+ self.inner
129
+ .store_account(contact, directory_url, account)
130
+ .await
131
+ }
132
+ }