itsi 0.1.7 → 0.1.9
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.
- checksums.yaml +4 -4
- data/Rakefile +21 -0
- data/crates/itsi_error/src/from.rs +26 -29
- data/crates/itsi_server/Cargo.lock +2956 -0
- data/crates/itsi_server/Cargo.toml +1 -1
- data/crates/itsi_server/src/lib.rs +5 -0
- data/crates/itsi_server/src/request/itsi_request.rs +37 -9
- data/crates/itsi_server/src/response/itsi_response.rs +12 -2
- data/crates/itsi_server/src/server/bind.rs +4 -3
- data/crates/itsi_server/src/server/itsi_server.rs +128 -78
- data/crates/itsi_server/src/server/listener.rs +98 -107
- data/crates/itsi_server/src/server/serve_strategy/single_mode.rs +40 -24
- data/crates/itsi_server/src/server/signal.rs +7 -0
- data/crates/itsi_server/src/server/thread_worker.rs +3 -4
- data/crates/itsi_server/src/server/tls.rs +20 -13
- data/crates/itsi_tracing/src/lib.rs +18 -1
- data/gems/scheduler/Cargo.lock +12 -12
- data/gems/scheduler/ext/itsi_error/src/from.rs +26 -29
- data/gems/scheduler/ext/itsi_server/Cargo.lock +2956 -0
- data/gems/scheduler/ext/itsi_server/Cargo.toml +1 -1
- data/gems/scheduler/ext/itsi_server/src/lib.rs +5 -0
- data/gems/scheduler/ext/itsi_server/src/request/itsi_request.rs +37 -9
- data/gems/scheduler/ext/itsi_server/src/response/itsi_response.rs +12 -2
- data/gems/scheduler/ext/itsi_server/src/server/bind.rs +4 -3
- data/gems/scheduler/ext/itsi_server/src/server/itsi_server.rs +128 -78
- data/gems/scheduler/ext/itsi_server/src/server/listener.rs +98 -107
- data/gems/scheduler/ext/itsi_server/src/server/serve_strategy/single_mode.rs +40 -24
- data/gems/scheduler/ext/itsi_server/src/server/signal.rs +7 -0
- data/gems/scheduler/ext/itsi_server/src/server/thread_worker.rs +3 -4
- data/gems/scheduler/ext/itsi_server/src/server/tls.rs +20 -13
- data/gems/scheduler/ext/itsi_tracing/src/lib.rs +18 -1
- data/gems/scheduler/lib/itsi/scheduler/version.rb +1 -1
- data/gems/scheduler/test/test_address_resolve.rb +0 -1
- data/gems/scheduler/test/test_file_io.rb +0 -1
- data/gems/scheduler/test/test_kernel_sleep.rb +3 -4
- data/gems/server/Cargo.lock +2917 -0
- data/gems/server/Cargo.toml +7 -0
- data/gems/server/Rakefile +8 -1
- data/gems/server/ext/itsi_error/src/from.rs +26 -29
- data/gems/server/ext/itsi_server/Cargo.lock +2956 -0
- data/gems/server/ext/itsi_server/Cargo.toml +1 -1
- data/gems/server/ext/itsi_server/src/lib.rs +5 -0
- data/gems/server/ext/itsi_server/src/request/itsi_request.rs +37 -9
- data/gems/server/ext/itsi_server/src/response/itsi_response.rs +12 -2
- data/gems/server/ext/itsi_server/src/server/bind.rs +4 -3
- data/gems/server/ext/itsi_server/src/server/itsi_server.rs +128 -78
- data/gems/server/ext/itsi_server/src/server/listener.rs +98 -107
- data/gems/server/ext/itsi_server/src/server/serve_strategy/single_mode.rs +40 -24
- data/gems/server/ext/itsi_server/src/server/signal.rs +7 -0
- data/gems/server/ext/itsi_server/src/server/thread_worker.rs +3 -4
- data/gems/server/ext/itsi_server/src/server/tls.rs +20 -13
- data/gems/server/ext/itsi_tracing/src/lib.rs +18 -1
- data/gems/server/lib/itsi/index.html +91 -0
- data/gems/server/lib/itsi/request.rb +29 -21
- data/gems/server/lib/itsi/server/rack/handler/itsi.rb +3 -4
- data/gems/server/lib/itsi/server/rack_interface.rb +79 -0
- data/gems/server/lib/itsi/server/scheduler_interface.rb +21 -0
- data/gems/server/lib/itsi/server/scheduler_mode.rb +1 -1
- data/gems/server/lib/itsi/server/signal_trap.rb +24 -0
- data/gems/server/lib/itsi/server/version.rb +1 -1
- data/gems/server/lib/itsi/server.rb +68 -82
- data/gems/server/test/helpers/test_helper.rb +28 -0
- data/gems/server/test/test_itsi_server.rb +275 -3
- data/lib/itsi/version.rb +1 -1
- data/sandbox/deploy/main.tf +238 -0
- data/sandbox/deploy/outputs.tf +4 -0
- data/sandbox/deploy/vars.tf +11 -0
- data/sandbox/falcon_benchmark/Gemfile +10 -0
- data/sandbox/falcon_benchmark/Gemfile.lock +140 -0
- data/sandbox/falcon_benchmark/config.ru +54 -0
- data/sandbox/itsi_sandbox_async/Gemfile +10 -0
- data/sandbox/itsi_sandbox_async/Gemfile.lock +69 -0
- data/sandbox/itsi_sandbox_async/config.ru +10 -0
- data/sandbox/itsi_sandbox_hanami/.env +2 -0
- data/sandbox/itsi_sandbox_hanami/.gitignore +6 -0
- data/sandbox/itsi_sandbox_hanami/.rspec +1 -0
- data/sandbox/itsi_sandbox_hanami/Gemfile +49 -0
- data/sandbox/itsi_sandbox_hanami/Gemfile.lock +440 -0
- data/sandbox/itsi_sandbox_hanami/Guardfile +9 -0
- data/sandbox/itsi_sandbox_hanami/Procfile.dev +2 -0
- data/sandbox/itsi_sandbox_hanami/README.md +1 -0
- data/sandbox/itsi_sandbox_hanami/Rakefile +3 -0
- data/sandbox/itsi_sandbox_hanami/app/action.rb +12 -0
- data/sandbox/itsi_sandbox_hanami/app/actions/.keep +0 -0
- data/sandbox/itsi_sandbox_hanami/app/assets/css/app.css +5 -0
- data/sandbox/itsi_sandbox_hanami/app/assets/images/favicon.ico +0 -0
- data/sandbox/itsi_sandbox_hanami/app/assets/js/app.js +1 -0
- data/sandbox/itsi_sandbox_hanami/app/db/relation.rb +10 -0
- data/sandbox/itsi_sandbox_hanami/app/db/repo.rb +10 -0
- data/sandbox/itsi_sandbox_hanami/app/db/struct.rb +10 -0
- data/sandbox/itsi_sandbox_hanami/app/operation.rb +9 -0
- data/sandbox/itsi_sandbox_hanami/app/relations/.keep +0 -0
- data/sandbox/itsi_sandbox_hanami/app/repos/.keep +0 -0
- data/sandbox/itsi_sandbox_hanami/app/structs/.keep +0 -0
- data/sandbox/itsi_sandbox_hanami/app/templates/layouts/app.html.erb +14 -0
- data/sandbox/itsi_sandbox_hanami/app/view.rb +9 -0
- data/sandbox/itsi_sandbox_hanami/app/views/helpers.rb +10 -0
- data/sandbox/itsi_sandbox_hanami/bin/dev +8 -0
- data/sandbox/itsi_sandbox_hanami/config/app.rb +8 -0
- data/sandbox/itsi_sandbox_hanami/config/assets.js +16 -0
- data/sandbox/itsi_sandbox_hanami/config/db/migrate/.keep +0 -0
- data/sandbox/itsi_sandbox_hanami/config/db/seeds.rb +15 -0
- data/sandbox/itsi_sandbox_hanami/config/puma.rb +47 -0
- data/sandbox/itsi_sandbox_hanami/config/routes.rb +7 -0
- data/sandbox/itsi_sandbox_hanami/config/settings.rb +9 -0
- data/sandbox/itsi_sandbox_hanami/config.ru +5 -0
- data/sandbox/itsi_sandbox_hanami/db/.keep +0 -0
- data/sandbox/itsi_sandbox_hanami/lib/itsi_hanami/types.rb +11 -0
- data/sandbox/itsi_sandbox_hanami/lib/tasks/.keep +0 -0
- data/sandbox/itsi_sandbox_hanami/package-lock.json +946 -0
- data/sandbox/itsi_sandbox_hanami/package.json +8 -0
- data/sandbox/itsi_sandbox_hanami/spec/requests/root_spec.rb +11 -0
- data/sandbox/itsi_sandbox_hanami/spec/spec_helper.rb +9 -0
- data/sandbox/itsi_sandbox_hanami/spec/support/db/cleaning.rb +42 -0
- data/sandbox/itsi_sandbox_hanami/spec/support/db.rb +10 -0
- data/sandbox/itsi_sandbox_hanami/spec/support/features.rb +5 -0
- data/sandbox/itsi_sandbox_hanami/spec/support/operations.rb +8 -0
- data/sandbox/itsi_sandbox_hanami/spec/support/requests.rb +13 -0
- data/sandbox/itsi_sandbox_hanami/spec/support/rspec.rb +61 -0
- data/sandbox/itsi_sandbox_rack/Gemfile +17 -0
- data/sandbox/itsi_sandbox_rack/Gemfile.lock +153 -0
- data/sandbox/itsi_sandbox_rack/config.ru +18 -0
- data/sandbox/itsi_sandbox_rack_lint/Gemfile +7 -0
- data/sandbox/itsi_sandbox_rack_lint/Gemfile.lock +27 -0
- data/sandbox/itsi_sandbox_rack_lint/config.ru +3 -0
- data/sandbox/itsi_sandbox_rails/.dockerignore +51 -0
- data/sandbox/itsi_sandbox_rails/.gitattributes +9 -0
- data/sandbox/itsi_sandbox_rails/.github/dependabot.yml +12 -0
- data/sandbox/itsi_sandbox_rails/.github/workflows/ci.yml +90 -0
- data/sandbox/itsi_sandbox_rails/.gitignore +34 -0
- data/sandbox/itsi_sandbox_rails/.kamal/hooks/docker-setup.sample +3 -0
- data/sandbox/itsi_sandbox_rails/.kamal/hooks/post-app-boot.sample +3 -0
- data/sandbox/itsi_sandbox_rails/.kamal/hooks/post-deploy.sample +14 -0
- data/sandbox/itsi_sandbox_rails/.kamal/hooks/post-proxy-reboot.sample +3 -0
- data/sandbox/itsi_sandbox_rails/.kamal/hooks/pre-app-boot.sample +3 -0
- data/sandbox/itsi_sandbox_rails/.kamal/hooks/pre-build.sample +51 -0
- data/sandbox/itsi_sandbox_rails/.kamal/hooks/pre-connect.sample +47 -0
- data/sandbox/itsi_sandbox_rails/.kamal/hooks/pre-deploy.sample +109 -0
- data/sandbox/itsi_sandbox_rails/.kamal/hooks/pre-proxy-reboot.sample +3 -0
- data/sandbox/itsi_sandbox_rails/.kamal/secrets +17 -0
- data/sandbox/itsi_sandbox_rails/.rubocop.yml +8 -0
- data/sandbox/itsi_sandbox_rails/.ruby-version +1 -0
- data/sandbox/itsi_sandbox_rails/Dockerfile +72 -0
- data/sandbox/itsi_sandbox_rails/Gemfile +72 -0
- data/sandbox/itsi_sandbox_rails/Gemfile.lock +480 -0
- data/sandbox/itsi_sandbox_rails/README.md +24 -0
- data/sandbox/itsi_sandbox_rails/Rakefile +6 -0
- data/sandbox/itsi_sandbox_rails/app/assets/images/.keep +0 -0
- data/sandbox/itsi_sandbox_rails/app/assets/stylesheets/application.css +10 -0
- data/sandbox/itsi_sandbox_rails/app/controllers/application_controller.rb +4 -0
- data/sandbox/itsi_sandbox_rails/app/controllers/concerns/.keep +0 -0
- data/sandbox/itsi_sandbox_rails/app/controllers/home_controller.rb +51 -0
- data/sandbox/itsi_sandbox_rails/app/controllers/live_controller.rb +41 -0
- data/sandbox/itsi_sandbox_rails/app/controllers/uploads_controller.rb +32 -0
- data/sandbox/itsi_sandbox_rails/app/helpers/application_helper.rb +2 -0
- data/sandbox/itsi_sandbox_rails/app/javascript/application.js +3 -0
- data/sandbox/itsi_sandbox_rails/app/javascript/controllers/application.js +9 -0
- data/sandbox/itsi_sandbox_rails/app/javascript/controllers/hello_controller.js +7 -0
- data/sandbox/itsi_sandbox_rails/app/javascript/controllers/index.js +4 -0
- data/sandbox/itsi_sandbox_rails/app/jobs/application_job.rb +7 -0
- data/sandbox/itsi_sandbox_rails/app/mailers/application_mailer.rb +4 -0
- data/sandbox/itsi_sandbox_rails/app/models/application_record.rb +3 -0
- data/sandbox/itsi_sandbox_rails/app/models/concerns/.keep +0 -0
- data/sandbox/itsi_sandbox_rails/app/models/post.rb +2 -0
- data/sandbox/itsi_sandbox_rails/app/views/layouts/application.html.erb +28 -0
- data/sandbox/itsi_sandbox_rails/app/views/layouts/mailer.html.erb +13 -0
- data/sandbox/itsi_sandbox_rails/app/views/layouts/mailer.text.erb +1 -0
- data/sandbox/itsi_sandbox_rails/app/views/pwa/manifest.json.erb +22 -0
- data/sandbox/itsi_sandbox_rails/app/views/pwa/service-worker.js +26 -0
- data/sandbox/itsi_sandbox_rails/bin/brakeman +7 -0
- data/sandbox/itsi_sandbox_rails/bin/bundle +109 -0
- data/sandbox/itsi_sandbox_rails/bin/dev +2 -0
- data/sandbox/itsi_sandbox_rails/bin/docker-entrypoint +14 -0
- data/sandbox/itsi_sandbox_rails/bin/importmap +4 -0
- data/sandbox/itsi_sandbox_rails/bin/jobs +6 -0
- data/sandbox/itsi_sandbox_rails/bin/kamal +27 -0
- data/sandbox/itsi_sandbox_rails/bin/rails +4 -0
- data/sandbox/itsi_sandbox_rails/bin/rake +4 -0
- data/sandbox/itsi_sandbox_rails/bin/rubocop +8 -0
- data/sandbox/itsi_sandbox_rails/bin/setup +34 -0
- data/sandbox/itsi_sandbox_rails/bin/thrust +5 -0
- data/sandbox/itsi_sandbox_rails/config/application.rb +61 -0
- data/sandbox/itsi_sandbox_rails/config/boot.rb +4 -0
- data/sandbox/itsi_sandbox_rails/config/cable.yml +17 -0
- data/sandbox/itsi_sandbox_rails/config/cache.yml +16 -0
- data/sandbox/itsi_sandbox_rails/config/credentials.yml.enc +1 -0
- data/sandbox/itsi_sandbox_rails/config/database.yml +40 -0
- data/sandbox/itsi_sandbox_rails/config/deploy.yml +116 -0
- data/sandbox/itsi_sandbox_rails/config/environment.rb +5 -0
- data/sandbox/itsi_sandbox_rails/config/environments/development.rb +72 -0
- data/sandbox/itsi_sandbox_rails/config/environments/production.rb +90 -0
- data/sandbox/itsi_sandbox_rails/config/environments/test.rb +53 -0
- data/sandbox/itsi_sandbox_rails/config/importmap.rb +7 -0
- data/sandbox/itsi_sandbox_rails/config/initializers/assets.rb +7 -0
- data/sandbox/itsi_sandbox_rails/config/initializers/content_security_policy.rb +25 -0
- data/sandbox/itsi_sandbox_rails/config/initializers/filter_parameter_logging.rb +8 -0
- data/sandbox/itsi_sandbox_rails/config/initializers/inflections.rb +16 -0
- data/sandbox/itsi_sandbox_rails/config/locales/en.yml +31 -0
- data/sandbox/itsi_sandbox_rails/config/puma.rb +41 -0
- data/sandbox/itsi_sandbox_rails/config/queue.yml +18 -0
- data/sandbox/itsi_sandbox_rails/config/recurring.yml +10 -0
- data/sandbox/itsi_sandbox_rails/config/routes.rb +21 -0
- data/sandbox/itsi_sandbox_rails/config/storage.yml +34 -0
- data/sandbox/itsi_sandbox_rails/config.ru +7 -0
- data/sandbox/itsi_sandbox_rails/db/cable_schema.rb +11 -0
- data/sandbox/itsi_sandbox_rails/db/cache_schema.rb +14 -0
- data/sandbox/itsi_sandbox_rails/db/migrate/20250301041554_create_posts.rb +10 -0
- data/sandbox/itsi_sandbox_rails/db/queue_schema.rb +129 -0
- data/sandbox/itsi_sandbox_rails/db/schema.rb +23 -0
- data/sandbox/itsi_sandbox_rails/db/seeds.rb +9 -0
- data/sandbox/itsi_sandbox_rails/lib/tasks/.keep +0 -0
- data/sandbox/itsi_sandbox_rails/log/.keep +0 -0
- data/sandbox/itsi_sandbox_rails/public/400.html +114 -0
- data/sandbox/itsi_sandbox_rails/public/404.html +114 -0
- data/sandbox/itsi_sandbox_rails/public/406-unsupported-browser.html +114 -0
- data/sandbox/itsi_sandbox_rails/public/422.html +114 -0
- data/sandbox/itsi_sandbox_rails/public/500.html +114 -0
- data/sandbox/itsi_sandbox_rails/public/icon.png +0 -0
- data/sandbox/itsi_sandbox_rails/public/icon.svg +3 -0
- data/sandbox/itsi_sandbox_rails/public/robots.txt +1 -0
- data/sandbox/itsi_sandbox_rails/script/.keep +0 -0
- data/sandbox/itsi_sandbox_rails/storage/.keep +0 -0
- data/sandbox/itsi_sandbox_rails/test/application_system_test_case.rb +5 -0
- data/sandbox/itsi_sandbox_rails/test/controllers/.keep +0 -0
- data/sandbox/itsi_sandbox_rails/test/fixtures/files/.keep +0 -0
- data/sandbox/itsi_sandbox_rails/test/fixtures/posts.yml +9 -0
- data/sandbox/itsi_sandbox_rails/test/helpers/.keep +0 -0
- data/sandbox/itsi_sandbox_rails/test/integration/.keep +0 -0
- data/sandbox/itsi_sandbox_rails/test/mailers/.keep +0 -0
- data/sandbox/itsi_sandbox_rails/test/models/.keep +0 -0
- data/sandbox/itsi_sandbox_rails/test/models/post_test.rb +7 -0
- data/sandbox/itsi_sandbox_rails/test/system/.keep +0 -0
- data/sandbox/itsi_sandbox_rails/test/test_helper.rb +15 -0
- data/sandbox/itsi_sandbox_rails/tmp/.keep +0 -0
- data/sandbox/itsi_sandbox_rails/tmp/pids/.keep +0 -0
- data/sandbox/itsi_sandbox_rails/tmp/storage/.keep +0 -0
- data/sandbox/itsi_sandbox_rails/vendor/.keep +0 -0
- data/sandbox/itsi_sandbox_rails/vendor/javascript/.keep +0 -0
- data/sandbox/itsi_sandbox_roda/Gemfile +5 -0
- data/sandbox/itsi_sandbox_roda/Gemfile.lock +44 -0
- data/sandbox/itsi_sandbox_roda/config.ru +39 -0
- data/sandbox/itsi_sinatra/Gemfile +9 -0
- data/sandbox/itsi_sinatra/Gemfile.lock +81 -0
- data/sandbox/itsi_sinatra/app.rb +9 -0
- data/sandbox/pebble/docker-compose.yml +11 -0
- data/tasks.txt +4 -4
- metadata +199 -10
- data/gems/server/lib/itsi/signals.rb +0 -23
- data/gems/server/test/test_helper.rb +0 -7
@@ -1,6 +1,7 @@
|
|
1
1
|
use super::bind::{Bind, BindAddress};
|
2
2
|
use super::bind_protocol::BindProtocol;
|
3
3
|
use super::io_stream::IoStream;
|
4
|
+
use super::serve_strategy::single_mode::RunningPhase;
|
4
5
|
use super::tls::ItsiTlsAcceptor;
|
5
6
|
use itsi_error::{ItsiError, Result};
|
6
7
|
use itsi_tracing::info;
|
@@ -11,6 +12,7 @@ use std::{os::unix::net::UnixListener, path::PathBuf};
|
|
11
12
|
use tokio::net::TcpListener as TokioTcpListener;
|
12
13
|
use tokio::net::UnixListener as TokioUnixListener;
|
13
14
|
use tokio::net::{unix, TcpStream, UnixStream};
|
15
|
+
use tokio::sync::watch::Receiver;
|
14
16
|
use tokio_rustls::TlsAcceptor;
|
15
17
|
use tokio_stream::StreamExt;
|
16
18
|
use tracing::error;
|
@@ -23,45 +25,79 @@ pub(crate) enum Listener {
|
|
23
25
|
}
|
24
26
|
|
25
27
|
pub(crate) enum TokioListener {
|
26
|
-
Tcp
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
Unix {
|
38
|
-
listener: TokioUnixListener,
|
39
|
-
},
|
40
|
-
UnixTls {
|
41
|
-
listener: TokioUnixListener,
|
42
|
-
acceptor: ItsiTlsAcceptor,
|
43
|
-
},
|
28
|
+
Tcp(TokioTcpListener),
|
29
|
+
TcpTls(TokioTcpListener, ItsiTlsAcceptor),
|
30
|
+
Unix(TokioUnixListener),
|
31
|
+
UnixTls(TokioUnixListener, ItsiTlsAcceptor),
|
32
|
+
}
|
33
|
+
|
34
|
+
#[derive(Debug, Clone)]
|
35
|
+
pub struct ListenerInfo {
|
36
|
+
pub host: String,
|
37
|
+
pub port: u16,
|
38
|
+
pub scheme: String,
|
44
39
|
}
|
45
40
|
|
46
41
|
impl TokioListener {
|
47
|
-
pub fn
|
42
|
+
pub fn listener_info(&self) -> ListenerInfo {
|
48
43
|
match self {
|
49
|
-
TokioListener::Tcp
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
44
|
+
TokioListener::Tcp(listener) => ListenerInfo {
|
45
|
+
host: listener
|
46
|
+
.local_addr()
|
47
|
+
.unwrap()
|
48
|
+
.ip()
|
49
|
+
.to_canonical()
|
50
|
+
.to_string(),
|
51
|
+
port: listener.local_addr().unwrap().port(),
|
52
|
+
scheme: "http".to_string(),
|
53
|
+
},
|
54
|
+
TokioListener::TcpTls(listener, _) => ListenerInfo {
|
55
|
+
host: listener
|
56
|
+
.local_addr()
|
57
|
+
.unwrap()
|
58
|
+
.ip()
|
59
|
+
.to_canonical()
|
60
|
+
.to_string(),
|
61
|
+
port: listener.local_addr().unwrap().port(),
|
62
|
+
scheme: "https".to_string(),
|
63
|
+
},
|
64
|
+
TokioListener::Unix(listener) => ListenerInfo {
|
65
|
+
host: listener
|
66
|
+
.local_addr()
|
67
|
+
.unwrap()
|
68
|
+
.as_pathname()
|
69
|
+
.unwrap()
|
70
|
+
.to_str()
|
71
|
+
.unwrap()
|
72
|
+
.to_owned(),
|
73
|
+
port: 0,
|
74
|
+
scheme: "unix".to_string(),
|
75
|
+
},
|
76
|
+
TokioListener::UnixTls(listener, _) => ListenerInfo {
|
77
|
+
host: listener
|
78
|
+
.local_addr()
|
79
|
+
.unwrap()
|
80
|
+
.as_pathname()
|
81
|
+
.unwrap()
|
82
|
+
.to_str()
|
83
|
+
.unwrap()
|
84
|
+
.to_owned(),
|
85
|
+
port: 0,
|
86
|
+
scheme: "ssl".to_string(),
|
87
|
+
},
|
88
|
+
}
|
54
89
|
}
|
90
|
+
|
55
91
|
pub(crate) async fn accept(&self) -> Result<IoStream> {
|
56
92
|
match self {
|
57
|
-
TokioListener::Tcp
|
58
|
-
TokioListener::TcpTls {
|
59
|
-
listener, acceptor
|
60
|
-
}
|
61
|
-
TokioListener::Unix
|
62
|
-
TokioListener::UnixTls {
|
63
|
-
listener, acceptor
|
64
|
-
}
|
93
|
+
TokioListener::Tcp(listener) => TokioListener::accept_tcp(listener).await,
|
94
|
+
TokioListener::TcpTls(listener, acceptor) => {
|
95
|
+
TokioListener::accept_tls(listener, acceptor).await
|
96
|
+
}
|
97
|
+
TokioListener::Unix(listener) => TokioListener::accept_unix(listener).await,
|
98
|
+
TokioListener::UnixTls(listener, acceptor) => {
|
99
|
+
TokioListener::accept_unix_tls(listener, acceptor).await
|
100
|
+
}
|
65
101
|
}
|
66
102
|
}
|
67
103
|
|
@@ -70,17 +106,24 @@ impl TokioListener {
|
|
70
106
|
Self::to_tokio_io(Stream::TcpStream(tcp_stream), None).await
|
71
107
|
}
|
72
108
|
|
73
|
-
pub async fn spawn_state_task(&self) {
|
74
|
-
if let TokioListener::TcpTls
|
75
|
-
|
76
|
-
|
77
|
-
|
109
|
+
pub async fn spawn_state_task(&self, mut shutdown_receiver: Receiver<RunningPhase>) {
|
110
|
+
if let TokioListener::TcpTls(
|
111
|
+
_,
|
112
|
+
ItsiTlsAcceptor::Automatic(_acme_acceptor, state, _server_config),
|
113
|
+
) = self
|
78
114
|
{
|
79
115
|
let mut state = state.lock().await;
|
80
116
|
loop {
|
81
|
-
|
82
|
-
|
83
|
-
|
117
|
+
tokio::select! {
|
118
|
+
stream_event = StreamExt::next(&mut *state) => {
|
119
|
+
match stream_event {
|
120
|
+
Some(event) => info!("ACME Event: {:?}", event),
|
121
|
+
None => error!("Received no acme event"),
|
122
|
+
}
|
123
|
+
},
|
124
|
+
_ = shutdown_receiver.changed() => {
|
125
|
+
break;
|
126
|
+
}
|
84
127
|
}
|
85
128
|
}
|
86
129
|
}
|
@@ -175,33 +218,6 @@ impl TokioListener {
|
|
175
218
|
},
|
176
219
|
}
|
177
220
|
}
|
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
221
|
}
|
206
222
|
|
207
223
|
enum Stream {
|
@@ -227,48 +243,22 @@ impl std::fmt::Display for SockAddr {
|
|
227
243
|
}
|
228
244
|
|
229
245
|
impl Listener {
|
230
|
-
pub fn unbind(self) {
|
231
|
-
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
|
-
};
|
237
|
-
}
|
238
246
|
pub fn to_tokio_listener(&self) -> TokioListener {
|
239
247
|
match self {
|
240
|
-
Listener::Tcp(listener) => TokioListener::Tcp
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
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(),
|
266
|
-
},
|
267
|
-
Listener::UnixTls((listener, acceptor)) => TokioListener::UnixTls {
|
268
|
-
listener: TokioUnixListener::from_std(UnixListener::try_clone(listener).unwrap())
|
269
|
-
.unwrap(),
|
270
|
-
acceptor: acceptor.clone(),
|
271
|
-
},
|
248
|
+
Listener::Tcp(listener) => TokioListener::Tcp(
|
249
|
+
TokioTcpListener::from_std(TcpListener::try_clone(listener).unwrap()).unwrap(),
|
250
|
+
),
|
251
|
+
Listener::TcpTls((listener, acceptor)) => TokioListener::TcpTls(
|
252
|
+
TokioTcpListener::from_std(TcpListener::try_clone(listener).unwrap()).unwrap(),
|
253
|
+
acceptor.clone(),
|
254
|
+
),
|
255
|
+
Listener::Unix(listener) => TokioListener::Unix(
|
256
|
+
TokioUnixListener::from_std(UnixListener::try_clone(listener).unwrap()).unwrap(),
|
257
|
+
),
|
258
|
+
Listener::UnixTls((listener, acceptor)) => TokioListener::UnixTls(
|
259
|
+
TokioUnixListener::from_std(UnixListener::try_clone(listener).unwrap()).unwrap(),
|
260
|
+
acceptor.clone(),
|
261
|
+
),
|
272
262
|
}
|
273
263
|
}
|
274
264
|
}
|
@@ -307,6 +297,7 @@ fn connect_tcp_socket(addr: IpAddr, port: u16) -> Result<TcpListener> {
|
|
307
297
|
socket.set_nonblocking(true).ok();
|
308
298
|
socket.set_nodelay(true).ok();
|
309
299
|
socket.set_recv_buffer_size(262_144).ok();
|
300
|
+
info!("Binding to {:?}", socket_address);
|
310
301
|
socket.bind(&socket_address.into())?;
|
311
302
|
socket.listen(1024)?;
|
312
303
|
Ok(socket.into())
|
@@ -4,7 +4,7 @@ use crate::{
|
|
4
4
|
io_stream::IoStream,
|
5
5
|
itsi_server::{RequestJob, Server},
|
6
6
|
lifecycle_event::LifecycleEvent,
|
7
|
-
listener::{Listener,
|
7
|
+
listener::{Listener, ListenerInfo},
|
8
8
|
thread_worker::{build_thread_workers, ThreadWorker},
|
9
9
|
},
|
10
10
|
};
|
@@ -25,7 +25,10 @@ use std::{
|
|
25
25
|
};
|
26
26
|
use tokio::{
|
27
27
|
runtime::{Builder as RuntimeBuilder, Runtime},
|
28
|
-
sync::
|
28
|
+
sync::{
|
29
|
+
broadcast,
|
30
|
+
watch::{self, Sender},
|
31
|
+
},
|
29
32
|
task::JoinSet,
|
30
33
|
};
|
31
34
|
use tracing::instrument;
|
@@ -55,7 +58,7 @@ impl SingleMode {
|
|
55
58
|
let (thread_workers, sender) = build_thread_workers(
|
56
59
|
Pid::this(),
|
57
60
|
NonZeroU8::try_from(server.threads).unwrap(),
|
58
|
-
server.app,
|
61
|
+
server.app.clone(),
|
59
62
|
server.scheduler_class.clone(),
|
60
63
|
)?;
|
61
64
|
Ok(Self {
|
@@ -80,6 +83,9 @@ impl SingleMode {
|
|
80
83
|
}
|
81
84
|
|
82
85
|
pub fn stop(&self) -> Result<()> {
|
86
|
+
self.lifecycle_channel
|
87
|
+
.send(LifecycleEvent::Shutdown)
|
88
|
+
.expect("Failed to send shutdown event");
|
83
89
|
Ok(())
|
84
90
|
}
|
85
91
|
|
@@ -87,18 +93,28 @@ impl SingleMode {
|
|
87
93
|
pub fn run(self: Arc<Self>) -> Result<()> {
|
88
94
|
let mut listener_task_set = JoinSet::new();
|
89
95
|
let self_ref = Arc::new(self);
|
90
|
-
self_ref.build_runtime()
|
96
|
+
let runtime = self_ref.build_runtime();
|
91
97
|
|
92
|
-
|
93
|
-
|
98
|
+
runtime.block_on(async {
|
99
|
+
let tokio_listeners = self_ref
|
100
|
+
.listeners
|
101
|
+
.iter()
|
102
|
+
.map(|list| Arc::new(list.to_tokio_listener()))
|
103
|
+
.collect::<Vec<_>>();
|
104
|
+
let (shutdown_sender, _) = watch::channel::<RunningPhase>(RunningPhase::Running);
|
105
|
+
for listener in tokio_listeners.iter() {
|
94
106
|
let mut lifecycle_rx = self_ref.lifecycle_channel.subscribe();
|
107
|
+
let listener_info = Arc::new(listener.listener_info());
|
95
108
|
let self_ref = self_ref.clone();
|
96
109
|
let listener = listener.clone();
|
97
|
-
let
|
98
|
-
let listener_clone = listener.clone();
|
110
|
+
let shutdown_sender = shutdown_sender.clone();
|
99
111
|
|
100
|
-
|
101
|
-
|
112
|
+
|
113
|
+
let listener_clone = listener.clone();
|
114
|
+
let mut shutdown_receiver = shutdown_sender.clone().subscribe();
|
115
|
+
let shutdown_receiver_clone = shutdown_receiver.clone();
|
116
|
+
listener_task_set.spawn(async move {
|
117
|
+
listener_clone.spawn_state_task(shutdown_receiver_clone).await;
|
102
118
|
});
|
103
119
|
|
104
120
|
listener_task_set.spawn(async move {
|
@@ -107,8 +123,11 @@ impl SingleMode {
|
|
107
123
|
tokio::select! {
|
108
124
|
accept_result = listener.accept() => match accept_result {
|
109
125
|
Ok(accept_result) => {
|
110
|
-
|
111
|
-
|
126
|
+
match strategy.serve_connection(accept_result, listener_info.clone(), shutdown_receiver.clone()).await {
|
127
|
+
Ok(_) => {
|
128
|
+
debug!("Connection accepted and served");
|
129
|
+
},
|
130
|
+
Err(e) => error!("Error in serve_connection {:?}", e)
|
112
131
|
}
|
113
132
|
},
|
114
133
|
Err(e) => debug!("Listener.accept failed {:?}", e),
|
@@ -130,24 +149,24 @@ impl SingleMode {
|
|
130
149
|
}
|
131
150
|
}
|
132
151
|
}
|
133
|
-
if let Ok(listener) = Arc::try_unwrap(listener){
|
134
|
-
listener.unbind();
|
135
|
-
}
|
136
152
|
});
|
137
153
|
|
138
154
|
}
|
139
155
|
|
140
156
|
while let Some(_res) = listener_task_set.join_next().await {}
|
157
|
+
|
141
158
|
});
|
159
|
+
runtime.shutdown_timeout(Duration::from_millis(100));
|
142
160
|
|
161
|
+
info!("Runtime has shut down");
|
143
162
|
Ok(())
|
144
163
|
}
|
145
164
|
|
146
165
|
pub(crate) async fn serve_connection(
|
147
166
|
&self,
|
148
167
|
stream: IoStream,
|
149
|
-
listener: Arc<
|
150
|
-
shutdown_channel:
|
168
|
+
listener: Arc<ListenerInfo>,
|
169
|
+
shutdown_channel: watch::Receiver<RunningPhase>,
|
151
170
|
) -> Result<()> {
|
152
171
|
let sender_clone = self.sender.clone();
|
153
172
|
let addr = stream.addr();
|
@@ -209,12 +228,11 @@ impl SingleMode {
|
|
209
228
|
pub async fn handle_lifecycle_event(
|
210
229
|
&self,
|
211
230
|
lifecycle_event: LifecycleEvent,
|
212
|
-
shutdown_sender:
|
231
|
+
shutdown_sender: Sender<RunningPhase>,
|
213
232
|
) -> Result<()> {
|
233
|
+
info!("Handling lifecycle event: {:?}", lifecycle_event);
|
214
234
|
if let LifecycleEvent::Shutdown = lifecycle_event {
|
215
|
-
shutdown_sender
|
216
|
-
.send(RunningPhase::ShutdownPending)
|
217
|
-
.expect("Failed to send shutdown pending signal");
|
235
|
+
shutdown_sender.send(RunningPhase::ShutdownPending).ok();
|
218
236
|
let deadline = Instant::now() + Duration::from_secs_f64(self.server.shutdown_timeout);
|
219
237
|
for worker in &*self.thread_workers {
|
220
238
|
worker.request_shutdown().await;
|
@@ -233,9 +251,7 @@ impl SingleMode {
|
|
233
251
|
}
|
234
252
|
|
235
253
|
info!("Sending shutdown signal");
|
236
|
-
shutdown_sender
|
237
|
-
.send(RunningPhase::Shutdown)
|
238
|
-
.expect("Failed to send shutdown signal");
|
254
|
+
shutdown_sender.send(RunningPhase::Shutdown).ok();
|
239
255
|
self.thread_workers.iter().for_each(|worker| {
|
240
256
|
worker.poll_shutdown(deadline);
|
241
257
|
});
|
@@ -10,6 +10,13 @@ pub static SIGNAL_HANDLER_CHANNEL: LazyLock<(
|
|
10
10
|
broadcast::Receiver<LifecycleEvent>,
|
11
11
|
)> = LazyLock::new(|| sync::broadcast::channel(5));
|
12
12
|
|
13
|
+
pub fn send_shutdown_event() {
|
14
|
+
SIGNAL_HANDLER_CHANNEL
|
15
|
+
.0
|
16
|
+
.send(LifecycleEvent::Shutdown)
|
17
|
+
.expect("Failed to send shutdown event");
|
18
|
+
}
|
19
|
+
|
13
20
|
pub static SIGINT_COUNT: AtomicI8 = AtomicI8::new(0);
|
14
21
|
fn receive_signal(signum: i32, _: sighandler_t) {
|
15
22
|
SIGINT_COUNT.fetch_add(-1, std::sync::atomic::Ordering::SeqCst);
|
@@ -1,7 +1,7 @@
|
|
1
1
|
use super::itsi_server::RequestJob;
|
2
2
|
use crate::{request::itsi_request::ItsiRequest, ITSI_SERVER};
|
3
3
|
use itsi_rb_helpers::{
|
4
|
-
call_with_gvl, call_without_gvl, create_ruby_thread, kill_threads, HeapValue,
|
4
|
+
call_with_gvl, call_without_gvl, create_ruby_thread, kill_threads, HeapVal, HeapValue,
|
5
5
|
};
|
6
6
|
use itsi_tracing::{debug, error, info, warn};
|
7
7
|
use magnus::{
|
@@ -52,7 +52,7 @@ pub struct TerminateWakerSignal(bool);
|
|
52
52
|
pub fn build_thread_workers(
|
53
53
|
pid: Pid,
|
54
54
|
threads: NonZeroU8,
|
55
|
-
app:
|
55
|
+
app: HeapVal,
|
56
56
|
scheduler_class: Option<String>,
|
57
57
|
) -> Result<(Arc<Vec<ThreadWorker>>, async_channel::Sender<RequestJob>)> {
|
58
58
|
let (sender, receiver) = async_channel::bounded(20);
|
@@ -79,11 +79,10 @@ pub fn build_thread_workers(
|
|
79
79
|
}
|
80
80
|
|
81
81
|
pub fn load_app(
|
82
|
-
app:
|
82
|
+
app: HeapVal,
|
83
83
|
scheduler_class: Option<String>,
|
84
84
|
) -> Result<(Opaque<Value>, Option<Opaque<Value>>)> {
|
85
85
|
call_with_gvl(|ruby| {
|
86
|
-
let app = app.get_inner_with(&ruby);
|
87
86
|
let app = Opaque::from(
|
88
87
|
app.funcall::<_, _, Value>(*ID_CALL, ())
|
89
88
|
.expect("Couldn't load app"),
|
@@ -48,23 +48,26 @@ pub fn configure_tls(
|
|
48
48
|
) -> Result<ItsiTlsAcceptor> {
|
49
49
|
let domains = query_params
|
50
50
|
.get("domains")
|
51
|
-
.map(|v| v.split(',').map(String::from).collect::<Vec<_>>())
|
51
|
+
.map(|v| v.split(',').map(String::from).collect::<Vec<_>>())
|
52
|
+
.or_else(|| query_params.get("domain").map(|v| vec![v.to_string()]));
|
52
53
|
|
53
|
-
if query_params.get("cert").is_some_and(|c| c == "
|
54
|
+
if query_params.get("cert").is_some_and(|c| c == "acme") {
|
54
55
|
if let Some(domains) = domains {
|
55
56
|
let directory_url = &*ITSI_ACME_DIRECTORY_URL;
|
56
57
|
info!(
|
57
58
|
domains = format!("{:?}", domains),
|
58
59
|
directory_url, "Requesting acme cert"
|
59
60
|
);
|
61
|
+
let acme_contact_email = query_params
|
62
|
+
.get("acme_email")
|
63
|
+
.map(|s| s.to_string())
|
64
|
+
.or_else(|| (*ITSI_ACME_CONTACT_EMAIL).as_ref().ok().map(|s| s.to_string()))
|
65
|
+
.ok_or_else(|| itsi_error::ItsiError::ArgumentError(
|
66
|
+
"acme_cert query param or ITSI_ACME_CONTACT_EMAIL must be set before you can auto-generate let's encrypt certificates".to_string(),
|
67
|
+
))?;
|
60
68
|
|
61
69
|
let acme_config = AcmeConfig::new(domains)
|
62
|
-
.contact([format!("mailto:{}",
|
63
|
-
itsi_error::ItsiError::ArgumentError(
|
64
|
-
"ITSI_ACME_CONTACT_EMAIL must be set before you can auto-generate production certificates"
|
65
|
-
.to_string(),
|
66
|
-
)
|
67
|
-
})?)])
|
70
|
+
.contact([format!("mailto:{}", acme_contact_email)])
|
68
71
|
.cache(LockedDirCache::new(&*ITSI_ACME_CACHE_DIR))
|
69
72
|
.directory(directory_url);
|
70
73
|
|
@@ -186,7 +189,15 @@ pub fn load_private_key(path: &str) -> PrivateKeyDer<'static> {
|
|
186
189
|
pub fn generate_ca_signed_cert(
|
187
190
|
domains: Vec<String>,
|
188
191
|
) -> Result<(Vec<CertificateDer<'static>>, PrivateKeyDer<'static>)> {
|
189
|
-
info!(
|
192
|
+
info!(
|
193
|
+
domains = format!("{}", domains.join(", ")),
|
194
|
+
"Self signed cert",
|
195
|
+
);
|
196
|
+
info!(
|
197
|
+
"Add {} to your system's trusted cert store to resolve certificate errors.",
|
198
|
+
format!("{}/itsi_dev_ca.crt", ITSI_LOCAL_CA_DIR.to_str().unwrap())
|
199
|
+
);
|
200
|
+
info!("Dev CA path can be overridden by setting env var: `ITSI_LOCAL_CA_DIR`.");
|
190
201
|
let (ca_key_pem, ca_cert_pem) = get_or_create_local_dev_ca()?;
|
191
202
|
|
192
203
|
let ca_kp = KeyPair::from_pem(&ca_key_pem).expect("Failed to load CA key");
|
@@ -198,10 +209,6 @@ pub fn generate_ca_signed_cert(
|
|
198
209
|
let ee_key = KeyPair::generate_for(&rcgen::PKCS_ECDSA_P256_SHA256).unwrap();
|
199
210
|
let mut ee_params = CertificateParams::default();
|
200
211
|
|
201
|
-
info!(
|
202
|
-
"Generated certificate will be valid for domains {:?}",
|
203
|
-
domains
|
204
|
-
);
|
205
212
|
use std::net::IpAddr;
|
206
213
|
|
207
214
|
ee_params.subject_alt_names = domains
|
@@ -1,11 +1,13 @@
|
|
1
1
|
use std::env;
|
2
2
|
|
3
3
|
use atty::{Stream, is};
|
4
|
+
use tracing::level_filters::LevelFilter;
|
4
5
|
pub use tracing::{debug, error, info, trace, warn};
|
5
6
|
pub use tracing_attributes::instrument; // Explicitly export from tracing-attributes
|
6
7
|
use tracing_subscriber::{
|
7
|
-
EnvFilter,
|
8
|
+
EnvFilter, Layer,
|
8
9
|
fmt::{self, format},
|
10
|
+
layer::SubscriberExt,
|
9
11
|
};
|
10
12
|
|
11
13
|
#[instrument]
|
@@ -39,3 +41,18 @@ pub fn init() {
|
|
39
41
|
.init();
|
40
42
|
}
|
41
43
|
}
|
44
|
+
|
45
|
+
pub fn run_silently<F, R>(f: F) -> R
|
46
|
+
where
|
47
|
+
F: FnOnce() -> R,
|
48
|
+
{
|
49
|
+
// Build a minimal subscriber that filters *everything* out
|
50
|
+
let no_op_subscriber =
|
51
|
+
tracing_subscriber::registry().with(fmt::layer().with_filter(LevelFilter::OFF));
|
52
|
+
|
53
|
+
// Turn that subscriber into a `Dispatch`
|
54
|
+
let no_op_dispatch = tracing::dispatcher::Dispatch::new(no_op_subscriber);
|
55
|
+
|
56
|
+
// Temporarily set `no_op_dispatch` as the *default* within this closure
|
57
|
+
tracing::dispatcher::with_default(&no_op_dispatch, f)
|
58
|
+
}
|
@@ -1,6 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
3
|
class TestKernelSleep < Minitest::Test
|
5
4
|
include Itsi::Scheduler::TestHelper
|
6
5
|
|
@@ -14,7 +13,7 @@ class TestKernelSleep < Minitest::Test
|
|
14
13
|
# Run the scheduler in a dedicated thread to avoid interference with the
|
15
14
|
# main thread’s scheduler state.
|
16
15
|
with_scheduler do |_scheduler|
|
17
|
-
|
16
|
+
10.times do
|
18
17
|
Fiber.schedule do
|
19
18
|
sleep 0.05
|
20
19
|
results << "first"
|
@@ -26,9 +25,9 @@ class TestKernelSleep < Minitest::Test
|
|
26
25
|
|
27
26
|
ends_at = Time.now
|
28
27
|
# We expect 10 sleep completions overall (2 per fiber).
|
29
|
-
assert_equal
|
28
|
+
assert_equal 20, results.size
|
30
29
|
# Because all sleeps run concurrently, the total elapsed time should be about 1 second.
|
31
|
-
assert_in_delta 0.1, ends_at - start_at, 0.
|
30
|
+
assert_in_delta 0.1, ends_at - start_at, 0.1, "Total elapsed time should be close to 0.1 second"
|
32
31
|
end
|
33
32
|
|
34
33
|
def test_sleep_zero_duration
|