|
5 | 5 |
|
6 | 6 | use std::collections::HashMap; |
7 | 7 | use std::convert::Infallible; |
| 8 | +use std::fs; |
| 9 | +use std::io::{Read, Write}; |
8 | 10 | use std::net::{IpAddr, Ipv4Addr, SocketAddr}; |
9 | | -use std::path::PathBuf; |
| 11 | +use std::path::{Path, PathBuf}; |
10 | 12 | use std::sync::{Arc, Mutex}; |
11 | 13 | use std::time::{Duration, Instant}; |
12 | 14 |
|
@@ -76,15 +78,14 @@ pub async fn serve_web(ctx: CommandContext, mut args: ServeWebArgs) -> Result<i3 |
76 | 78 | legal::require_consent(&ctx.paths, args.accept_server_license_terms)?; |
77 | 79 |
|
78 | 80 | let platform: crate::update_service::Platform = PreReqChecker::new().verify().await?; |
79 | | - |
80 | 81 | if !args.without_connection_token { |
81 | 82 | // Ensure there's a defined connection token, since if multiple server versions |
82 | 83 | // are excuted, they will need to have a single shared token. |
83 | | - args.connection_token = Some( |
84 | | - args.connection_token |
85 | | - .clone() |
86 | | - .unwrap_or_else(|| uuid::Uuid::new_v4().to_string()), |
87 | | - ); |
| 84 | + let token_path = ctx.paths.root().join("serve-web-token"); |
| 85 | + let token = mint_connection_token(&token_path, args.connection_token.clone()) |
| 86 | + .map_err(CodeError::CouldNotCreateConnectionTokenFile)?; |
| 87 | + args.connection_token = Some(token); |
| 88 | + args.connection_token_file = Some(token_path.to_string_lossy().to_string()); |
88 | 89 | } |
89 | 90 |
|
90 | 91 | let cm = ConnectionManager::new(&ctx, platform, args.clone()); |
@@ -704,8 +705,10 @@ impl ConnectionManager { |
704 | 705 | if args.args.without_connection_token { |
705 | 706 | cmd.arg("--without-connection-token"); |
706 | 707 | } |
707 | | - if let Some(ct) = &args.args.connection_token { |
708 | | - cmd.arg("--connection-token"); |
| 708 | + // Note: intentional that we don't pass --connection-token here, we always |
| 709 | + // convert it into the file variant. |
| 710 | + if let Some(ct) = &args.args.connection_token_file { |
| 711 | + cmd.arg("--connection-token-file"); |
709 | 712 | cmd.arg(ct); |
710 | 713 | } |
711 | 714 |
|
@@ -779,3 +782,30 @@ struct StartArgs { |
779 | 782 | release: Release, |
780 | 783 | opener: BarrierOpener<Result<StartData, String>>, |
781 | 784 | } |
| 785 | + |
| 786 | +fn mint_connection_token(path: &Path, prefer_token: Option<String>) -> std::io::Result<String> { |
| 787 | + #[cfg(not(windows))] |
| 788 | + use std::os::unix::fs::OpenOptionsExt; |
| 789 | + |
| 790 | + let mut f = fs::OpenOptions::new(); |
| 791 | + f.create(true); |
| 792 | + f.write(true); |
| 793 | + f.read(true); |
| 794 | + #[cfg(not(windows))] |
| 795 | + f.mode(0o600); |
| 796 | + let mut f = f.open(path)?; |
| 797 | + |
| 798 | + if prefer_token.is_none() { |
| 799 | + let mut t = String::new(); |
| 800 | + f.read_to_string(&mut t)?; |
| 801 | + let t = t.trim(); |
| 802 | + if !t.is_empty() { |
| 803 | + return Ok(t.to_string()); |
| 804 | + } |
| 805 | + } |
| 806 | + |
| 807 | + f.set_len(0)?; |
| 808 | + let prefer_token = prefer_token.unwrap_or_else(|| uuid::Uuid::new_v4().to_string()); |
| 809 | + f.write_all(prefer_token.as_bytes())?; |
| 810 | + Ok(prefer_token) |
| 811 | +} |
0 commit comments