|
6 | 6 | use std::collections::HashMap;
|
7 | 7 | use std::convert::Infallible;
|
8 | 8 | use std::net::{IpAddr, Ipv4Addr, SocketAddr};
|
9 |
| -use std::path::PathBuf; |
| 9 | +use std::path::{Path, PathBuf}; |
10 | 10 | use std::sync::{Arc, Mutex};
|
11 | 11 | use std::time::{Duration, Instant};
|
12 | 12 |
|
13 | 13 | use const_format::concatcp;
|
14 | 14 | use hyper::service::{make_service_fn, service_fn};
|
15 | 15 | use hyper::{Body, Request, Response, Server};
|
| 16 | +use tempfile::{tempdir, TempDir}; |
16 | 17 | use tokio::io::{AsyncBufReadExt, BufReader};
|
17 | 18 | use tokio::pin;
|
18 | 19 |
|
@@ -76,16 +77,21 @@ pub async fn serve_web(ctx: CommandContext, mut args: ServeWebArgs) -> Result<i3
|
76 | 77 | legal::require_consent(&ctx.paths, args.accept_server_license_terms)?;
|
77 | 78 |
|
78 | 79 | let platform: crate::update_service::Platform = PreReqChecker::new().verify().await?;
|
79 |
| - |
80 |
| - if !args.without_connection_token { |
| 80 | + let token_file = if !args.without_connection_token { |
81 | 81 | // Ensure there's a defined connection token, since if multiple server versions
|
82 | 82 | // 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 |
| - ); |
88 |
| - } |
| 83 | + let connection_token = args |
| 84 | + .connection_token |
| 85 | + .clone() |
| 86 | + .unwrap_or_else(|| uuid::Uuid::new_v4().to_string()); |
| 87 | + let tf = ConnectionTokenFile::new(&connection_token) |
| 88 | + .map_err(CodeError::CouldNotCreateConnectionTokenFile)?; |
| 89 | + args.connection_token = Some(connection_token); |
| 90 | + args.connection_token_file = Some(tf.path().to_string_lossy().to_string()); |
| 91 | + Some(tf) |
| 92 | + } else { |
| 93 | + None |
| 94 | + }; |
89 | 95 |
|
90 | 96 | let cm = ConnectionManager::new(&ctx, platform, args.clone());
|
91 | 97 | let key = get_server_key_half(&ctx.paths);
|
@@ -137,6 +143,7 @@ pub async fn serve_web(ctx: CommandContext, mut args: ServeWebArgs) -> Result<i3
|
137 | 143 | };
|
138 | 144 |
|
139 | 145 | r.map_err(CodeError::CouldNotListenOnInterface)?;
|
| 146 | + drop(token_file); // ensure it lives long enough |
140 | 147 |
|
141 | 148 | Ok(0)
|
142 | 149 | }
|
@@ -704,8 +711,10 @@ impl ConnectionManager {
|
704 | 711 | if args.args.without_connection_token {
|
705 | 712 | cmd.arg("--without-connection-token");
|
706 | 713 | }
|
707 |
| - if let Some(ct) = &args.args.connection_token { |
708 |
| - cmd.arg("--connection-token"); |
| 714 | + // Note: intentional that we don't pass --connection-token here, we always |
| 715 | + // convert it into the file variant. |
| 716 | + if let Some(ct) = &args.args.connection_token_file { |
| 717 | + cmd.arg("--connection-token-file"); |
709 | 718 | cmd.arg(ct);
|
710 | 719 | }
|
711 | 720 |
|
@@ -779,3 +788,21 @@ struct StartArgs {
|
779 | 788 | release: Release,
|
780 | 789 | opener: BarrierOpener<Result<StartData, String>>,
|
781 | 790 | }
|
| 791 | + |
| 792 | +struct ConnectionTokenFile { |
| 793 | + path: PathBuf, |
| 794 | + _dir: TempDir, // implements Drop to delete the dir |
| 795 | +} |
| 796 | + |
| 797 | +impl ConnectionTokenFile { |
| 798 | + fn new(connection_token: &str) -> std::io::Result<Self> { |
| 799 | + let d = tempdir()?; |
| 800 | + let path = d.path().join("connection-token"); |
| 801 | + std::fs::write(&path, connection_token)?; |
| 802 | + Ok(ConnectionTokenFile { path, _dir: d }) |
| 803 | + } |
| 804 | + |
| 805 | + fn path(&self) -> &Path { |
| 806 | + &self.path |
| 807 | + } |
| 808 | +} |
0 commit comments