itsi-scheduler 0.1.5 → 0.1.19

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-scheduler might be problematic. Click here for more details.

Files changed (125) hide show
  1. checksums.yaml +4 -4
  2. data/CODE_OF_CONDUCT.md +7 -0
  3. data/Cargo.lock +90 -22
  4. data/README.md +5 -0
  5. data/_index.md +7 -0
  6. data/ext/itsi_error/Cargo.toml +1 -0
  7. data/ext/itsi_error/src/lib.rs +106 -7
  8. data/ext/itsi_error/target/debug/build/clang-sys-da71b0344e568175/out/common.rs +355 -0
  9. data/ext/itsi_error/target/debug/build/clang-sys-da71b0344e568175/out/dynamic.rs +276 -0
  10. data/ext/itsi_error/target/debug/build/clang-sys-da71b0344e568175/out/macros.rs +49 -0
  11. data/ext/itsi_error/target/debug/build/rb-sys-49f554618693db24/out/bindings-0.9.110-mri-arm64-darwin23-3.4.2.rs +8865 -0
  12. data/ext/itsi_error/target/debug/incremental/itsi_error-1mmt5sux7jb0i/s-h510z7m8v9-0bxu7yd.lock +0 -0
  13. data/ext/itsi_error/target/debug/incremental/itsi_error-2vn3jey74oiw0/s-h5113n0e7e-1v5qzs6.lock +0 -0
  14. data/ext/itsi_error/target/debug/incremental/itsi_error-37uv9dicz7awp/s-h510ykifhe-0tbnep2.lock +0 -0
  15. data/ext/itsi_error/target/debug/incremental/itsi_error-37uv9dicz7awp/s-h510yyocpj-0tz7ug7.lock +0 -0
  16. data/ext/itsi_error/target/debug/incremental/itsi_error-37uv9dicz7awp/s-h510z0xc8g-14ol18k.lock +0 -0
  17. data/ext/itsi_error/target/debug/incremental/itsi_error-3g5qf4y7d54uj/s-h5113n0e7d-1trk8on.lock +0 -0
  18. data/ext/itsi_error/target/debug/incremental/itsi_error-3lpfftm45d3e2/s-h510z7m8r3-1pxp20o.lock +0 -0
  19. data/ext/itsi_error/target/debug/incremental/itsi_error-3o4qownhl3d7n/s-h510ykifek-1uxasnk.lock +0 -0
  20. data/ext/itsi_error/target/debug/incremental/itsi_error-3o4qownhl3d7n/s-h510yyocki-11u37qm.lock +0 -0
  21. data/ext/itsi_error/target/debug/incremental/itsi_error-3o4qownhl3d7n/s-h510z0xc93-0pmy0zm.lock +0 -0
  22. data/ext/itsi_rb_helpers/Cargo.toml +1 -0
  23. data/ext/itsi_rb_helpers/src/heap_value.rs +18 -0
  24. data/ext/itsi_rb_helpers/src/lib.rs +59 -9
  25. data/ext/itsi_rb_helpers/target/debug/build/clang-sys-da71b0344e568175/out/common.rs +355 -0
  26. data/ext/itsi_rb_helpers/target/debug/build/clang-sys-da71b0344e568175/out/dynamic.rs +276 -0
  27. data/ext/itsi_rb_helpers/target/debug/build/clang-sys-da71b0344e568175/out/macros.rs +49 -0
  28. 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
  29. data/ext/itsi_rb_helpers/target/debug/incremental/itsi_rb_helpers-040pxg6yhb3g3/s-h5113n7a1b-03bwlt4.lock +0 -0
  30. data/ext/itsi_rb_helpers/target/debug/incremental/itsi_rb_helpers-131g1u4dzkt1a/s-h51113xnh3-1eik1ip.lock +0 -0
  31. data/ext/itsi_rb_helpers/target/debug/incremental/itsi_rb_helpers-131g1u4dzkt1a/s-h5111704jj-0g4rj8x.lock +0 -0
  32. data/ext/itsi_rb_helpers/target/debug/incremental/itsi_rb_helpers-1q2d3drtxrzs5/s-h5113n79yl-0bxcqc5.lock +0 -0
  33. data/ext/itsi_rb_helpers/target/debug/incremental/itsi_rb_helpers-374a9h7ovycj0/s-h51113xoox-10de2hp.lock +0 -0
  34. data/ext/itsi_rb_helpers/target/debug/incremental/itsi_rb_helpers-374a9h7ovycj0/s-h5111704w7-0vdq7gq.lock +0 -0
  35. data/ext/itsi_scheduler/src/itsi_scheduler.rs +1 -1
  36. data/ext/itsi_server/Cargo.lock +2956 -0
  37. data/ext/itsi_server/Cargo.toml +72 -28
  38. data/ext/itsi_server/src/default_responses/mod.rs +11 -0
  39. data/ext/itsi_server/src/env.rs +43 -0
  40. data/ext/itsi_server/src/lib.rs +113 -75
  41. data/ext/itsi_server/src/prelude.rs +2 -0
  42. data/ext/itsi_server/src/{body_proxy → ruby_types/itsi_body_proxy}/big_bytes.rs +10 -5
  43. data/ext/itsi_server/src/{body_proxy/itsi_body_proxy.rs → ruby_types/itsi_body_proxy/mod.rs} +29 -8
  44. data/ext/itsi_server/src/ruby_types/itsi_grpc_call.rs +344 -0
  45. data/ext/itsi_server/src/ruby_types/itsi_grpc_response_stream/mod.rs +264 -0
  46. data/ext/itsi_server/src/ruby_types/itsi_http_request.rs +345 -0
  47. data/ext/itsi_server/src/{response/itsi_response.rs → ruby_types/itsi_http_response.rs} +84 -40
  48. data/ext/itsi_server/src/ruby_types/itsi_server/file_watcher.rs +225 -0
  49. data/ext/itsi_server/src/ruby_types/itsi_server/itsi_server_config.rs +375 -0
  50. data/ext/itsi_server/src/ruby_types/itsi_server.rs +83 -0
  51. data/ext/itsi_server/src/ruby_types/mod.rs +48 -0
  52. data/ext/itsi_server/src/server/{bind.rs → binds/bind.rs} +56 -24
  53. data/ext/itsi_server/src/server/{listener.rs → binds/listener.rs} +218 -113
  54. data/ext/itsi_server/src/server/binds/mod.rs +4 -0
  55. data/ext/itsi_server/src/server/{tls → binds/tls}/locked_dir_cache.rs +55 -17
  56. data/ext/itsi_server/src/server/{tls.rs → binds/tls.rs} +109 -28
  57. data/ext/itsi_server/src/server/byte_frame.rs +32 -0
  58. data/ext/itsi_server/src/server/http_message_types.rs +97 -0
  59. data/ext/itsi_server/src/server/io_stream.rs +2 -1
  60. data/ext/itsi_server/src/server/lifecycle_event.rs +3 -0
  61. data/ext/itsi_server/src/server/middleware_stack/middleware.rs +165 -0
  62. data/ext/itsi_server/src/server/middleware_stack/middlewares/allow_list.rs +56 -0
  63. data/ext/itsi_server/src/server/middleware_stack/middlewares/auth_api_key.rs +87 -0
  64. data/ext/itsi_server/src/server/middleware_stack/middlewares/auth_basic.rs +86 -0
  65. data/ext/itsi_server/src/server/middleware_stack/middlewares/auth_jwt.rs +285 -0
  66. data/ext/itsi_server/src/server/middleware_stack/middlewares/cache_control.rs +142 -0
  67. data/ext/itsi_server/src/server/middleware_stack/middlewares/compression.rs +289 -0
  68. data/ext/itsi_server/src/server/middleware_stack/middlewares/cors.rs +292 -0
  69. data/ext/itsi_server/src/server/middleware_stack/middlewares/deny_list.rs +55 -0
  70. data/ext/itsi_server/src/server/middleware_stack/middlewares/error_response/default_responses.rs +190 -0
  71. data/ext/itsi_server/src/server/middleware_stack/middlewares/error_response.rs +157 -0
  72. data/ext/itsi_server/src/server/middleware_stack/middlewares/etag.rs +195 -0
  73. data/ext/itsi_server/src/server/middleware_stack/middlewares/header_interpretation.rs +82 -0
  74. data/ext/itsi_server/src/server/middleware_stack/middlewares/intrusion_protection.rs +201 -0
  75. data/ext/itsi_server/src/server/middleware_stack/middlewares/log_requests.rs +82 -0
  76. data/ext/itsi_server/src/server/middleware_stack/middlewares/max_body.rs +47 -0
  77. data/ext/itsi_server/src/server/middleware_stack/middlewares/mod.rs +87 -0
  78. data/ext/itsi_server/src/server/middleware_stack/middlewares/proxy.rs +414 -0
  79. data/ext/itsi_server/src/server/middleware_stack/middlewares/rate_limit.rs +131 -0
  80. data/ext/itsi_server/src/server/middleware_stack/middlewares/redirect.rs +76 -0
  81. data/ext/itsi_server/src/server/middleware_stack/middlewares/request_headers.rs +44 -0
  82. data/ext/itsi_server/src/server/middleware_stack/middlewares/response_headers.rs +36 -0
  83. data/ext/itsi_server/src/server/middleware_stack/middlewares/ruby_app.rs +126 -0
  84. data/ext/itsi_server/src/server/middleware_stack/middlewares/static_assets.rs +180 -0
  85. data/ext/itsi_server/src/server/middleware_stack/middlewares/static_response.rs +55 -0
  86. data/ext/itsi_server/src/server/middleware_stack/middlewares/string_rewrite.rs +163 -0
  87. data/ext/itsi_server/src/server/middleware_stack/middlewares/token_source.rs +12 -0
  88. data/ext/itsi_server/src/server/middleware_stack/mod.rs +347 -0
  89. data/ext/itsi_server/src/server/mod.rs +6 -5
  90. data/ext/itsi_server/src/server/process_worker.rs +65 -14
  91. data/ext/itsi_server/src/server/request_job.rs +11 -0
  92. data/ext/itsi_server/src/server/serve_strategy/cluster_mode.rs +137 -49
  93. data/ext/itsi_server/src/server/serve_strategy/mod.rs +9 -6
  94. data/ext/itsi_server/src/server/serve_strategy/single_mode.rs +338 -164
  95. data/ext/itsi_server/src/server/signal.rs +32 -26
  96. data/ext/itsi_server/src/server/size_limited_incoming.rs +101 -0
  97. data/ext/itsi_server/src/server/thread_worker.rs +214 -107
  98. data/ext/itsi_server/src/services/cache_store.rs +74 -0
  99. data/ext/itsi_server/src/services/itsi_http_service.rs +239 -0
  100. data/ext/itsi_server/src/services/mime_types.rs +1416 -0
  101. data/ext/itsi_server/src/services/mod.rs +6 -0
  102. data/ext/itsi_server/src/services/password_hasher.rs +83 -0
  103. data/ext/itsi_server/src/services/rate_limiter.rs +569 -0
  104. data/ext/itsi_server/src/services/static_file_server.rs +1324 -0
  105. data/ext/itsi_tracing/Cargo.toml +1 -0
  106. data/ext/itsi_tracing/src/lib.rs +312 -34
  107. data/ext/itsi_tracing/target/debug/incremental/itsi_tracing-0994n8rpvvt9m/s-h510hfz1f6-1kbycmq.lock +0 -0
  108. data/ext/itsi_tracing/target/debug/incremental/itsi_tracing-0bob7bf4yq34i/s-h5113125h5-0lh4rag.lock +0 -0
  109. data/ext/itsi_tracing/target/debug/incremental/itsi_tracing-2fcodulrxbbxo/s-h510h2infk-0hp5kjw.lock +0 -0
  110. data/ext/itsi_tracing/target/debug/incremental/itsi_tracing-2iak63r1woi1l/s-h510h2in4q-0kxfzw1.lock +0 -0
  111. data/ext/itsi_tracing/target/debug/incremental/itsi_tracing-2kk4qj9gn5dg2/s-h5113124kv-0enwon2.lock +0 -0
  112. data/ext/itsi_tracing/target/debug/incremental/itsi_tracing-2mwo0yas7dtw4/s-h510hfz1ha-1udgpei.lock +0 -0
  113. data/lib/itsi/scheduler/version.rb +1 -1
  114. data/lib/itsi/scheduler.rb +2 -2
  115. metadata +93 -21
  116. data/ext/itsi_error/src/from.rs +0 -71
  117. data/ext/itsi_server/extconf.rb +0 -6
  118. data/ext/itsi_server/src/body_proxy/mod.rs +0 -2
  119. data/ext/itsi_server/src/request/itsi_request.rs +0 -277
  120. data/ext/itsi_server/src/request/mod.rs +0 -1
  121. data/ext/itsi_server/src/response/mod.rs +0 -1
  122. data/ext/itsi_server/src/server/itsi_ca/itsi_ca.crt +0 -13
  123. data/ext/itsi_server/src/server/itsi_ca/itsi_ca.key +0 -5
  124. data/ext/itsi_server/src/server/itsi_server.rs +0 -244
  125. /data/ext/itsi_server/src/server/{bind_protocol.rs → binds/bind_protocol.rs} +0 -0
@@ -0,0 +1,48 @@
1
+ use magnus::{value::Lazy, Module, RClass, RModule};
2
+
3
+ pub mod itsi_body_proxy;
4
+ pub mod itsi_grpc_call;
5
+ pub mod itsi_grpc_response_stream;
6
+ pub mod itsi_http_request;
7
+ pub mod itsi_http_response;
8
+ pub mod itsi_server;
9
+
10
+ pub static ITSI_MODULE: Lazy<RModule> = Lazy::new(|ruby| ruby.define_module("Itsi").unwrap());
11
+ pub static ITSI_SERVER: Lazy<RClass> = Lazy::new(|ruby| {
12
+ ruby.get_inner(&ITSI_MODULE)
13
+ .define_class("Server", ruby.class_object())
14
+ .unwrap()
15
+ });
16
+
17
+ pub static ITSI_SERVER_CONFIG: Lazy<RModule> =
18
+ Lazy::new(|ruby| ruby.get_inner(&ITSI_SERVER).const_get("Config").unwrap());
19
+
20
+ pub static ITSI_REQUEST: Lazy<RClass> = Lazy::new(|ruby| {
21
+ ruby.get_inner(&ITSI_MODULE)
22
+ .define_class("HttpRequest", ruby.class_object())
23
+ .unwrap()
24
+ });
25
+
26
+ pub static ITSI_RESPONSE: Lazy<RClass> = Lazy::new(|ruby| {
27
+ ruby.get_inner(&ITSI_MODULE)
28
+ .define_class("HttpResponse", ruby.class_object())
29
+ .unwrap()
30
+ });
31
+
32
+ pub static ITSI_BODY_PROXY: Lazy<RClass> = Lazy::new(|ruby| {
33
+ ruby.get_inner(&ITSI_MODULE)
34
+ .define_class("BodyProxy", ruby.class_object())
35
+ .unwrap()
36
+ });
37
+
38
+ pub static ITSI_GRPC_CALL: Lazy<RClass> = Lazy::new(|ruby| {
39
+ ruby.get_inner(&ITSI_MODULE)
40
+ .define_class("GrpcCall", ruby.class_object())
41
+ .unwrap()
42
+ });
43
+
44
+ pub static ITSI_GRPC_RESPONSE_STREAM: Lazy<RClass> = Lazy::new(|ruby| {
45
+ ruby.get_inner(&ITSI_MODULE)
46
+ .define_class("GrpcResponseStream", ruby.class_object())
47
+ .unwrap()
48
+ });
@@ -2,6 +2,7 @@ use super::{
2
2
  bind_protocol::BindProtocol,
3
3
  tls::{configure_tls, ItsiTlsAcceptor},
4
4
  };
5
+ use crate::prelude::*;
5
6
  use itsi_error::ItsiError;
6
7
  use std::{
7
8
  collections::HashMap,
@@ -9,6 +10,7 @@ use std::{
9
10
  path::PathBuf,
10
11
  str::FromStr,
11
12
  };
13
+
12
14
  #[derive(Debug, Clone)]
13
15
  pub enum BindAddress {
14
16
  Ip(IpAddr),
@@ -27,16 +29,36 @@ pub struct Bind {
27
29
  pub address: BindAddress,
28
30
  pub port: Option<u16>, // None for Unix Sockets
29
31
  pub protocol: BindProtocol,
30
- pub tls_config: Option<ItsiTlsAcceptor>,
32
+ pub tls_config: Option<TlsOptions>,
33
+ }
34
+
35
+ #[derive(Default, Clone)]
36
+ pub struct TlsOptions {
37
+ pub host: String,
38
+ pub options: HashMap<String, String>,
39
+ }
40
+
41
+ impl TlsOptions {
42
+ pub fn build_acceptor(&self) -> Result<ItsiTlsAcceptor> {
43
+ configure_tls(&self.host, &self.options)
44
+ }
45
+ }
46
+
47
+ impl Bind {
48
+ pub fn listener_address_string(&self) -> String {
49
+ match &self.address {
50
+ BindAddress::Ip(ip) => format!("tcp://{}:{}", ip.to_canonical(), self.port.unwrap()),
51
+ BindAddress::UnixSocket(path) => {
52
+ format!("unix://{}", path.as_path().to_str().unwrap())
53
+ }
54
+ }
55
+ }
31
56
  }
32
57
 
33
58
  impl std::fmt::Debug for Bind {
34
59
  fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
35
60
  match &self.address {
36
61
  BindAddress::Ip(ip) => match self.protocol {
37
- BindProtocol::Unix | BindProtocol::Unixs => {
38
- write!(f, "{}://{}", self.protocol, ip)
39
- }
40
62
  BindProtocol::Https if self.port == Some(443) => {
41
63
  write!(f, "{}://{}", self.protocol, ip)
42
64
  }
@@ -64,7 +86,7 @@ impl std::fmt::Debug for Bind {
64
86
  impl FromStr for Bind {
65
87
  type Err = ItsiError;
66
88
 
67
- fn from_str(s: &str) -> Result<Self, Self::Err> {
89
+ fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
68
90
  let (protocol, remainder) = if let Some((proto, rest)) = s.split_once("://") {
69
91
  (proto.parse::<BindProtocol>()?, rest)
70
92
  } else {
@@ -100,7 +122,7 @@ impl FromStr for Bind {
100
122
  "IPv6 addresses must use [ ] when specifying a port".to_owned(),
101
123
  ));
102
124
  } else {
103
- (h, None) // Treat as a hostname
125
+ (h, p.parse::<u16>().ok()) // Treat as a hostname
104
126
  }
105
127
  } else {
106
128
  (url, None)
@@ -109,33 +131,43 @@ impl FromStr for Bind {
109
131
  let address = if let Ok(ip) = host.parse::<IpAddr>() {
110
132
  BindAddress::Ip(ip)
111
133
  } else {
112
- resolve_hostname(host)
113
- .map(BindAddress::Ip)
114
- .ok_or(ItsiError::ArgumentError(format!(
115
- "Failed to resolve hostname {}",
116
- host
117
- )))?
134
+ match protocol {
135
+ BindProtocol::Https | BindProtocol::Http => resolve_hostname(host)
136
+ .map(BindAddress::Ip)
137
+ .ok_or(ItsiError::ArgumentError(format!(
138
+ "Failed to resolve hostname {}",
139
+ host
140
+ )))?,
141
+ BindProtocol::Unix | BindProtocol::Unixs => BindAddress::UnixSocket(host.into()),
142
+ }
118
143
  };
119
- let (port, address) = match protocol {
120
- BindProtocol::Http => (port.or(Some(80)), address),
121
- BindProtocol::Https => (port.or(Some(443)), address),
122
- BindProtocol::Unix => (None, BindAddress::UnixSocket(host.into())),
123
- BindProtocol::Unixs => (None, BindAddress::UnixSocket(host.into())),
144
+
145
+ let port = match protocol {
146
+ BindProtocol::Http => port.or(Some(80)),
147
+ BindProtocol::Https => port.or(Some(443)),
148
+ BindProtocol::Unix => None,
149
+ BindProtocol::Unixs => None,
124
150
  };
125
151
 
126
152
  let tls_config = match protocol {
127
153
  BindProtocol::Http => None,
128
- BindProtocol::Https => Some(configure_tls(host, &options)?),
154
+ BindProtocol::Https => Some(TlsOptions {
155
+ host: host.to_owned(),
156
+ options,
157
+ }),
129
158
  BindProtocol::Unix => None,
130
- BindProtocol::Unixs => Some(configure_tls(host, &options)?),
159
+ BindProtocol::Unixs => Some(TlsOptions {
160
+ host: host.to_owned(),
161
+ options,
162
+ }),
131
163
  };
132
-
133
- Ok(Self {
164
+ let bind = Self {
134
165
  address,
135
166
  port,
136
167
  protocol,
137
168
  tls_config,
138
- })
169
+ };
170
+ Ok(bind)
139
171
  }
140
172
  }
141
173
 
@@ -153,8 +185,8 @@ fn resolve_hostname(hostname: &str) -> Option<IpAddr> {
153
185
  .to_socket_addrs()
154
186
  .ok()?
155
187
  .find_map(|addr| {
156
- if addr.is_ipv6() {
157
- Some(addr.ip()) // Prefer IPv6
188
+ if addr.is_ipv4() {
189
+ Some(addr.ip()) // Prefer IPv4
158
190
  } else {
159
191
  None
160
192
  }
@@ -1,19 +1,25 @@
1
+ use crate::prelude::*;
2
+ use crate::server::io_stream::IoStream;
3
+ use crate::server::serve_strategy::single_mode::RunningPhase;
4
+
1
5
  use super::bind::{Bind, BindAddress};
2
6
  use super::bind_protocol::BindProtocol;
3
- use super::io_stream::IoStream;
7
+
4
8
  use super::tls::ItsiTlsAcceptor;
5
9
  use itsi_error::{ItsiError, Result};
6
10
  use itsi_tracing::info;
7
11
  use socket2::{Domain, Protocol, Socket, Type};
12
+ use std::fmt::Display;
8
13
  use std::net::{IpAddr, SocketAddr, TcpListener};
14
+ use std::os::fd::{AsRawFd, FromRawFd, RawFd};
9
15
  use std::sync::Arc;
10
16
  use std::{os::unix::net::UnixListener, path::PathBuf};
11
17
  use tokio::net::TcpListener as TokioTcpListener;
12
18
  use tokio::net::UnixListener as TokioUnixListener;
13
19
  use tokio::net::{unix, TcpStream, UnixStream};
20
+ use tokio::sync::watch::Receiver;
14
21
  use tokio_rustls::TlsAcceptor;
15
22
  use tokio_stream::StreamExt;
16
- use tracing::error;
17
23
 
18
24
  pub(crate) enum Listener {
19
25
  Tcp(TcpListener),
@@ -23,45 +29,79 @@ pub(crate) enum Listener {
23
29
  }
24
30
 
25
31
  pub(crate) enum TokioListener {
26
- Tcp {
27
- listener: TokioTcpListener,
28
- host: String,
29
- port: u16,
30
- },
31
- TcpTls {
32
- listener: TokioTcpListener,
33
- acceptor: ItsiTlsAcceptor,
34
- host: String,
35
- port: u16,
36
- },
37
- Unix {
38
- listener: TokioUnixListener,
39
- },
40
- UnixTls {
41
- listener: TokioUnixListener,
42
- acceptor: ItsiTlsAcceptor,
43
- },
32
+ Tcp(TokioTcpListener),
33
+ TcpTls(TokioTcpListener, ItsiTlsAcceptor),
34
+ Unix(TokioUnixListener),
35
+ UnixTls(TokioUnixListener, ItsiTlsAcceptor),
36
+ }
37
+
38
+ #[derive(Debug, Clone)]
39
+ pub struct ListenerInfo {
40
+ pub host: String,
41
+ pub port: u16,
42
+ pub scheme: String,
44
43
  }
45
44
 
46
45
  impl TokioListener {
47
- pub fn unbind(self) {
46
+ pub fn listener_info(&self) -> ListenerInfo {
48
47
  match self {
49
- TokioListener::Tcp { listener, .. } => drop(listener.into_std().unwrap()),
50
- TokioListener::TcpTls { listener, .. } => drop(listener.into_std().unwrap()),
51
- TokioListener::Unix { listener } => drop(listener.into_std().unwrap()),
52
- TokioListener::UnixTls { listener, .. } => drop(listener.into_std().unwrap()),
53
- };
48
+ TokioListener::Tcp(listener) => ListenerInfo {
49
+ host: listener
50
+ .local_addr()
51
+ .unwrap()
52
+ .ip()
53
+ .to_canonical()
54
+ .to_string(),
55
+ port: listener.local_addr().unwrap().port(),
56
+ scheme: "http".to_string(),
57
+ },
58
+ TokioListener::TcpTls(listener, _) => ListenerInfo {
59
+ host: listener
60
+ .local_addr()
61
+ .unwrap()
62
+ .ip()
63
+ .to_canonical()
64
+ .to_string(),
65
+ port: listener.local_addr().unwrap().port(),
66
+ scheme: "https".to_string(),
67
+ },
68
+ TokioListener::Unix(listener) => ListenerInfo {
69
+ host: listener
70
+ .local_addr()
71
+ .unwrap()
72
+ .as_pathname()
73
+ .unwrap()
74
+ .to_str()
75
+ .unwrap()
76
+ .to_owned(),
77
+ port: 0,
78
+ scheme: "unix".to_string(),
79
+ },
80
+ TokioListener::UnixTls(listener, _) => ListenerInfo {
81
+ host: listener
82
+ .local_addr()
83
+ .unwrap()
84
+ .as_pathname()
85
+ .unwrap()
86
+ .to_str()
87
+ .unwrap()
88
+ .to_owned(),
89
+ port: 0,
90
+ scheme: "ssl".to_string(),
91
+ },
92
+ }
54
93
  }
94
+
55
95
  pub(crate) async fn accept(&self) -> Result<IoStream> {
56
96
  match self {
57
- TokioListener::Tcp { listener, .. } => TokioListener::accept_tcp(listener).await,
58
- TokioListener::TcpTls {
59
- listener, acceptor, ..
60
- } => TokioListener::accept_tls(listener, acceptor).await,
61
- TokioListener::Unix { listener, .. } => TokioListener::accept_unix(listener).await,
62
- TokioListener::UnixTls {
63
- listener, acceptor, ..
64
- } => TokioListener::accept_unix_tls(listener, acceptor).await,
97
+ TokioListener::Tcp(listener) => TokioListener::accept_tcp(listener).await,
98
+ TokioListener::TcpTls(listener, acceptor) => {
99
+ TokioListener::accept_tls(listener, acceptor).await
100
+ }
101
+ TokioListener::Unix(listener) => TokioListener::accept_unix(listener).await,
102
+ TokioListener::UnixTls(listener, acceptor) => {
103
+ TokioListener::accept_unix_tls(listener, acceptor).await
104
+ }
65
105
  }
66
106
  }
67
107
 
@@ -70,17 +110,24 @@ impl TokioListener {
70
110
  Self::to_tokio_io(Stream::TcpStream(tcp_stream), None).await
71
111
  }
72
112
 
73
- pub async fn spawn_state_task(&self) {
74
- if let TokioListener::TcpTls {
75
- acceptor: ItsiTlsAcceptor::Automatic(_acme_acceptor, state, _server_config),
76
- ..
77
- } = self
113
+ pub async fn spawn_state_task(&self, mut shutdown_receiver: Receiver<RunningPhase>) {
114
+ if let TokioListener::TcpTls(
115
+ _,
116
+ ItsiTlsAcceptor::Automatic(_acme_acceptor, state, _server_config),
117
+ ) = self
78
118
  {
79
119
  let mut state = state.lock().await;
80
120
  loop {
81
- match StreamExt::next(&mut *state).await {
82
- Some(event) => info!("Received acme event: {:?}", event),
83
- None => error!("Received no acme event"),
121
+ tokio::select! {
122
+ stream_event = StreamExt::next(&mut *state) => {
123
+ match stream_event {
124
+ Some(event) => info!("ACME Event: {:?}", event),
125
+ None => error!("Received no acme event"),
126
+ }
127
+ },
128
+ _ = shutdown_receiver.changed() => {
129
+ break;
130
+ }
84
131
  }
85
132
  }
86
133
  }
@@ -98,7 +145,7 @@ impl TokioListener {
98
145
  ItsiTlsAcceptor::Automatic(acme_acceptor, _, rustls_config) => {
99
146
  let accept_future = acme_acceptor.accept(tcp_stream.0);
100
147
  match accept_future.await {
101
- Ok(None) => Err(ItsiError::Pass()),
148
+ Ok(None) => Err(ItsiError::Pass),
102
149
  Ok(Some(start_handshake)) => {
103
150
  let tls_stream = start_handshake.into_stream(rustls_config.clone()).await?;
104
151
  Ok(IoStream::TcpTls {
@@ -108,7 +155,7 @@ impl TokioListener {
108
155
  }
109
156
  Err(error) => {
110
157
  error!(error = format!("{:?}", error));
111
- Err(ItsiError::Pass())
158
+ Err(ItsiError::Pass)
112
159
  }
113
160
  }
114
161
  }
@@ -175,33 +222,6 @@ impl TokioListener {
175
222
  },
176
223
  }
177
224
  }
178
-
179
- pub(crate) fn scheme(&self) -> String {
180
- match self {
181
- TokioListener::Tcp { .. } => "http".to_string(),
182
- TokioListener::TcpTls { .. } => "https".to_string(),
183
- TokioListener::Unix { .. } => "http".to_string(),
184
- TokioListener::UnixTls { .. } => "https".to_string(),
185
- }
186
- }
187
-
188
- pub(crate) fn port(&self) -> u16 {
189
- match self {
190
- TokioListener::Tcp { port, .. } => *port,
191
- TokioListener::TcpTls { port, .. } => *port,
192
- TokioListener::Unix { .. } => 0,
193
- TokioListener::UnixTls { .. } => 0,
194
- }
195
- }
196
-
197
- pub(crate) fn host(&self) -> String {
198
- match self {
199
- TokioListener::Tcp { host, .. } => host.to_string(),
200
- TokioListener::TcpTls { host, .. } => host.to_string(),
201
- TokioListener::Unix { .. } => "unix".to_string(),
202
- TokioListener::UnixTls { .. } => "unix".to_string(),
203
- }
204
- }
205
225
  }
206
226
 
207
227
  enum Stream {
@@ -225,51 +245,109 @@ impl std::fmt::Display for SockAddr {
225
245
  }
226
246
  }
227
247
  }
248
+ impl Display for Listener {
249
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
250
+ match self {
251
+ Listener::Tcp(listener) | Listener::TcpTls((listener, _)) => write!(
252
+ f,
253
+ "{}",
254
+ listener
255
+ .local_addr()
256
+ .map(|addr| addr.to_string())
257
+ .unwrap_or_else(|_| "".to_string())
258
+ ),
259
+
260
+ Listener::Unix(listener) | Listener::UnixTls((listener, _)) => write!(
261
+ f,
262
+ "{}",
263
+ listener
264
+ .local_addr()
265
+ .map(|addr| addr
266
+ .as_pathname()
267
+ .map(|path| path.to_str().unwrap_or("").to_owned())
268
+ .unwrap_or_default())
269
+ .unwrap_or_else(|_| "".to_string())
270
+ ),
271
+ }
272
+ }
273
+ }
228
274
 
229
275
  impl Listener {
230
- pub fn unbind(self) {
276
+ pub fn into_tokio_listener(self) -> TokioListener {
231
277
  match self {
232
- Listener::Tcp(listener) => drop(listener),
233
- Listener::TcpTls((listener, _)) => drop(listener),
234
- Listener::Unix(listener) => drop(listener),
235
- Listener::UnixTls((listener, _)) => drop(listener),
236
- };
278
+ Listener::Tcp(listener) => {
279
+ TokioListener::Tcp(TokioTcpListener::from_std(listener).unwrap())
280
+ }
281
+ Listener::TcpTls((listener, acceptor)) => TokioListener::TcpTls(
282
+ TokioTcpListener::from_std(listener).unwrap(),
283
+ acceptor.clone(),
284
+ ),
285
+ Listener::Unix(listener) => {
286
+ TokioListener::Unix(TokioUnixListener::from_std(listener).unwrap())
287
+ }
288
+ Listener::UnixTls((listener, acceptor)) => TokioListener::UnixTls(
289
+ TokioUnixListener::from_std(listener).unwrap(),
290
+ acceptor.clone(),
291
+ ),
292
+ }
237
293
  }
238
- pub fn to_tokio_listener(&self) -> TokioListener {
294
+
295
+ /// Handover information when using exec to hand over the listener to a replacement process.
296
+ pub fn handover(&self) -> Result<(String, i32)> {
239
297
  match self {
240
- Listener::Tcp(listener) => TokioListener::Tcp {
241
- listener: TokioTcpListener::from_std(TcpListener::try_clone(listener).unwrap())
242
- .unwrap(),
243
- host: listener
244
- .local_addr()
245
- .unwrap()
246
- .ip()
247
- .to_canonical()
248
- .to_string(),
249
- port: listener.local_addr().unwrap().port(),
250
- },
251
- Listener::TcpTls((listener, acceptor)) => TokioListener::TcpTls {
252
- listener: TokioTcpListener::from_std(TcpListener::try_clone(listener).unwrap())
253
- .unwrap(),
254
- acceptor: acceptor.clone(),
255
- host: listener
256
- .local_addr()
257
- .unwrap()
258
- .ip()
259
- .to_canonical()
260
- .to_string(),
261
- port: listener.local_addr().unwrap().port(),
262
- },
263
- Listener::Unix(listener) => TokioListener::Unix {
264
- listener: TokioUnixListener::from_std(UnixListener::try_clone(listener).unwrap())
265
- .unwrap(),
298
+ Listener::Tcp(listener) => {
299
+ let addr = listener.local_addr()?;
300
+ Ok((
301
+ format!("tcp://{}:{}", addr.ip().to_canonical(), addr.port()),
302
+ listener.as_raw_fd(),
303
+ ))
304
+ }
305
+ Listener::TcpTls((listener, _)) => {
306
+ let addr = listener.local_addr()?;
307
+ Ok((
308
+ format!("tcp://{}:{}", addr.ip().to_canonical(), addr.port()),
309
+ listener.as_raw_fd(),
310
+ ))
311
+ }
312
+ Listener::Unix(listener) => {
313
+ let addr = listener.local_addr()?;
314
+ Ok((
315
+ format!("unix://{}", addr.as_pathname().unwrap().to_str().unwrap()),
316
+ listener.as_raw_fd(),
317
+ ))
318
+ }
319
+ Listener::UnixTls((listener, _)) => {
320
+ let addr = listener.local_addr()?;
321
+ Ok((
322
+ format!("unix://{}", addr.as_pathname().unwrap().to_str().unwrap()),
323
+ listener.as_raw_fd(),
324
+ ))
325
+ }
326
+ }
327
+ }
328
+
329
+ pub fn inherit_fd(bind: Bind, fd: RawFd) -> Result<Self> {
330
+ let bound = match bind.address {
331
+ BindAddress::Ip(_) => match bind.protocol {
332
+ BindProtocol::Http => Listener::Tcp(revive_tcp_socket(fd)?),
333
+ BindProtocol::Https => {
334
+ let tcp_listener = revive_tcp_socket(fd)?;
335
+ Listener::TcpTls((
336
+ tcp_listener,
337
+ bind.tls_config.unwrap().build_acceptor().unwrap(),
338
+ ))
339
+ }
340
+ _ => unreachable!(),
266
341
  },
267
- Listener::UnixTls((listener, acceptor)) => TokioListener::UnixTls {
268
- listener: TokioUnixListener::from_std(UnixListener::try_clone(listener).unwrap())
269
- .unwrap(),
270
- acceptor: acceptor.clone(),
342
+ BindAddress::UnixSocket(_) => match bind.tls_config {
343
+ Some(tls_config) => Listener::UnixTls((
344
+ revive_unix_socket(fd)?,
345
+ tls_config.build_acceptor().unwrap(),
346
+ )),
347
+ None => Listener::Unix(revive_unix_socket(fd)?),
271
348
  },
272
- }
349
+ };
350
+ Ok(bound)
273
351
  }
274
352
  }
275
353
 
@@ -282,12 +360,18 @@ impl TryFrom<Bind> for Listener {
282
360
  BindProtocol::Http => Listener::Tcp(connect_tcp_socket(addr, bind.port.unwrap())?),
283
361
  BindProtocol::Https => {
284
362
  let tcp_listener = connect_tcp_socket(addr, bind.port.unwrap())?;
285
- Listener::TcpTls((tcp_listener, bind.tls_config.unwrap()))
363
+ Listener::TcpTls((
364
+ tcp_listener,
365
+ bind.tls_config.unwrap().build_acceptor().unwrap(),
366
+ ))
286
367
  }
287
368
  _ => unreachable!(),
288
369
  },
289
370
  BindAddress::UnixSocket(path) => match bind.tls_config {
290
- Some(tls_config) => Listener::UnixTls((connect_unix_socket(&path)?, tls_config)),
371
+ Some(tls_config) => Listener::UnixTls((
372
+ connect_unix_socket(&path)?,
373
+ tls_config.build_acceptor().unwrap(),
374
+ )),
291
375
  None => Listener::Unix(connect_unix_socket(&path)?),
292
376
  },
293
377
  };
@@ -295,6 +379,27 @@ impl TryFrom<Bind> for Listener {
295
379
  }
296
380
  }
297
381
 
382
+ fn revive_tcp_socket(fd: RawFd) -> Result<TcpListener> {
383
+ let socket = unsafe { Socket::from_raw_fd(fd) };
384
+ socket.set_reuse_port(true).ok();
385
+ socket.set_reuse_address(true).ok();
386
+ socket.set_nonblocking(true).ok();
387
+ socket.set_nodelay(true).ok();
388
+ socket.set_recv_buffer_size(262_144).ok();
389
+ socket.set_cloexec(true)?;
390
+ socket.listen(1024)?;
391
+ Ok(socket.into())
392
+ }
393
+
394
+ fn revive_unix_socket(fd: RawFd) -> Result<UnixListener> {
395
+ let socket = unsafe { Socket::from_raw_fd(fd) };
396
+ socket.set_nonblocking(true).ok();
397
+ socket.listen(1024)?;
398
+ socket.set_cloexec(true)?;
399
+
400
+ Ok(socket.into())
401
+ }
402
+
298
403
  fn connect_tcp_socket(addr: IpAddr, port: u16) -> Result<TcpListener> {
299
404
  let domain = match addr {
300
405
  IpAddr::V4(_) => Domain::IPV4,
@@ -302,11 +407,12 @@ fn connect_tcp_socket(addr: IpAddr, port: u16) -> Result<TcpListener> {
302
407
  };
303
408
  let socket = Socket::new(domain, Type::STREAM, Some(Protocol::TCP))?;
304
409
  let socket_address: SocketAddr = SocketAddr::new(addr, port);
305
- socket.set_reuse_port(true).ok();
306
410
  socket.set_reuse_address(true).ok();
411
+ socket.set_reuse_port(true).ok();
307
412
  socket.set_nonblocking(true).ok();
308
413
  socket.set_nodelay(true).ok();
309
414
  socket.set_recv_buffer_size(262_144).ok();
415
+ socket.set_only_v6(false).ok();
310
416
  socket.bind(&socket_address.into())?;
311
417
  socket.listen(1024)?;
312
418
  Ok(socket.into())
@@ -319,7 +425,6 @@ fn connect_unix_socket(path: &PathBuf) -> Result<UnixListener> {
319
425
 
320
426
  let socket_address = socket2::SockAddr::unix(path)?;
321
427
 
322
- info!("Binding to {:?}", path);
323
428
  socket.bind(&socket_address)?;
324
429
  socket.listen(1024)?;
325
430
 
@@ -0,0 +1,4 @@
1
+ pub mod bind;
2
+ pub mod bind_protocol;
3
+ pub mod listener;
4
+ pub mod tls;