Skip to content

Commit 621bec5

Browse files
Saruniksmontekki
andcommitted
Replace rouille with warp
Co-authored-by: Fedor Sakharov <[email protected]>
1 parent 0e66562 commit 621bec5

File tree

17 files changed

+1978
-1272
lines changed

17 files changed

+1978
-1272
lines changed

Cargo.lock

Lines changed: 582 additions & 493 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ regex = "1.10.3"
7171
reqsign = { version = "0.16.0", optional = true }
7272
reqwest = { version = "0.12", features = [
7373
"json",
74-
"blocking",
74+
"native-tls",
7575
"stream",
7676
"rustls-tls",
7777
"rustls-tls-native-roots",
@@ -107,6 +107,7 @@ zstd = "0.13"
107107

108108
# dist-server only
109109
memmap2 = "0.9.4"
110+
native-tls = "0.2.8"
110111
nix = { version = "0.28.0", optional = true, features = [
111112
"mount",
112113
"user",
@@ -115,11 +116,10 @@ nix = { version = "0.28.0", optional = true, features = [
115116
"process",
116117
] }
117118
object = "0.32"
118-
rouille = { version = "3.6", optional = true, default-features = false, features = [
119-
"ssl",
120-
] }
121119
syslog = { version = "6", optional = true }
120+
thiserror = { version = "1.0.30", optional = true }
122121
version-compare = { version = "0.1.1", optional = true }
122+
warp = { version = "0.3.2", optional = true, features = ["tls"] }
123123

124124
[dev-dependencies]
125125
assert_cmd = "2.0.13"
@@ -190,15 +190,17 @@ dist-client = [
190190
]
191191
# Enables the sccache-dist binary
192192
dist-server = [
193+
"reqwest/blocking",
193194
"jwt",
194195
"flate2",
195196
"libmount",
196197
"nix",
197198
"openssl",
198199
"reqwest",
199-
"rouille",
200200
"syslog",
201201
"version-compare",
202+
"warp",
203+
"thiserror",
202204
]
203205
# Enables dist tests with external requirements
204206
dist-tests = ["dist-client", "dist-server"]

src/bin/sccache-dist/build.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,7 @@ impl OverlayBuilder {
231231
for (tc, _) in entries {
232232
warn!("Removing old un-compressed toolchain: {:?}", tc);
233233
assert!(toolchain_dir_map.remove(tc).is_some());
234-
fs::remove_dir_all(&self.dir.join("toolchains").join(&tc.archive_id))
234+
fs::remove_dir_all(self.dir.join("toolchains").join(&tc.archive_id))
235235
.context("Failed to remove old toolchain directory")?;
236236
}
237237
}

src/bin/sccache-dist/main.rs

Lines changed: 30 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22
extern crate log;
33

44
use anyhow::{bail, Context, Error, Result};
5+
use async_trait::async_trait;
56
use base64::Engine;
7+
use cmdline::{AuthSubcommand, Command};
68
use rand::{rngs::OsRng, RngCore};
79
use sccache::config::{
810
scheduler as scheduler_config, server as server_config, INSECURE_DIST_CLIENT_TOKEN,
@@ -22,17 +24,16 @@ use std::env;
2224
use std::io;
2325
use std::path::Path;
2426
use std::sync::atomic::{AtomicUsize, Ordering};
25-
use std::sync::{Mutex, MutexGuard};
27+
use std::sync::{Arc, Mutex, MutexGuard};
2628
use std::time::{Duration, Instant};
29+
use tokio::runtime::Runtime;
2730

2831
#[cfg_attr(target_os = "freebsd", path = "build_freebsd.rs")]
2932
mod build;
3033

3134
mod cmdline;
3235
mod token_check;
3336

34-
use cmdline::{AuthSubcommand, Command};
35-
3637
pub const INSECURE_DIST_SERVER_TOKEN: &str = "dangerously_insecure_server";
3738

3839
// Only supported on x86_64 Linux machines and on FreeBSD
@@ -184,10 +185,10 @@ fn run(command: Command) -> Result<i32> {
184185
scheduler_config::ServerAuth::Insecure => {
185186
warn!("Scheduler starting with DANGEROUSLY_INSECURE server authentication");
186187
let token = INSECURE_DIST_SERVER_TOKEN;
187-
Box::new(move |server_token| check_server_token(server_token, token))
188+
Arc::new(move |server_token| check_server_token(server_token, token))
188189
}
189190
scheduler_config::ServerAuth::Token { token } => {
190-
Box::new(move |server_token| check_server_token(server_token, &token))
191+
Arc::new(move |server_token| check_server_token(server_token, &token))
191192
}
192193
scheduler_config::ServerAuth::JwtHS256 { secret_key } => {
193194
let secret_key = BASE64_URL_SAFE_ENGINE
@@ -203,7 +204,7 @@ fn run(command: Command) -> Result<i32> {
203204
validation.validate_nbf = false;
204205
validation
205206
};
206-
Box::new(move |server_token| {
207+
Arc::new(move |server_token| {
207208
check_jwt_server_token(server_token, &secret_key, &validation)
208209
})
209210
}
@@ -217,7 +218,10 @@ fn run(command: Command) -> Result<i32> {
217218
check_client_auth,
218219
check_server_auth,
219220
);
220-
http_scheduler.start()?;
221+
222+
// Create runtime after daemonize because Tokio doesn't work well with daemonize
223+
let runtime = Runtime::new().context("Failed to create Tokio runtime")?;
224+
runtime.block_on(async { http_scheduler.start().await })?;
221225
unreachable!();
222226
}
223227

@@ -294,7 +298,8 @@ fn run(command: Command) -> Result<i32> {
294298
server,
295299
)
296300
.context("Failed to create sccache HTTP server instance")?;
297-
http_server.start()?;
301+
let runtime = Runtime::new().context("Failed to create Tokio runtime")?;
302+
runtime.block_on(async { http_server.start().await })?;
298303
unreachable!();
299304
}
300305
}
@@ -399,8 +404,9 @@ impl Default for Scheduler {
399404
}
400405
}
401406

407+
#[async_trait]
402408
impl SchedulerIncoming for Scheduler {
403-
fn handle_alloc_job(
409+
async fn handle_alloc_job(
404410
&self,
405411
requester: &dyn SchedulerOutgoing,
406412
tc: Toolchain,
@@ -499,6 +505,7 @@ impl SchedulerIncoming for Scheduler {
499505
need_toolchain,
500506
} = requester
501507
.do_assign_job(server_id, job_id, tc, auth.clone())
508+
.await
502509
.with_context(|| {
503510
// LOCKS
504511
let mut servers = self.servers.lock().unwrap();
@@ -717,7 +724,7 @@ impl SchedulerIncoming for Scheduler {
717724
pub struct Server {
718725
builder: Box<dyn BuilderIncoming>,
719726
cache: Mutex<TcCache>,
720-
job_toolchains: Mutex<HashMap<JobId, Toolchain>>,
727+
job_toolchains: tokio::sync::Mutex<HashMap<JobId, Toolchain>>,
721728
}
722729

723730
impl Server {
@@ -731,18 +738,19 @@ impl Server {
731738
Ok(Server {
732739
builder,
733740
cache: Mutex::new(cache),
734-
job_toolchains: Mutex::new(HashMap::new()),
741+
job_toolchains: tokio::sync::Mutex::new(HashMap::new()),
735742
})
736743
}
737744
}
738745

746+
#[async_trait]
739747
impl ServerIncoming for Server {
740-
fn handle_assign_job(&self, job_id: JobId, tc: Toolchain) -> Result<AssignJobResult> {
748+
async fn handle_assign_job(&self, job_id: JobId, tc: Toolchain) -> Result<AssignJobResult> {
741749
let need_toolchain = !self.cache.lock().unwrap().contains_toolchain(&tc);
742750
assert!(self
743751
.job_toolchains
744752
.lock()
745-
.unwrap()
753+
.await
746754
.insert(job_id, tc)
747755
.is_none());
748756
let state = if need_toolchain {
@@ -756,18 +764,19 @@ impl ServerIncoming for Server {
756764
need_toolchain,
757765
})
758766
}
759-
fn handle_submit_toolchain(
767+
async fn handle_submit_toolchain(
760768
&self,
761769
requester: &dyn ServerOutgoing,
762770
job_id: JobId,
763-
tc_rdr: ToolchainReader,
771+
tc_rdr: ToolchainReader<'_>,
764772
) -> Result<SubmitToolchainResult> {
765773
requester
766774
.do_update_job_state(job_id, JobState::Ready)
775+
.await
767776
.context("Updating job state failed")?;
768777
// TODO: need to lock the toolchain until the container has started
769778
// TODO: can start prepping container
770-
let tc = match self.job_toolchains.lock().unwrap().get(&job_id).cloned() {
779+
let tc = match self.job_toolchains.lock().await.get(&job_id).cloned() {
771780
Some(tc) => tc,
772781
None => return Ok(SubmitToolchainResult::JobNotFound),
773782
};
@@ -783,18 +792,19 @@ impl ServerIncoming for Server {
783792
.map(|_| SubmitToolchainResult::Success)
784793
.unwrap_or(SubmitToolchainResult::CannotCache))
785794
}
786-
fn handle_run_job(
795+
async fn handle_run_job(
787796
&self,
788797
requester: &dyn ServerOutgoing,
789798
job_id: JobId,
790799
command: CompileCommand,
791800
outputs: Vec<String>,
792-
inputs_rdr: InputsReader,
801+
inputs_rdr: InputsReader<'_>,
793802
) -> Result<RunJobResult> {
794803
requester
795804
.do_update_job_state(job_id, JobState::Started)
805+
.await
796806
.context("Updating job state failed")?;
797-
let tc = self.job_toolchains.lock().unwrap().remove(&job_id);
807+
let tc = self.job_toolchains.lock().await.remove(&job_id);
798808
let res = match tc {
799809
None => Ok(RunJobResult::JobNotFound),
800810
Some(tc) => {
@@ -812,6 +822,7 @@ impl ServerIncoming for Server {
812822
};
813823
requester
814824
.do_update_job_state(job_id, JobState::Complete)
825+
.await
815826
.context("Updating job state failed")?;
816827
res
817828
}

src/bin/sccache-dist/token_check.rs

Lines changed: 25 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
use anyhow::{bail, Context, Result};
2+
use async_trait::async_trait;
23
use base64::Engine;
34
use sccache::dist::http::{ClientAuthCheck, ClientVisibleMsg};
4-
use sccache::util::{new_reqwest_blocking_client, BASE64_URL_SAFE_ENGINE};
5+
use sccache::util::new_reqwest_client;
6+
use sccache::util::BASE64_URL_SAFE_ENGINE;
57
use serde::{Deserialize, Serialize};
68
use std::collections::HashMap;
79
use std::result::Result as StdResult;
@@ -54,8 +56,9 @@ pub struct EqCheck {
5456
s: String,
5557
}
5658

59+
#[async_trait]
5760
impl ClientAuthCheck for EqCheck {
58-
fn check(&self, token: &str) -> StdResult<(), ClientVisibleMsg> {
61+
async fn check(&self, token: &str) -> StdResult<(), ClientVisibleMsg> {
5962
if self.s == token {
6063
Ok(())
6164
} else {
@@ -80,14 +83,15 @@ const MOZ_USERINFO_ENDPOINT: &str = "https://auth.mozilla.auth0.com/userinfo";
8083
/// Mozilla-specific check by forwarding the token onto the auth0 userinfo endpoint
8184
pub struct MozillaCheck {
8285
// token, token_expiry
83-
auth_cache: Mutex<HashMap<String, Instant>>,
84-
client: reqwest::blocking::Client,
86+
auth_cache: tokio::sync::Mutex<HashMap<String, Instant>>,
87+
client: reqwest::Client,
8588
required_groups: Vec<String>,
8689
}
8790

91+
#[async_trait]
8892
impl ClientAuthCheck for MozillaCheck {
89-
fn check(&self, token: &str) -> StdResult<(), ClientVisibleMsg> {
90-
self.check_mozilla(token).map_err(|e| {
93+
async fn check(&self, token: &str) -> StdResult<(), ClientVisibleMsg> {
94+
self.check_mozilla(token).await.map_err(|e| {
9195
warn!("Mozilla token validation failed: {}", e);
9296
ClientVisibleMsg::from_nonsensitive(
9397
"Failed to validate Mozilla OAuth token, run sccache --dist-auth".to_owned(),
@@ -99,13 +103,13 @@ impl ClientAuthCheck for MozillaCheck {
99103
impl MozillaCheck {
100104
pub fn new(required_groups: Vec<String>) -> Self {
101105
Self {
102-
auth_cache: Mutex::new(HashMap::new()),
103-
client: new_reqwest_blocking_client(),
106+
auth_cache: tokio::sync::Mutex::new(HashMap::new()),
107+
client: new_reqwest_client(),
104108
required_groups,
105109
}
106110
}
107111

108-
fn check_mozilla(&self, token: &str) -> Result<()> {
112+
async fn check_mozilla(&self, token: &str) -> Result<()> {
109113
// azp == client_id
110114
// {
111115
// "iss": "https://auth.mozilla.auth0.com/",
@@ -139,7 +143,7 @@ impl MozillaCheck {
139143
}
140144

141145
// If the token is cached and not expired, return it
142-
let mut auth_cache = self.auth_cache.lock().unwrap();
146+
let mut auth_cache = self.auth_cache.lock().await;
143147
if let Some(cached_at) = auth_cache.get(token) {
144148
if cached_at.elapsed() < MOZ_SESSION_TIMEOUT {
145149
return Ok(());
@@ -158,10 +162,12 @@ impl MozillaCheck {
158162
.get(url.clone())
159163
.bearer_auth(token)
160164
.send()
165+
.await
161166
.context("Failed to make request to mozilla userinfo")?;
162167
let status = res.status();
163168
let res_text = res
164169
.text()
170+
.await
165171
.context("Failed to interpret response from mozilla userinfo as string")?;
166172
if !status.is_success() {
167173
bail!("JWT forwarded to {} returned {}: {}", url, status, res_text)
@@ -245,14 +251,15 @@ fn test_auth_verify_check_mozilla_profile() {
245251
// Don't check a token is valid (it may not even be a JWT) just forward it to
246252
// an API and check for success
247253
pub struct ProxyTokenCheck {
248-
client: reqwest::blocking::Client,
254+
client: reqwest::Client,
249255
maybe_auth_cache: Option<Mutex<(HashMap<String, Instant>, Duration)>>,
250256
url: String,
251257
}
252258

259+
#[async_trait]
253260
impl ClientAuthCheck for ProxyTokenCheck {
254-
fn check(&self, token: &str) -> StdResult<(), ClientVisibleMsg> {
255-
match self.check_token_with_forwarding(token) {
261+
async fn check(&self, token: &str) -> StdResult<(), ClientVisibleMsg> {
262+
match self.check_token_with_forwarding(token).await {
256263
Ok(()) => Ok(()),
257264
Err(e) => {
258265
warn!("Proxying token validation failed: {}", e);
@@ -269,13 +276,13 @@ impl ProxyTokenCheck {
269276
let maybe_auth_cache: Option<Mutex<(HashMap<String, Instant>, Duration)>> =
270277
cache_secs.map(|secs| Mutex::new((HashMap::new(), Duration::from_secs(secs))));
271278
Self {
272-
client: new_reqwest_blocking_client(),
279+
client: new_reqwest_client(),
273280
maybe_auth_cache,
274281
url,
275282
}
276283
}
277284

278-
fn check_token_with_forwarding(&self, token: &str) -> Result<()> {
285+
async fn check_token_with_forwarding(&self, token: &str) -> Result<()> {
279286
trace!("Validating token by forwarding to {}", self.url);
280287
// If the token is cached and not cache has not expired, return it
281288
if let Some(ref auth_cache) = self.maybe_auth_cache {
@@ -294,6 +301,7 @@ impl ProxyTokenCheck {
294301
.get(&self.url)
295302
.bearer_auth(token)
296303
.send()
304+
.await
297305
.context("Failed to make request to proxying url")?;
298306
if !res.status().is_success() {
299307
bail!("Token forwarded to {} returned {}", self.url, res.status());
@@ -315,8 +323,9 @@ pub struct ValidJWTCheck {
315323
kid_to_pkcs1: HashMap<String, Vec<u8>>,
316324
}
317325

326+
#[async_trait]
318327
impl ClientAuthCheck for ValidJWTCheck {
319-
fn check(&self, token: &str) -> StdResult<(), ClientVisibleMsg> {
328+
async fn check(&self, token: &str) -> StdResult<(), ClientVisibleMsg> {
320329
match self.check_jwt_validity(token) {
321330
Ok(()) => Ok(()),
322331
Err(e) => {

src/compiler/compiler.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1460,7 +1460,6 @@ mod test {
14601460
use std::io::{Cursor, Write};
14611461
use std::sync::Arc;
14621462
use std::time::Duration;
1463-
use std::u64;
14641463
use test_case::test_case;
14651464
use tokio::runtime::Runtime;
14661465

src/compiler/rust.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@ use fs_err as fs;
3434
use log::Level::Trace;
3535
use once_cell::sync::Lazy;
3636
#[cfg(feature = "dist-client")]
37-
#[cfg(feature = "dist-client")]
3837
use std::borrow::Borrow;
3938
use std::borrow::Cow;
4039
#[cfg(feature = "dist-client")]

0 commit comments

Comments
 (0)