├── .gitignore ├── shim-protos ├── src │ └── lib.rs ├── build.rs ├── Cargo.toml └── proto │ └── shim.proto ├── Cargo.toml ├── shim ├── Cargo.toml └── src │ ├── utils.rs │ ├── signal.rs │ ├── main.rs │ ├── container.rs │ └── service.rs ├── README.md ├── LICENSE └── Cargo.lock /.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | 3 | .DS_Store 4 | -------------------------------------------------------------------------------- /shim-protos/src/lib.rs: -------------------------------------------------------------------------------- 1 | pub mod proto { 2 | tonic::include_proto!("shim.task"); 3 | } 4 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | resolver = "2" 3 | 4 | members = [ 5 | "shim", "shim-protos", 6 | ] 7 | -------------------------------------------------------------------------------- /shim-protos/build.rs: -------------------------------------------------------------------------------- 1 | fn main() -> Result<(), Box> { 2 | tonic_build::compile_protos("proto/shim.proto")?; 3 | Ok(()) 4 | } 5 | -------------------------------------------------------------------------------- /shim-protos/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "shim-protos" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | prost = "0.13.3" 8 | prost-types = "0.13.3" 9 | tonic = "0.12.2" 10 | 11 | [build-dependencies] 12 | tonic-build = "0.12.2" 13 | -------------------------------------------------------------------------------- /shim/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "shim" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | anyhow = "1.0.89" 8 | clap = { version = "4.5.17", features = ["derive"] } 9 | command-fds = "0.3.0" 10 | dashmap = "6.1.0" 11 | nix = { version = "0.29.0", features = ["process", "fs", "signal"] } 12 | prost-types = "0.13.3" 13 | shim-protos = { version = "0.1.0", path = "../shim-protos" } 14 | time = "0.3.36" 15 | tokio = { version = "1.40.0", features = ["full"] } 16 | tokio-stream = "0.1.16" 17 | tonic = "0.12.3" 18 | tracing = "0.1.40" 19 | tracing-subscriber = { version = "0.3.18", features = ["env-filter"] } 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # runc-shim 2 | 3 | A shim to interact with an OCI runtime that is loosely based on the containerd shim. Read about containerd shim's design and the purpose of a shim [here](https://github.com/containerd/containerd/blob/main/core/runtime/v2/README.md). 4 | 5 | ## Usage 6 | 7 | Build the shim by running: 8 | 9 | ```bash 10 | cargo build --release 11 | ``` 12 | 13 | Running the shim will print to stdout a socket path that can be used to interact with the shim process via gRPC. For example to start a task with ID `hello`: 14 | 15 | ```bash 16 | sudo ./target/release/shim --runtime /usr/sbin/runc --id hello start 17 | # unix:///run/shim/16156531084128653017.sock 18 | ``` 19 | -------------------------------------------------------------------------------- /shim/src/utils.rs: -------------------------------------------------------------------------------- 1 | use std::sync::atomic::{AtomicBool, Ordering}; 2 | 3 | use tokio::sync::Notify; 4 | 5 | pub struct ExitSignal { 6 | notifier: Notify, 7 | exited: AtomicBool, 8 | } 9 | 10 | impl ExitSignal { 11 | pub fn signal(&self) { 12 | self.exited.store(true, Ordering::SeqCst); 13 | self.notifier.notify_waiters(); 14 | } 15 | 16 | pub async fn wait(&self) { 17 | loop { 18 | let notified = self.notifier.notified(); 19 | if self.exited.load(Ordering::SeqCst) { 20 | break; 21 | } 22 | notified.await; 23 | } 24 | } 25 | } 26 | 27 | impl Default for ExitSignal { 28 | fn default() -> Self { 29 | Self { 30 | notifier: Notify::new(), 31 | exited: AtomicBool::new(false), 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 David Mo 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /shim-protos/proto/shim.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package shim.task; 4 | 5 | import "google/protobuf/empty.proto"; 6 | import "google/protobuf/timestamp.proto"; 7 | 8 | service Task { 9 | rpc Create(CreateTaskRequest) returns (CreateTaskResponse); 10 | rpc Start(StartRequest) returns (StartResponse); 11 | rpc Delete(DeleteRequest) returns (DeleteResponse); 12 | rpc Wait(WaitRequest) returns (WaitResponse); 13 | rpc Kill(KillRequest) returns (google.protobuf.Empty); 14 | rpc Shutdown(ShutdownRequest) returns (google.protobuf.Empty); 15 | } 16 | 17 | message CreateTaskRequest { 18 | string id = 1; 19 | string bundle = 2; 20 | // these fields are used to represent rootfs, terminal, and stdin in 21 | // containerd's message definition 22 | reserved 3 to 5; 23 | string stdout = 6; 24 | string stderr = 7; 25 | } 26 | 27 | message CreateTaskResponse { 28 | uint32 pid = 1; 29 | } 30 | 31 | message StartRequest { 32 | string id = 1; 33 | } 34 | 35 | message StartResponse { 36 | uint32 pid = 1; 37 | } 38 | 39 | message DeleteRequest { 40 | string id = 1; 41 | } 42 | 43 | message DeleteResponse { 44 | uint32 pid = 1; 45 | } 46 | 47 | message WaitRequest { 48 | string id = 1; 49 | } 50 | 51 | message WaitResponse { 52 | uint32 exit_status = 1; 53 | google.protobuf.Timestamp exited_at = 2; 54 | } 55 | 56 | message KillRequest { 57 | string id = 1; 58 | // this field is used to represent the exec_id in containerd's message definition 59 | reserved 2; 60 | uint32 signal = 3; 61 | } 62 | 63 | message ShutdownRequest { 64 | string id = 1; 65 | } 66 | -------------------------------------------------------------------------------- /shim/src/signal.rs: -------------------------------------------------------------------------------- 1 | use std::time::Duration; 2 | 3 | use anyhow::{bail, Result}; 4 | use nix::{ 5 | libc::pid_t, 6 | sys::{ 7 | signal::{kill, Signal}, 8 | wait::{waitpid, WaitPidFlag, WaitStatus}, 9 | }, 10 | unistd::Pid, 11 | }; 12 | use tokio::{ 13 | signal::unix::{signal, SignalKind}, 14 | sync::mpsc, 15 | time::sleep, 16 | }; 17 | use tracing::{debug, error, info, warn}; 18 | 19 | pub async fn handle_signals(sender: mpsc::UnboundedSender<(pid_t, i32)>) -> Result<()> { 20 | let mut sigchld = signal(SignalKind::child())?; 21 | 22 | loop { 23 | tokio::select! { 24 | _ = sigchld.recv() => { 25 | debug!("Received SIGCHLD"); 26 | // Because container PIDs are not known a priori, we call `waitpid` with a PID of -1. 27 | // However, not all SIGCHLD signals are from container processes (e.g. a 28 | // `process::Command` to create a container). 29 | // 30 | // TODO: Sleeping is a hack awit to avoid prematurely reaping commands 31 | sleep(Duration::from_millis(10)).await; 32 | loop { 33 | match waitpid(Pid::from_raw(-1), Some(WaitPidFlag::WNOHANG)) { 34 | Ok(WaitStatus::Exited(pid, status)) => { 35 | info!("Process {} exited with status {}", pid, status); 36 | if let Err(err) = sender.send((pid.as_raw(), status)) { 37 | error!("Failed to send exit status: {}", err); 38 | } 39 | } 40 | Ok(WaitStatus::Signaled(pid, signal, _)) => { 41 | info!("Process {} exited with signal {}", pid, signal); 42 | if let Err(err) = sender.send((pid.as_raw(), 128 + signal as i32)) { 43 | error!("Failed to send exit status: {}", err); 44 | } 45 | } 46 | Ok(WaitStatus::StillAlive) => { 47 | // Still some unterminated child process 48 | break; 49 | } 50 | Ok(_) => { 51 | // Unknown status 52 | } 53 | Err(nix::Error::ECHILD) => { 54 | // No child processes 55 | break; 56 | } 57 | Err(err) => { 58 | warn!("Error occurred in signal handler: {}", err); 59 | break; 60 | } 61 | }; 62 | } 63 | } 64 | } 65 | } 66 | } 67 | 68 | pub fn forward_signal(pid: Pid, signal: Signal) -> Result<()> { 69 | match kill(pid, signal) { 70 | Ok(()) => Ok(()), 71 | Err(nix::Error::ESRCH) => { 72 | warn!("Process {} not found, ignoring signal", pid); 73 | Ok(()) 74 | } 75 | Err(err) => { 76 | bail!("Failed to forward signal to process {}: {}", pid, err); 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /shim/src/main.rs: -------------------------------------------------------------------------------- 1 | use std::{ 2 | env, 3 | hash::{DefaultHasher, Hash, Hasher}, 4 | io::{stdout, Write}, 5 | os::{ 6 | fd::{FromRawFd, RawFd}, 7 | unix::net::UnixListener, 8 | }, 9 | path::PathBuf, 10 | process::{ExitCode, Stdio}, 11 | sync::Arc, 12 | }; 13 | 14 | use anyhow::{Context, Result}; 15 | use clap::{Parser, Subcommand}; 16 | use command_fds::{CommandFdExt, FdMapping}; 17 | use nix::{sys::prctl::set_child_subreaper, unistd::setsid}; 18 | use service::TaskService; 19 | use shim_protos::proto::task_server::TaskServer; 20 | use signal::handle_signals; 21 | use tokio::{fs, sync::mpsc}; 22 | use tokio_stream::wrappers::UnixListenerStream; 23 | use tonic::transport::Server; 24 | use tracing::{error, warn}; 25 | use utils::ExitSignal; 26 | 27 | mod container; 28 | mod service; 29 | mod signal; 30 | mod utils; 31 | 32 | const SOCKET_ROOT: &str = "/run/shim"; 33 | const SOCKET_FD: RawFd = 3; 34 | 35 | /// Shim process for running containers. 36 | #[derive(Parser, Debug)] 37 | #[command(version, about, long_about = None)] 38 | struct Args { 39 | /// Path to OCI runtime executable. 40 | #[arg(short, long, default_value = "/usr/sbin/runc")] 41 | runtime: PathBuf, 42 | 43 | /// ID of the task. 44 | #[arg(short, long)] 45 | id: String, 46 | 47 | /// Command to run. 48 | #[command(subcommand)] 49 | command: Command, 50 | } 51 | 52 | #[derive(Subcommand, Debug)] 53 | enum Command { 54 | /// Start a task. 55 | Start, 56 | 57 | /// Start daemon process (internal use only). 58 | Daemon { 59 | /// Path to the socket file. 60 | socket_path: PathBuf, 61 | }, 62 | } 63 | 64 | fn main() -> ExitCode { 65 | tracing_subscriber::fmt() 66 | .with_env_filter(std::env::var("RUST_LOG").unwrap_or_else(|_| "info".into())) 67 | .init(); 68 | 69 | let args = Args::parse(); 70 | let result = match args.command { 71 | Command::Start => start(args), 72 | Command::Daemon { ref socket_path } => { 73 | let socket_path = socket_path.clone(); 74 | start_daemon(args, socket_path) 75 | } 76 | }; 77 | 78 | match result { 79 | Ok(()) => ExitCode::SUCCESS, 80 | Err(err) => { 81 | error!("{:?}", err); 82 | ExitCode::FAILURE 83 | } 84 | } 85 | } 86 | 87 | fn start(args: Args) -> Result<()> { 88 | let hash = { 89 | let mut hasher = DefaultHasher::new(); 90 | args.id.hash(&mut hasher); 91 | hasher.finish() 92 | }; 93 | let socket_path = PathBuf::from(SOCKET_ROOT).join(format!("{}.sock", hash)); 94 | std::fs::create_dir_all(SOCKET_ROOT).context("Failed to create socket root")?; 95 | let uds = UnixListener::bind(&socket_path).context("Failed to bind socket")?; 96 | let socket_addr = format!("unix://{}", socket_path.display()); 97 | stdout().write_all(socket_addr.as_bytes())?; 98 | stdout().flush()?; 99 | let cmd = env::current_exe().context("Failed to get current executable")?; 100 | let cwd = env::current_dir().context("Failed to get current directory")?; 101 | let mut command = std::process::Command::new(cmd); 102 | command.current_dir(cwd); 103 | command 104 | .stdin(Stdio::null()) 105 | .stdout(Stdio::null()) 106 | .stderr(Stdio::null()); 107 | command 108 | .arg("--runtime") 109 | .arg(args.runtime) 110 | .arg("--id") 111 | .arg(args.id) 112 | .arg("daemon") 113 | .arg(socket_path); 114 | command 115 | .fd_mappings(vec![FdMapping { 116 | parent_fd: uds.into(), 117 | child_fd: SOCKET_FD, 118 | }]) 119 | .context("Failed to set fd mapping")?; 120 | let _child = command.spawn().context("Failed to spawn shim")?; 121 | Ok(()) 122 | } 123 | 124 | #[tokio::main] 125 | async fn start_daemon(args: Args, socket_path: PathBuf) -> Result<()> { 126 | setsid().context("Failed to setsid")?; 127 | set_child_subreaper(true).context("Failed to set subreaper")?; 128 | 129 | let shutdown_signal = Arc::new(ExitSignal::default()); 130 | let task_service = TaskService::new(args.runtime, shutdown_signal.clone()); 131 | 132 | let (tx, mut rx) = mpsc::unbounded_channel(); 133 | let containers = task_service.containers.clone(); 134 | tokio::spawn(async move { handle_signals(tx).await }); 135 | tokio::spawn(async move { 136 | loop { 137 | if let Some((pid, exit_code)) = rx.recv().await { 138 | let mut found = false; 139 | for container in containers.iter() { 140 | if container.pid().await == pid { 141 | container.set_exited(exit_code).await; 142 | found = true; 143 | break; 144 | } 145 | } 146 | if !found { 147 | warn!("Received exit code for unknown pid {}", pid); 148 | } 149 | } 150 | } 151 | }); 152 | 153 | let std_uds = unsafe { UnixListener::from_raw_fd(SOCKET_FD) }; 154 | std_uds.set_nonblocking(true)?; 155 | let uds = tokio::net::UnixListener::from_std(std_uds)?; 156 | let uds_stream = UnixListenerStream::new(uds); 157 | 158 | Server::builder() 159 | .add_service(TaskServer::new(task_service)) 160 | .serve_with_incoming_shutdown(uds_stream, shutdown_signal.wait()) 161 | .await?; 162 | 163 | fs::remove_file(socket_path) 164 | .await 165 | .context("Failed to remove socket")?; 166 | 167 | Ok(()) 168 | } 169 | -------------------------------------------------------------------------------- /shim/src/container.rs: -------------------------------------------------------------------------------- 1 | use std::{ 2 | fs::{self, File, OpenOptions}, 3 | path::{Path, PathBuf}, 4 | process::Stdio, 5 | }; 6 | 7 | use anyhow::{bail, Context, Result}; 8 | use nix::{sys::signal::Signal, unistd::Pid}; 9 | use prost_types::Timestamp; 10 | use time::OffsetDateTime; 11 | use tokio::{ 12 | process::Command, 13 | sync::{mpsc, RwLock}, 14 | }; 15 | 16 | use crate::signal::forward_signal; 17 | 18 | const PID_FILE: &str = "container.pid"; 19 | 20 | pub struct Container { 21 | /// The container ID. 22 | pub id: String, 23 | 24 | /// The bundle directory. 25 | pub bundle: PathBuf, 26 | 27 | /// The container's stdout path. 28 | pub stdout: PathBuf, 29 | 30 | /// The container's stderr path. 31 | pub stderr: PathBuf, 32 | 33 | /// The container status. 34 | status: RwLock, 35 | 36 | /// The container process ID. 37 | pid: RwLock, 38 | 39 | /// The container's exit code. 40 | exit_code: RwLock, 41 | 42 | /// The container's exit timestamp. 43 | exited_at: RwLock>, 44 | 45 | /// The container's wait channels. 46 | wait_channels: RwLock>>, 47 | } 48 | 49 | #[derive(Clone, Copy, PartialEq, Eq)] 50 | pub enum Status { 51 | UNKNOWN, 52 | CREATED, 53 | RUNNING, 54 | STOPPED, 55 | } 56 | 57 | impl Container { 58 | pub fn new(id: &str, bundle: &PathBuf, stdout: &PathBuf, stderr: &PathBuf) -> Self { 59 | Self { 60 | id: id.to_string(), 61 | bundle: bundle.to_owned(), 62 | stdout: stdout.to_owned(), 63 | stderr: stderr.to_owned(), 64 | status: RwLock::new(Status::UNKNOWN), 65 | pid: RwLock::new(0), 66 | exit_code: RwLock::new(0), 67 | exited_at: RwLock::new(None), 68 | wait_channels: RwLock::new(Vec::new()), 69 | } 70 | } 71 | 72 | pub async fn create(&self, runtime: &PathBuf) -> Result<()> { 73 | let mut cmd = Command::new(runtime); 74 | cmd.arg("create") 75 | .arg("--bundle") 76 | .arg(&self.bundle) 77 | .arg("--pid-file") 78 | .arg(self.bundle.join(PID_FILE)) 79 | .arg(&self.id); 80 | cmd.stdin(Stdio::null()) 81 | .stdout(stdio_file(&self.stdout)?) 82 | .stderr(stdio_file(&self.stderr)?); 83 | let mut child = cmd.spawn().context("Failed to spawn OCI runtime")?; 84 | match child.wait().await { 85 | Ok(status) if status.success() => {} 86 | Ok(status) => bail!("OCI runtime exited with status {}", status), 87 | Err(err) => bail!("Failed to wait for OCI runtime: {}", err), 88 | }; 89 | let pid = read_pid(self.bundle.join(PID_FILE))?; 90 | let mut pid_guard = self.pid.write().await; 91 | let mut status_guard = self.status.write().await; 92 | *pid_guard = pid; 93 | *status_guard = Status::CREATED; 94 | Ok(()) 95 | } 96 | 97 | pub async fn start(&self, runtime: &PathBuf) -> Result<()> { 98 | let mut cmd = Command::new(runtime); 99 | cmd.arg("start").arg(&self.id); 100 | cmd.stdin(Stdio::null()) 101 | .stdout(Stdio::null()) 102 | .stderr(Stdio::null()); 103 | let mut child = cmd.spawn().context("Failed to spawn OCI runtime")?; 104 | match child.wait().await { 105 | Ok(status) if status.success() => {} 106 | Ok(status) => bail!("OCI runtime exited with status {}", status), 107 | Err(err) => bail!("Failed to wait for OCI runtime: {}", err), 108 | }; 109 | *self.status.write().await = Status::RUNNING; 110 | Ok(()) 111 | } 112 | 113 | pub async fn delete(&self, runtime: &PathBuf) -> Result<()> { 114 | let mut cmd = Command::new(runtime); 115 | cmd.arg("delete").arg(&self.id); 116 | cmd.stdin(Stdio::null()) 117 | .stdout(Stdio::null()) 118 | .stderr(Stdio::null()); 119 | let mut child = cmd.spawn().context("Failed to spawn OCI runtime")?; 120 | match child.wait().await { 121 | Ok(status) if status.success() => {} 122 | Ok(status) => bail!("OCI runtime exited with status {}", status), 123 | Err(err) => bail!("Failed to wait for OCI runtime: {}", err), 124 | }; 125 | Ok(()) 126 | } 127 | 128 | pub async fn kill(&self, signal: Signal) -> Result<()> { 129 | let pid = Pid::from_raw(*self.pid.read().await); 130 | forward_signal(pid, signal)?; 131 | Ok(()) 132 | } 133 | 134 | pub async fn wait_channel(&self) -> mpsc::UnboundedReceiver<()> { 135 | let (tx, rx) = mpsc::unbounded_channel(); 136 | // keep this guard so that the status is not changed while adding the channel 137 | let status_guard = self.status.read().await; 138 | if *status_guard != Status::STOPPED { 139 | self.wait_channels.write().await.push(tx); 140 | } 141 | rx 142 | } 143 | 144 | pub async fn set_exited(&self, exit_code: i32) { 145 | let mut status_guard = self.status.write().await; 146 | let mut exit_code_guard = self.exit_code.write().await; 147 | let mut exited_at_guard = self.exited_at.write().await; 148 | *status_guard = Status::STOPPED; 149 | *exit_code_guard = exit_code; 150 | *exited_at_guard = Some(OffsetDateTime::now_utc()); 151 | for tx in self.wait_channels.write().await.drain(..) { 152 | let _ = tx.send(()); 153 | } 154 | } 155 | 156 | pub async fn exited_at(&self) -> Option { 157 | self.exited_at.read().await.map(|exited_at| Timestamp { 158 | seconds: exited_at.unix_timestamp(), 159 | nanos: exited_at.nanosecond() as i32, 160 | }) 161 | } 162 | 163 | pub async fn pid(&self) -> i32 { 164 | *self.pid.read().await 165 | } 166 | 167 | pub async fn status(&self) -> Status { 168 | *self.status.read().await 169 | } 170 | 171 | pub async fn exit_code(&self) -> i32 { 172 | *self.exit_code.read().await 173 | } 174 | } 175 | 176 | fn read_pid>(path: P) -> Result { 177 | let contents = fs::read_to_string(path)?; 178 | Ok(contents.parse()?) 179 | } 180 | 181 | fn stdio_file>(path: P) -> Result { 182 | let file = OpenOptions::new() 183 | .create(true) 184 | .truncate(true) 185 | .write(true) 186 | .open(path)?; 187 | Ok(file) 188 | } 189 | -------------------------------------------------------------------------------- /shim/src/service.rs: -------------------------------------------------------------------------------- 1 | use std::{path::PathBuf, sync::Arc}; 2 | 3 | use dashmap::DashMap; 4 | use nix::sys::signal::Signal; 5 | use shim_protos::proto::{ 6 | task_server::Task, CreateTaskRequest, CreateTaskResponse, DeleteRequest, DeleteResponse, 7 | KillRequest, ShutdownRequest, StartRequest, StartResponse, WaitRequest, WaitResponse, 8 | }; 9 | use tonic::{Request, Response, Status}; 10 | use tracing::debug; 11 | 12 | use crate::{ 13 | container::{Container, Status as ContainerStatus}, 14 | utils::ExitSignal, 15 | }; 16 | 17 | pub struct TaskService { 18 | pub runtime: PathBuf, 19 | pub containers: Arc>, 20 | pub exit_signal: Arc, 21 | } 22 | 23 | impl TaskService { 24 | pub fn new(runtime: PathBuf, exit_signal: Arc) -> Self { 25 | Self { 26 | runtime, 27 | containers: Arc::new(DashMap::new()), 28 | exit_signal, 29 | } 30 | } 31 | } 32 | 33 | #[tonic::async_trait] 34 | impl Task for TaskService { 35 | async fn create( 36 | &self, 37 | request: Request, 38 | ) -> Result, Status> { 39 | debug!("Creating container"); 40 | let request = request.into_inner(); 41 | if self.containers.contains_key(&request.id) { 42 | return Err(Status::new( 43 | tonic::Code::AlreadyExists, 44 | "Container already exists", 45 | )); 46 | } 47 | let container = Container::new( 48 | &request.id, 49 | &request.bundle.into(), 50 | &request.stdout.into(), 51 | &request.stderr.into(), 52 | ); 53 | if let Err(err) = container.create(&self.runtime).await { 54 | return Err(Status::new( 55 | tonic::Code::Internal, 56 | format!("Failed to create container: {}", err), 57 | )); 58 | } 59 | let pid = container.pid().await as u32; 60 | self.containers.insert(request.id, container); 61 | Ok(Response::new(CreateTaskResponse { pid })) 62 | } 63 | 64 | async fn start( 65 | &self, 66 | request: Request, 67 | ) -> Result, Status> { 68 | debug!("Starting container"); 69 | let request = request.into_inner(); 70 | let container = self 71 | .containers 72 | .get(&request.id) 73 | .ok_or_else(|| Status::new(tonic::Code::NotFound, "Container not found"))?; 74 | if let Err(err) = container.start(&self.runtime).await { 75 | return Err(Status::new( 76 | tonic::Code::Internal, 77 | format!("Failed to start container: {}", err), 78 | )); 79 | } 80 | let pid = container.pid().await as u32; 81 | Ok(Response::new(StartResponse { pid })) 82 | } 83 | 84 | async fn delete( 85 | &self, 86 | request: Request, 87 | ) -> Result, Status> { 88 | debug!("Deleting container"); 89 | let request = request.into_inner(); 90 | let container = self 91 | .containers 92 | .get(&request.id) 93 | .ok_or_else(|| Status::new(tonic::Code::NotFound, "Container not found"))?; 94 | if let Err(err) = container.delete(&self.runtime).await { 95 | return Err(Status::new( 96 | tonic::Code::Internal, 97 | format!("Failed to delete container: {}", err), 98 | )); 99 | } 100 | let pid = container.pid().await as u32; 101 | drop(container); 102 | self.containers.remove(&request.id); 103 | Ok(Response::new(DeleteResponse { pid })) 104 | } 105 | 106 | async fn wait(&self, request: Request) -> Result, Status> { 107 | debug!("Waiting for container"); 108 | let request = request.into_inner(); 109 | let container = self 110 | .containers 111 | .get(&request.id) 112 | .ok_or_else(|| Status::new(tonic::Code::NotFound, "Container not found"))?; 113 | let status = container.status().await; 114 | if status != ContainerStatus::RUNNING && status != ContainerStatus::CREATED { 115 | return Ok(Response::new(WaitResponse { 116 | exit_status: container.exit_code().await as u32, 117 | exited_at: container.exited_at().await, 118 | })); 119 | } 120 | let mut rx = container.wait_channel().await; 121 | if rx.recv().await.is_none() { 122 | return Err(Status::new( 123 | tonic::Code::Aborted, 124 | "Container exited unexpectedly", 125 | )); 126 | } 127 | Ok(Response::new(WaitResponse { 128 | exit_status: container.exit_code().await as u32, 129 | exited_at: container.exited_at().await, 130 | })) 131 | } 132 | 133 | async fn kill(&self, request: Request) -> Result, Status> { 134 | debug!("Killing container"); 135 | let request = request.into_inner(); 136 | let container = self 137 | .containers 138 | .get(&request.id) 139 | .ok_or_else(|| Status::new(tonic::Code::NotFound, "Container not found"))?; 140 | let signal = match Signal::try_from(request.signal as i32) { 141 | Ok(signal) => signal, 142 | Err(err) => { 143 | return Err(Status::new( 144 | tonic::Code::InvalidArgument, 145 | format!("Invalid signal: {}", err), 146 | )) 147 | } 148 | }; 149 | if let Err(err) = container.kill(signal).await { 150 | return Err(Status::new( 151 | tonic::Code::Internal, 152 | format!("Failed to kill container: {}", err), 153 | )); 154 | } 155 | Ok(Response::new(())) 156 | } 157 | 158 | async fn shutdown(&self, _request: Request) -> Result, Status> { 159 | debug!("Shutting down container"); 160 | for container in self.containers.iter() { 161 | // Kills all containers so that all `TaskService::wait` calls return and Tonic can shutdown. 162 | if let Err(err) = container.delete(&self.runtime).await { 163 | return Err(Status::new( 164 | tonic::Code::Internal, 165 | format!("Failed to delete container: {}", err), 166 | )); 167 | } 168 | } 169 | self.containers.clear(); 170 | self.exit_signal.signal(); 171 | Ok(Response::new(())) 172 | } 173 | } 174 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "addr2line" 7 | version = "0.24.1" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "f5fb1d8e4442bd405fdfd1dacb42792696b0cf9cb15882e5d097b742a676d375" 10 | dependencies = [ 11 | "gimli", 12 | ] 13 | 14 | [[package]] 15 | name = "adler2" 16 | version = "2.0.0" 17 | source = "registry+https://github.com/rust-lang/crates.io-index" 18 | checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" 19 | 20 | [[package]] 21 | name = "aho-corasick" 22 | version = "1.1.3" 23 | source = "registry+https://github.com/rust-lang/crates.io-index" 24 | checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" 25 | dependencies = [ 26 | "memchr", 27 | ] 28 | 29 | [[package]] 30 | name = "anstream" 31 | version = "0.6.15" 32 | source = "registry+https://github.com/rust-lang/crates.io-index" 33 | checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526" 34 | dependencies = [ 35 | "anstyle", 36 | "anstyle-parse", 37 | "anstyle-query", 38 | "anstyle-wincon", 39 | "colorchoice", 40 | "is_terminal_polyfill", 41 | "utf8parse", 42 | ] 43 | 44 | [[package]] 45 | name = "anstyle" 46 | version = "1.0.8" 47 | source = "registry+https://github.com/rust-lang/crates.io-index" 48 | checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1" 49 | 50 | [[package]] 51 | name = "anstyle-parse" 52 | version = "0.2.5" 53 | source = "registry+https://github.com/rust-lang/crates.io-index" 54 | checksum = "eb47de1e80c2b463c735db5b217a0ddc39d612e7ac9e2e96a5aed1f57616c1cb" 55 | dependencies = [ 56 | "utf8parse", 57 | ] 58 | 59 | [[package]] 60 | name = "anstyle-query" 61 | version = "1.1.1" 62 | source = "registry+https://github.com/rust-lang/crates.io-index" 63 | checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a" 64 | dependencies = [ 65 | "windows-sys 0.52.0", 66 | ] 67 | 68 | [[package]] 69 | name = "anstyle-wincon" 70 | version = "3.0.4" 71 | source = "registry+https://github.com/rust-lang/crates.io-index" 72 | checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8" 73 | dependencies = [ 74 | "anstyle", 75 | "windows-sys 0.52.0", 76 | ] 77 | 78 | [[package]] 79 | name = "anyhow" 80 | version = "1.0.89" 81 | source = "registry+https://github.com/rust-lang/crates.io-index" 82 | checksum = "86fdf8605db99b54d3cd748a44c6d04df638eb5dafb219b135d0149bd0db01f6" 83 | 84 | [[package]] 85 | name = "async-stream" 86 | version = "0.3.5" 87 | source = "registry+https://github.com/rust-lang/crates.io-index" 88 | checksum = "cd56dd203fef61ac097dd65721a419ddccb106b2d2b70ba60a6b529f03961a51" 89 | dependencies = [ 90 | "async-stream-impl", 91 | "futures-core", 92 | "pin-project-lite", 93 | ] 94 | 95 | [[package]] 96 | name = "async-stream-impl" 97 | version = "0.3.5" 98 | source = "registry+https://github.com/rust-lang/crates.io-index" 99 | checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" 100 | dependencies = [ 101 | "proc-macro2", 102 | "quote", 103 | "syn", 104 | ] 105 | 106 | [[package]] 107 | name = "async-trait" 108 | version = "0.1.83" 109 | source = "registry+https://github.com/rust-lang/crates.io-index" 110 | checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" 111 | dependencies = [ 112 | "proc-macro2", 113 | "quote", 114 | "syn", 115 | ] 116 | 117 | [[package]] 118 | name = "atomic-waker" 119 | version = "1.1.2" 120 | source = "registry+https://github.com/rust-lang/crates.io-index" 121 | checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" 122 | 123 | [[package]] 124 | name = "autocfg" 125 | version = "1.3.0" 126 | source = "registry+https://github.com/rust-lang/crates.io-index" 127 | checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" 128 | 129 | [[package]] 130 | name = "axum" 131 | version = "0.7.6" 132 | source = "registry+https://github.com/rust-lang/crates.io-index" 133 | checksum = "8f43644eed690f5374f1af436ecd6aea01cd201f6fbdf0178adaf6907afb2cec" 134 | dependencies = [ 135 | "async-trait", 136 | "axum-core", 137 | "bytes", 138 | "futures-util", 139 | "http", 140 | "http-body", 141 | "http-body-util", 142 | "itoa", 143 | "matchit", 144 | "memchr", 145 | "mime", 146 | "percent-encoding", 147 | "pin-project-lite", 148 | "rustversion", 149 | "serde", 150 | "sync_wrapper 1.0.1", 151 | "tower 0.5.1", 152 | "tower-layer", 153 | "tower-service", 154 | ] 155 | 156 | [[package]] 157 | name = "axum-core" 158 | version = "0.4.4" 159 | source = "registry+https://github.com/rust-lang/crates.io-index" 160 | checksum = "5e6b8ba012a258d63c9adfa28b9ddcf66149da6f986c5b5452e629d5ee64bf00" 161 | dependencies = [ 162 | "async-trait", 163 | "bytes", 164 | "futures-util", 165 | "http", 166 | "http-body", 167 | "http-body-util", 168 | "mime", 169 | "pin-project-lite", 170 | "rustversion", 171 | "sync_wrapper 1.0.1", 172 | "tower-layer", 173 | "tower-service", 174 | ] 175 | 176 | [[package]] 177 | name = "backtrace" 178 | version = "0.3.74" 179 | source = "registry+https://github.com/rust-lang/crates.io-index" 180 | checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" 181 | dependencies = [ 182 | "addr2line", 183 | "cfg-if", 184 | "libc", 185 | "miniz_oxide", 186 | "object", 187 | "rustc-demangle", 188 | "windows-targets", 189 | ] 190 | 191 | [[package]] 192 | name = "base64" 193 | version = "0.22.1" 194 | source = "registry+https://github.com/rust-lang/crates.io-index" 195 | checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" 196 | 197 | [[package]] 198 | name = "bitflags" 199 | version = "2.6.0" 200 | source = "registry+https://github.com/rust-lang/crates.io-index" 201 | checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" 202 | 203 | [[package]] 204 | name = "byteorder" 205 | version = "1.5.0" 206 | source = "registry+https://github.com/rust-lang/crates.io-index" 207 | checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" 208 | 209 | [[package]] 210 | name = "bytes" 211 | version = "1.7.2" 212 | source = "registry+https://github.com/rust-lang/crates.io-index" 213 | checksum = "428d9aa8fbc0670b7b8d6030a7fadd0f86151cae55e4dbbece15f3780a3dfaf3" 214 | 215 | [[package]] 216 | name = "cfg-if" 217 | version = "1.0.0" 218 | source = "registry+https://github.com/rust-lang/crates.io-index" 219 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 220 | 221 | [[package]] 222 | name = "cfg_aliases" 223 | version = "0.2.1" 224 | source = "registry+https://github.com/rust-lang/crates.io-index" 225 | checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" 226 | 227 | [[package]] 228 | name = "clap" 229 | version = "4.5.18" 230 | source = "registry+https://github.com/rust-lang/crates.io-index" 231 | checksum = "b0956a43b323ac1afaffc053ed5c4b7c1f1800bacd1683c353aabbb752515dd3" 232 | dependencies = [ 233 | "clap_builder", 234 | "clap_derive", 235 | ] 236 | 237 | [[package]] 238 | name = "clap_builder" 239 | version = "4.5.18" 240 | source = "registry+https://github.com/rust-lang/crates.io-index" 241 | checksum = "4d72166dd41634086d5803a47eb71ae740e61d84709c36f3c34110173db3961b" 242 | dependencies = [ 243 | "anstream", 244 | "anstyle", 245 | "clap_lex", 246 | "strsim", 247 | ] 248 | 249 | [[package]] 250 | name = "clap_derive" 251 | version = "4.5.18" 252 | source = "registry+https://github.com/rust-lang/crates.io-index" 253 | checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab" 254 | dependencies = [ 255 | "heck", 256 | "proc-macro2", 257 | "quote", 258 | "syn", 259 | ] 260 | 261 | [[package]] 262 | name = "clap_lex" 263 | version = "0.7.2" 264 | source = "registry+https://github.com/rust-lang/crates.io-index" 265 | checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97" 266 | 267 | [[package]] 268 | name = "colorchoice" 269 | version = "1.0.2" 270 | source = "registry+https://github.com/rust-lang/crates.io-index" 271 | checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0" 272 | 273 | [[package]] 274 | name = "command-fds" 275 | version = "0.3.0" 276 | source = "registry+https://github.com/rust-lang/crates.io-index" 277 | checksum = "7bb11bd1378bf3731b182997b40cefe00aba6a6cc74042c8318c1b271d3badf7" 278 | dependencies = [ 279 | "nix 0.27.1", 280 | "thiserror", 281 | ] 282 | 283 | [[package]] 284 | name = "crossbeam-utils" 285 | version = "0.8.20" 286 | source = "registry+https://github.com/rust-lang/crates.io-index" 287 | checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" 288 | 289 | [[package]] 290 | name = "dashmap" 291 | version = "6.1.0" 292 | source = "registry+https://github.com/rust-lang/crates.io-index" 293 | checksum = "5041cc499144891f3790297212f32a74fb938e5136a14943f338ef9e0ae276cf" 294 | dependencies = [ 295 | "cfg-if", 296 | "crossbeam-utils", 297 | "hashbrown 0.14.5", 298 | "lock_api", 299 | "once_cell", 300 | "parking_lot_core", 301 | ] 302 | 303 | [[package]] 304 | name = "deranged" 305 | version = "0.3.11" 306 | source = "registry+https://github.com/rust-lang/crates.io-index" 307 | checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" 308 | dependencies = [ 309 | "powerfmt", 310 | ] 311 | 312 | [[package]] 313 | name = "either" 314 | version = "1.13.0" 315 | source = "registry+https://github.com/rust-lang/crates.io-index" 316 | checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" 317 | 318 | [[package]] 319 | name = "equivalent" 320 | version = "1.0.1" 321 | source = "registry+https://github.com/rust-lang/crates.io-index" 322 | checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" 323 | 324 | [[package]] 325 | name = "errno" 326 | version = "0.3.9" 327 | source = "registry+https://github.com/rust-lang/crates.io-index" 328 | checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" 329 | dependencies = [ 330 | "libc", 331 | "windows-sys 0.52.0", 332 | ] 333 | 334 | [[package]] 335 | name = "fastrand" 336 | version = "2.1.1" 337 | source = "registry+https://github.com/rust-lang/crates.io-index" 338 | checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" 339 | 340 | [[package]] 341 | name = "fixedbitset" 342 | version = "0.4.2" 343 | source = "registry+https://github.com/rust-lang/crates.io-index" 344 | checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" 345 | 346 | [[package]] 347 | name = "fnv" 348 | version = "1.0.7" 349 | source = "registry+https://github.com/rust-lang/crates.io-index" 350 | checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" 351 | 352 | [[package]] 353 | name = "futures-channel" 354 | version = "0.3.30" 355 | source = "registry+https://github.com/rust-lang/crates.io-index" 356 | checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" 357 | dependencies = [ 358 | "futures-core", 359 | ] 360 | 361 | [[package]] 362 | name = "futures-core" 363 | version = "0.3.30" 364 | source = "registry+https://github.com/rust-lang/crates.io-index" 365 | checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" 366 | 367 | [[package]] 368 | name = "futures-sink" 369 | version = "0.3.30" 370 | source = "registry+https://github.com/rust-lang/crates.io-index" 371 | checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" 372 | 373 | [[package]] 374 | name = "futures-task" 375 | version = "0.3.30" 376 | source = "registry+https://github.com/rust-lang/crates.io-index" 377 | checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" 378 | 379 | [[package]] 380 | name = "futures-util" 381 | version = "0.3.30" 382 | source = "registry+https://github.com/rust-lang/crates.io-index" 383 | checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" 384 | dependencies = [ 385 | "futures-core", 386 | "futures-task", 387 | "pin-project-lite", 388 | "pin-utils", 389 | ] 390 | 391 | [[package]] 392 | name = "getrandom" 393 | version = "0.2.15" 394 | source = "registry+https://github.com/rust-lang/crates.io-index" 395 | checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" 396 | dependencies = [ 397 | "cfg-if", 398 | "libc", 399 | "wasi", 400 | ] 401 | 402 | [[package]] 403 | name = "gimli" 404 | version = "0.31.0" 405 | source = "registry+https://github.com/rust-lang/crates.io-index" 406 | checksum = "32085ea23f3234fc7846555e85283ba4de91e21016dc0455a16286d87a292d64" 407 | 408 | [[package]] 409 | name = "h2" 410 | version = "0.4.6" 411 | source = "registry+https://github.com/rust-lang/crates.io-index" 412 | checksum = "524e8ac6999421f49a846c2d4411f337e53497d8ec55d67753beffa43c5d9205" 413 | dependencies = [ 414 | "atomic-waker", 415 | "bytes", 416 | "fnv", 417 | "futures-core", 418 | "futures-sink", 419 | "http", 420 | "indexmap 2.5.0", 421 | "slab", 422 | "tokio", 423 | "tokio-util", 424 | "tracing", 425 | ] 426 | 427 | [[package]] 428 | name = "hashbrown" 429 | version = "0.12.3" 430 | source = "registry+https://github.com/rust-lang/crates.io-index" 431 | checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" 432 | 433 | [[package]] 434 | name = "hashbrown" 435 | version = "0.14.5" 436 | source = "registry+https://github.com/rust-lang/crates.io-index" 437 | checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" 438 | 439 | [[package]] 440 | name = "heck" 441 | version = "0.5.0" 442 | source = "registry+https://github.com/rust-lang/crates.io-index" 443 | checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" 444 | 445 | [[package]] 446 | name = "hermit-abi" 447 | version = "0.3.9" 448 | source = "registry+https://github.com/rust-lang/crates.io-index" 449 | checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" 450 | 451 | [[package]] 452 | name = "http" 453 | version = "1.1.0" 454 | source = "registry+https://github.com/rust-lang/crates.io-index" 455 | checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" 456 | dependencies = [ 457 | "bytes", 458 | "fnv", 459 | "itoa", 460 | ] 461 | 462 | [[package]] 463 | name = "http-body" 464 | version = "1.0.1" 465 | source = "registry+https://github.com/rust-lang/crates.io-index" 466 | checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" 467 | dependencies = [ 468 | "bytes", 469 | "http", 470 | ] 471 | 472 | [[package]] 473 | name = "http-body-util" 474 | version = "0.1.2" 475 | source = "registry+https://github.com/rust-lang/crates.io-index" 476 | checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" 477 | dependencies = [ 478 | "bytes", 479 | "futures-util", 480 | "http", 481 | "http-body", 482 | "pin-project-lite", 483 | ] 484 | 485 | [[package]] 486 | name = "httparse" 487 | version = "1.9.4" 488 | source = "registry+https://github.com/rust-lang/crates.io-index" 489 | checksum = "0fcc0b4a115bf80b728eb8ea024ad5bd707b615bfed49e0665b6e0f86fd082d9" 490 | 491 | [[package]] 492 | name = "httpdate" 493 | version = "1.0.3" 494 | source = "registry+https://github.com/rust-lang/crates.io-index" 495 | checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" 496 | 497 | [[package]] 498 | name = "hyper" 499 | version = "1.4.1" 500 | source = "registry+https://github.com/rust-lang/crates.io-index" 501 | checksum = "50dfd22e0e76d0f662d429a5f80fcaf3855009297eab6a0a9f8543834744ba05" 502 | dependencies = [ 503 | "bytes", 504 | "futures-channel", 505 | "futures-util", 506 | "h2", 507 | "http", 508 | "http-body", 509 | "httparse", 510 | "httpdate", 511 | "itoa", 512 | "pin-project-lite", 513 | "smallvec", 514 | "tokio", 515 | "want", 516 | ] 517 | 518 | [[package]] 519 | name = "hyper-timeout" 520 | version = "0.5.1" 521 | source = "registry+https://github.com/rust-lang/crates.io-index" 522 | checksum = "3203a961e5c83b6f5498933e78b6b263e208c197b63e9c6c53cc82ffd3f63793" 523 | dependencies = [ 524 | "hyper", 525 | "hyper-util", 526 | "pin-project-lite", 527 | "tokio", 528 | "tower-service", 529 | ] 530 | 531 | [[package]] 532 | name = "hyper-util" 533 | version = "0.1.9" 534 | source = "registry+https://github.com/rust-lang/crates.io-index" 535 | checksum = "41296eb09f183ac68eec06e03cdbea2e759633d4067b2f6552fc2e009bcad08b" 536 | dependencies = [ 537 | "bytes", 538 | "futures-channel", 539 | "futures-util", 540 | "http", 541 | "http-body", 542 | "hyper", 543 | "pin-project-lite", 544 | "socket2", 545 | "tokio", 546 | "tower-service", 547 | "tracing", 548 | ] 549 | 550 | [[package]] 551 | name = "indexmap" 552 | version = "1.9.3" 553 | source = "registry+https://github.com/rust-lang/crates.io-index" 554 | checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" 555 | dependencies = [ 556 | "autocfg", 557 | "hashbrown 0.12.3", 558 | ] 559 | 560 | [[package]] 561 | name = "indexmap" 562 | version = "2.5.0" 563 | source = "registry+https://github.com/rust-lang/crates.io-index" 564 | checksum = "68b900aa2f7301e21c36462b170ee99994de34dff39a4a6a528e80e7376d07e5" 565 | dependencies = [ 566 | "equivalent", 567 | "hashbrown 0.14.5", 568 | ] 569 | 570 | [[package]] 571 | name = "is_terminal_polyfill" 572 | version = "1.70.1" 573 | source = "registry+https://github.com/rust-lang/crates.io-index" 574 | checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" 575 | 576 | [[package]] 577 | name = "itertools" 578 | version = "0.13.0" 579 | source = "registry+https://github.com/rust-lang/crates.io-index" 580 | checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" 581 | dependencies = [ 582 | "either", 583 | ] 584 | 585 | [[package]] 586 | name = "itoa" 587 | version = "1.0.11" 588 | source = "registry+https://github.com/rust-lang/crates.io-index" 589 | checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" 590 | 591 | [[package]] 592 | name = "lazy_static" 593 | version = "1.5.0" 594 | source = "registry+https://github.com/rust-lang/crates.io-index" 595 | checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" 596 | 597 | [[package]] 598 | name = "libc" 599 | version = "0.2.158" 600 | source = "registry+https://github.com/rust-lang/crates.io-index" 601 | checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" 602 | 603 | [[package]] 604 | name = "linux-raw-sys" 605 | version = "0.4.14" 606 | source = "registry+https://github.com/rust-lang/crates.io-index" 607 | checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" 608 | 609 | [[package]] 610 | name = "lock_api" 611 | version = "0.4.12" 612 | source = "registry+https://github.com/rust-lang/crates.io-index" 613 | checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" 614 | dependencies = [ 615 | "autocfg", 616 | "scopeguard", 617 | ] 618 | 619 | [[package]] 620 | name = "log" 621 | version = "0.4.22" 622 | source = "registry+https://github.com/rust-lang/crates.io-index" 623 | checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" 624 | 625 | [[package]] 626 | name = "matchers" 627 | version = "0.1.0" 628 | source = "registry+https://github.com/rust-lang/crates.io-index" 629 | checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" 630 | dependencies = [ 631 | "regex-automata 0.1.10", 632 | ] 633 | 634 | [[package]] 635 | name = "matchit" 636 | version = "0.7.3" 637 | source = "registry+https://github.com/rust-lang/crates.io-index" 638 | checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94" 639 | 640 | [[package]] 641 | name = "memchr" 642 | version = "2.7.4" 643 | source = "registry+https://github.com/rust-lang/crates.io-index" 644 | checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" 645 | 646 | [[package]] 647 | name = "mime" 648 | version = "0.3.17" 649 | source = "registry+https://github.com/rust-lang/crates.io-index" 650 | checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" 651 | 652 | [[package]] 653 | name = "miniz_oxide" 654 | version = "0.8.0" 655 | source = "registry+https://github.com/rust-lang/crates.io-index" 656 | checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" 657 | dependencies = [ 658 | "adler2", 659 | ] 660 | 661 | [[package]] 662 | name = "mio" 663 | version = "1.0.2" 664 | source = "registry+https://github.com/rust-lang/crates.io-index" 665 | checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" 666 | dependencies = [ 667 | "hermit-abi", 668 | "libc", 669 | "wasi", 670 | "windows-sys 0.52.0", 671 | ] 672 | 673 | [[package]] 674 | name = "multimap" 675 | version = "0.10.0" 676 | source = "registry+https://github.com/rust-lang/crates.io-index" 677 | checksum = "defc4c55412d89136f966bbb339008b474350e5e6e78d2714439c386b3137a03" 678 | 679 | [[package]] 680 | name = "nix" 681 | version = "0.27.1" 682 | source = "registry+https://github.com/rust-lang/crates.io-index" 683 | checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053" 684 | dependencies = [ 685 | "bitflags", 686 | "cfg-if", 687 | "libc", 688 | ] 689 | 690 | [[package]] 691 | name = "nix" 692 | version = "0.29.0" 693 | source = "registry+https://github.com/rust-lang/crates.io-index" 694 | checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" 695 | dependencies = [ 696 | "bitflags", 697 | "cfg-if", 698 | "cfg_aliases", 699 | "libc", 700 | ] 701 | 702 | [[package]] 703 | name = "nu-ansi-term" 704 | version = "0.46.0" 705 | source = "registry+https://github.com/rust-lang/crates.io-index" 706 | checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" 707 | dependencies = [ 708 | "overload", 709 | "winapi", 710 | ] 711 | 712 | [[package]] 713 | name = "num-conv" 714 | version = "0.1.0" 715 | source = "registry+https://github.com/rust-lang/crates.io-index" 716 | checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" 717 | 718 | [[package]] 719 | name = "object" 720 | version = "0.36.4" 721 | source = "registry+https://github.com/rust-lang/crates.io-index" 722 | checksum = "084f1a5821ac4c651660a94a7153d27ac9d8a53736203f58b31945ded098070a" 723 | dependencies = [ 724 | "memchr", 725 | ] 726 | 727 | [[package]] 728 | name = "once_cell" 729 | version = "1.19.0" 730 | source = "registry+https://github.com/rust-lang/crates.io-index" 731 | checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" 732 | 733 | [[package]] 734 | name = "overload" 735 | version = "0.1.1" 736 | source = "registry+https://github.com/rust-lang/crates.io-index" 737 | checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" 738 | 739 | [[package]] 740 | name = "parking_lot" 741 | version = "0.12.3" 742 | source = "registry+https://github.com/rust-lang/crates.io-index" 743 | checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" 744 | dependencies = [ 745 | "lock_api", 746 | "parking_lot_core", 747 | ] 748 | 749 | [[package]] 750 | name = "parking_lot_core" 751 | version = "0.9.10" 752 | source = "registry+https://github.com/rust-lang/crates.io-index" 753 | checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" 754 | dependencies = [ 755 | "cfg-if", 756 | "libc", 757 | "redox_syscall", 758 | "smallvec", 759 | "windows-targets", 760 | ] 761 | 762 | [[package]] 763 | name = "percent-encoding" 764 | version = "2.3.1" 765 | source = "registry+https://github.com/rust-lang/crates.io-index" 766 | checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" 767 | 768 | [[package]] 769 | name = "petgraph" 770 | version = "0.6.5" 771 | source = "registry+https://github.com/rust-lang/crates.io-index" 772 | checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" 773 | dependencies = [ 774 | "fixedbitset", 775 | "indexmap 2.5.0", 776 | ] 777 | 778 | [[package]] 779 | name = "pin-project" 780 | version = "1.1.5" 781 | source = "registry+https://github.com/rust-lang/crates.io-index" 782 | checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" 783 | dependencies = [ 784 | "pin-project-internal", 785 | ] 786 | 787 | [[package]] 788 | name = "pin-project-internal" 789 | version = "1.1.5" 790 | source = "registry+https://github.com/rust-lang/crates.io-index" 791 | checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" 792 | dependencies = [ 793 | "proc-macro2", 794 | "quote", 795 | "syn", 796 | ] 797 | 798 | [[package]] 799 | name = "pin-project-lite" 800 | version = "0.2.14" 801 | source = "registry+https://github.com/rust-lang/crates.io-index" 802 | checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" 803 | 804 | [[package]] 805 | name = "pin-utils" 806 | version = "0.1.0" 807 | source = "registry+https://github.com/rust-lang/crates.io-index" 808 | checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" 809 | 810 | [[package]] 811 | name = "powerfmt" 812 | version = "0.2.0" 813 | source = "registry+https://github.com/rust-lang/crates.io-index" 814 | checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" 815 | 816 | [[package]] 817 | name = "ppv-lite86" 818 | version = "0.2.20" 819 | source = "registry+https://github.com/rust-lang/crates.io-index" 820 | checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" 821 | dependencies = [ 822 | "zerocopy", 823 | ] 824 | 825 | [[package]] 826 | name = "prettyplease" 827 | version = "0.2.22" 828 | source = "registry+https://github.com/rust-lang/crates.io-index" 829 | checksum = "479cf940fbbb3426c32c5d5176f62ad57549a0bb84773423ba8be9d089f5faba" 830 | dependencies = [ 831 | "proc-macro2", 832 | "syn", 833 | ] 834 | 835 | [[package]] 836 | name = "proc-macro2" 837 | version = "1.0.86" 838 | source = "registry+https://github.com/rust-lang/crates.io-index" 839 | checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" 840 | dependencies = [ 841 | "unicode-ident", 842 | ] 843 | 844 | [[package]] 845 | name = "prost" 846 | version = "0.13.3" 847 | source = "registry+https://github.com/rust-lang/crates.io-index" 848 | checksum = "7b0487d90e047de87f984913713b85c601c05609aad5b0df4b4573fbf69aa13f" 849 | dependencies = [ 850 | "bytes", 851 | "prost-derive", 852 | ] 853 | 854 | [[package]] 855 | name = "prost-build" 856 | version = "0.13.3" 857 | source = "registry+https://github.com/rust-lang/crates.io-index" 858 | checksum = "0c1318b19085f08681016926435853bbf7858f9c082d0999b80550ff5d9abe15" 859 | dependencies = [ 860 | "bytes", 861 | "heck", 862 | "itertools", 863 | "log", 864 | "multimap", 865 | "once_cell", 866 | "petgraph", 867 | "prettyplease", 868 | "prost", 869 | "prost-types", 870 | "regex", 871 | "syn", 872 | "tempfile", 873 | ] 874 | 875 | [[package]] 876 | name = "prost-derive" 877 | version = "0.13.3" 878 | source = "registry+https://github.com/rust-lang/crates.io-index" 879 | checksum = "e9552f850d5f0964a4e4d0bf306459ac29323ddfbae05e35a7c0d35cb0803cc5" 880 | dependencies = [ 881 | "anyhow", 882 | "itertools", 883 | "proc-macro2", 884 | "quote", 885 | "syn", 886 | ] 887 | 888 | [[package]] 889 | name = "prost-types" 890 | version = "0.13.3" 891 | source = "registry+https://github.com/rust-lang/crates.io-index" 892 | checksum = "4759aa0d3a6232fb8dbdb97b61de2c20047c68aca932c7ed76da9d788508d670" 893 | dependencies = [ 894 | "prost", 895 | ] 896 | 897 | [[package]] 898 | name = "quote" 899 | version = "1.0.37" 900 | source = "registry+https://github.com/rust-lang/crates.io-index" 901 | checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" 902 | dependencies = [ 903 | "proc-macro2", 904 | ] 905 | 906 | [[package]] 907 | name = "rand" 908 | version = "0.8.5" 909 | source = "registry+https://github.com/rust-lang/crates.io-index" 910 | checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" 911 | dependencies = [ 912 | "libc", 913 | "rand_chacha", 914 | "rand_core", 915 | ] 916 | 917 | [[package]] 918 | name = "rand_chacha" 919 | version = "0.3.1" 920 | source = "registry+https://github.com/rust-lang/crates.io-index" 921 | checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" 922 | dependencies = [ 923 | "ppv-lite86", 924 | "rand_core", 925 | ] 926 | 927 | [[package]] 928 | name = "rand_core" 929 | version = "0.6.4" 930 | source = "registry+https://github.com/rust-lang/crates.io-index" 931 | checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" 932 | dependencies = [ 933 | "getrandom", 934 | ] 935 | 936 | [[package]] 937 | name = "redox_syscall" 938 | version = "0.5.4" 939 | source = "registry+https://github.com/rust-lang/crates.io-index" 940 | checksum = "0884ad60e090bf1345b93da0a5de8923c93884cd03f40dfcfddd3b4bee661853" 941 | dependencies = [ 942 | "bitflags", 943 | ] 944 | 945 | [[package]] 946 | name = "regex" 947 | version = "1.10.6" 948 | source = "registry+https://github.com/rust-lang/crates.io-index" 949 | checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619" 950 | dependencies = [ 951 | "aho-corasick", 952 | "memchr", 953 | "regex-automata 0.4.7", 954 | "regex-syntax 0.8.4", 955 | ] 956 | 957 | [[package]] 958 | name = "regex-automata" 959 | version = "0.1.10" 960 | source = "registry+https://github.com/rust-lang/crates.io-index" 961 | checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" 962 | dependencies = [ 963 | "regex-syntax 0.6.29", 964 | ] 965 | 966 | [[package]] 967 | name = "regex-automata" 968 | version = "0.4.7" 969 | source = "registry+https://github.com/rust-lang/crates.io-index" 970 | checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" 971 | dependencies = [ 972 | "aho-corasick", 973 | "memchr", 974 | "regex-syntax 0.8.4", 975 | ] 976 | 977 | [[package]] 978 | name = "regex-syntax" 979 | version = "0.6.29" 980 | source = "registry+https://github.com/rust-lang/crates.io-index" 981 | checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" 982 | 983 | [[package]] 984 | name = "regex-syntax" 985 | version = "0.8.4" 986 | source = "registry+https://github.com/rust-lang/crates.io-index" 987 | checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" 988 | 989 | [[package]] 990 | name = "rustc-demangle" 991 | version = "0.1.24" 992 | source = "registry+https://github.com/rust-lang/crates.io-index" 993 | checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" 994 | 995 | [[package]] 996 | name = "rustix" 997 | version = "0.38.37" 998 | source = "registry+https://github.com/rust-lang/crates.io-index" 999 | checksum = "8acb788b847c24f28525660c4d7758620a7210875711f79e7f663cc152726811" 1000 | dependencies = [ 1001 | "bitflags", 1002 | "errno", 1003 | "libc", 1004 | "linux-raw-sys", 1005 | "windows-sys 0.52.0", 1006 | ] 1007 | 1008 | [[package]] 1009 | name = "rustversion" 1010 | version = "1.0.17" 1011 | source = "registry+https://github.com/rust-lang/crates.io-index" 1012 | checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" 1013 | 1014 | [[package]] 1015 | name = "scopeguard" 1016 | version = "1.2.0" 1017 | source = "registry+https://github.com/rust-lang/crates.io-index" 1018 | checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" 1019 | 1020 | [[package]] 1021 | name = "serde" 1022 | version = "1.0.210" 1023 | source = "registry+https://github.com/rust-lang/crates.io-index" 1024 | checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" 1025 | dependencies = [ 1026 | "serde_derive", 1027 | ] 1028 | 1029 | [[package]] 1030 | name = "serde_derive" 1031 | version = "1.0.210" 1032 | source = "registry+https://github.com/rust-lang/crates.io-index" 1033 | checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" 1034 | dependencies = [ 1035 | "proc-macro2", 1036 | "quote", 1037 | "syn", 1038 | ] 1039 | 1040 | [[package]] 1041 | name = "sharded-slab" 1042 | version = "0.1.7" 1043 | source = "registry+https://github.com/rust-lang/crates.io-index" 1044 | checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" 1045 | dependencies = [ 1046 | "lazy_static", 1047 | ] 1048 | 1049 | [[package]] 1050 | name = "shim" 1051 | version = "0.1.0" 1052 | dependencies = [ 1053 | "anyhow", 1054 | "clap", 1055 | "command-fds", 1056 | "dashmap", 1057 | "nix 0.29.0", 1058 | "prost-types", 1059 | "shim-protos", 1060 | "time", 1061 | "tokio", 1062 | "tokio-stream", 1063 | "tonic", 1064 | "tracing", 1065 | "tracing-subscriber", 1066 | ] 1067 | 1068 | [[package]] 1069 | name = "shim-protos" 1070 | version = "0.1.0" 1071 | dependencies = [ 1072 | "prost", 1073 | "prost-types", 1074 | "tonic", 1075 | "tonic-build", 1076 | ] 1077 | 1078 | [[package]] 1079 | name = "signal-hook-registry" 1080 | version = "1.4.2" 1081 | source = "registry+https://github.com/rust-lang/crates.io-index" 1082 | checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" 1083 | dependencies = [ 1084 | "libc", 1085 | ] 1086 | 1087 | [[package]] 1088 | name = "slab" 1089 | version = "0.4.9" 1090 | source = "registry+https://github.com/rust-lang/crates.io-index" 1091 | checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" 1092 | dependencies = [ 1093 | "autocfg", 1094 | ] 1095 | 1096 | [[package]] 1097 | name = "smallvec" 1098 | version = "1.13.2" 1099 | source = "registry+https://github.com/rust-lang/crates.io-index" 1100 | checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" 1101 | 1102 | [[package]] 1103 | name = "socket2" 1104 | version = "0.5.7" 1105 | source = "registry+https://github.com/rust-lang/crates.io-index" 1106 | checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" 1107 | dependencies = [ 1108 | "libc", 1109 | "windows-sys 0.52.0", 1110 | ] 1111 | 1112 | [[package]] 1113 | name = "strsim" 1114 | version = "0.11.1" 1115 | source = "registry+https://github.com/rust-lang/crates.io-index" 1116 | checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" 1117 | 1118 | [[package]] 1119 | name = "syn" 1120 | version = "2.0.77" 1121 | source = "registry+https://github.com/rust-lang/crates.io-index" 1122 | checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed" 1123 | dependencies = [ 1124 | "proc-macro2", 1125 | "quote", 1126 | "unicode-ident", 1127 | ] 1128 | 1129 | [[package]] 1130 | name = "sync_wrapper" 1131 | version = "0.1.2" 1132 | source = "registry+https://github.com/rust-lang/crates.io-index" 1133 | checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" 1134 | 1135 | [[package]] 1136 | name = "sync_wrapper" 1137 | version = "1.0.1" 1138 | source = "registry+https://github.com/rust-lang/crates.io-index" 1139 | checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" 1140 | 1141 | [[package]] 1142 | name = "tempfile" 1143 | version = "3.12.0" 1144 | source = "registry+https://github.com/rust-lang/crates.io-index" 1145 | checksum = "04cbcdd0c794ebb0d4cf35e88edd2f7d2c4c3e9a5a6dab322839b321c6a87a64" 1146 | dependencies = [ 1147 | "cfg-if", 1148 | "fastrand", 1149 | "once_cell", 1150 | "rustix", 1151 | "windows-sys 0.59.0", 1152 | ] 1153 | 1154 | [[package]] 1155 | name = "thiserror" 1156 | version = "1.0.64" 1157 | source = "registry+https://github.com/rust-lang/crates.io-index" 1158 | checksum = "d50af8abc119fb8bb6dbabcfa89656f46f84aa0ac7688088608076ad2b459a84" 1159 | dependencies = [ 1160 | "thiserror-impl", 1161 | ] 1162 | 1163 | [[package]] 1164 | name = "thiserror-impl" 1165 | version = "1.0.64" 1166 | source = "registry+https://github.com/rust-lang/crates.io-index" 1167 | checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3" 1168 | dependencies = [ 1169 | "proc-macro2", 1170 | "quote", 1171 | "syn", 1172 | ] 1173 | 1174 | [[package]] 1175 | name = "thread_local" 1176 | version = "1.1.8" 1177 | source = "registry+https://github.com/rust-lang/crates.io-index" 1178 | checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" 1179 | dependencies = [ 1180 | "cfg-if", 1181 | "once_cell", 1182 | ] 1183 | 1184 | [[package]] 1185 | name = "time" 1186 | version = "0.3.36" 1187 | source = "registry+https://github.com/rust-lang/crates.io-index" 1188 | checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" 1189 | dependencies = [ 1190 | "deranged", 1191 | "num-conv", 1192 | "powerfmt", 1193 | "serde", 1194 | "time-core", 1195 | ] 1196 | 1197 | [[package]] 1198 | name = "time-core" 1199 | version = "0.1.2" 1200 | source = "registry+https://github.com/rust-lang/crates.io-index" 1201 | checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" 1202 | 1203 | [[package]] 1204 | name = "tokio" 1205 | version = "1.40.0" 1206 | source = "registry+https://github.com/rust-lang/crates.io-index" 1207 | checksum = "e2b070231665d27ad9ec9b8df639893f46727666c6767db40317fbe920a5d998" 1208 | dependencies = [ 1209 | "backtrace", 1210 | "bytes", 1211 | "libc", 1212 | "mio", 1213 | "parking_lot", 1214 | "pin-project-lite", 1215 | "signal-hook-registry", 1216 | "socket2", 1217 | "tokio-macros", 1218 | "windows-sys 0.52.0", 1219 | ] 1220 | 1221 | [[package]] 1222 | name = "tokio-macros" 1223 | version = "2.4.0" 1224 | source = "registry+https://github.com/rust-lang/crates.io-index" 1225 | checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" 1226 | dependencies = [ 1227 | "proc-macro2", 1228 | "quote", 1229 | "syn", 1230 | ] 1231 | 1232 | [[package]] 1233 | name = "tokio-stream" 1234 | version = "0.1.16" 1235 | source = "registry+https://github.com/rust-lang/crates.io-index" 1236 | checksum = "4f4e6ce100d0eb49a2734f8c0812bcd324cf357d21810932c5df6b96ef2b86f1" 1237 | dependencies = [ 1238 | "futures-core", 1239 | "pin-project-lite", 1240 | "tokio", 1241 | ] 1242 | 1243 | [[package]] 1244 | name = "tokio-util" 1245 | version = "0.7.12" 1246 | source = "registry+https://github.com/rust-lang/crates.io-index" 1247 | checksum = "61e7c3654c13bcd040d4a03abee2c75b1d14a37b423cf5a813ceae1cc903ec6a" 1248 | dependencies = [ 1249 | "bytes", 1250 | "futures-core", 1251 | "futures-sink", 1252 | "pin-project-lite", 1253 | "tokio", 1254 | ] 1255 | 1256 | [[package]] 1257 | name = "tonic" 1258 | version = "0.12.3" 1259 | source = "registry+https://github.com/rust-lang/crates.io-index" 1260 | checksum = "877c5b330756d856ffcc4553ab34a5684481ade925ecc54bcd1bf02b1d0d4d52" 1261 | dependencies = [ 1262 | "async-stream", 1263 | "async-trait", 1264 | "axum", 1265 | "base64", 1266 | "bytes", 1267 | "h2", 1268 | "http", 1269 | "http-body", 1270 | "http-body-util", 1271 | "hyper", 1272 | "hyper-timeout", 1273 | "hyper-util", 1274 | "percent-encoding", 1275 | "pin-project", 1276 | "prost", 1277 | "socket2", 1278 | "tokio", 1279 | "tokio-stream", 1280 | "tower 0.4.13", 1281 | "tower-layer", 1282 | "tower-service", 1283 | "tracing", 1284 | ] 1285 | 1286 | [[package]] 1287 | name = "tonic-build" 1288 | version = "0.12.2" 1289 | source = "registry+https://github.com/rust-lang/crates.io-index" 1290 | checksum = "fe4ee8877250136bd7e3d2331632810a4df4ea5e004656990d8d66d2f5ee8a67" 1291 | dependencies = [ 1292 | "prettyplease", 1293 | "proc-macro2", 1294 | "prost-build", 1295 | "quote", 1296 | "syn", 1297 | ] 1298 | 1299 | [[package]] 1300 | name = "tower" 1301 | version = "0.4.13" 1302 | source = "registry+https://github.com/rust-lang/crates.io-index" 1303 | checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" 1304 | dependencies = [ 1305 | "futures-core", 1306 | "futures-util", 1307 | "indexmap 1.9.3", 1308 | "pin-project", 1309 | "pin-project-lite", 1310 | "rand", 1311 | "slab", 1312 | "tokio", 1313 | "tokio-util", 1314 | "tower-layer", 1315 | "tower-service", 1316 | "tracing", 1317 | ] 1318 | 1319 | [[package]] 1320 | name = "tower" 1321 | version = "0.5.1" 1322 | source = "registry+https://github.com/rust-lang/crates.io-index" 1323 | checksum = "2873938d487c3cfb9aed7546dc9f2711d867c9f90c46b889989a2cb84eba6b4f" 1324 | dependencies = [ 1325 | "futures-core", 1326 | "futures-util", 1327 | "pin-project-lite", 1328 | "sync_wrapper 0.1.2", 1329 | "tower-layer", 1330 | "tower-service", 1331 | ] 1332 | 1333 | [[package]] 1334 | name = "tower-layer" 1335 | version = "0.3.3" 1336 | source = "registry+https://github.com/rust-lang/crates.io-index" 1337 | checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" 1338 | 1339 | [[package]] 1340 | name = "tower-service" 1341 | version = "0.3.3" 1342 | source = "registry+https://github.com/rust-lang/crates.io-index" 1343 | checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" 1344 | 1345 | [[package]] 1346 | name = "tracing" 1347 | version = "0.1.40" 1348 | source = "registry+https://github.com/rust-lang/crates.io-index" 1349 | checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" 1350 | dependencies = [ 1351 | "pin-project-lite", 1352 | "tracing-attributes", 1353 | "tracing-core", 1354 | ] 1355 | 1356 | [[package]] 1357 | name = "tracing-attributes" 1358 | version = "0.1.27" 1359 | source = "registry+https://github.com/rust-lang/crates.io-index" 1360 | checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" 1361 | dependencies = [ 1362 | "proc-macro2", 1363 | "quote", 1364 | "syn", 1365 | ] 1366 | 1367 | [[package]] 1368 | name = "tracing-core" 1369 | version = "0.1.32" 1370 | source = "registry+https://github.com/rust-lang/crates.io-index" 1371 | checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" 1372 | dependencies = [ 1373 | "once_cell", 1374 | "valuable", 1375 | ] 1376 | 1377 | [[package]] 1378 | name = "tracing-log" 1379 | version = "0.2.0" 1380 | source = "registry+https://github.com/rust-lang/crates.io-index" 1381 | checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" 1382 | dependencies = [ 1383 | "log", 1384 | "once_cell", 1385 | "tracing-core", 1386 | ] 1387 | 1388 | [[package]] 1389 | name = "tracing-subscriber" 1390 | version = "0.3.18" 1391 | source = "registry+https://github.com/rust-lang/crates.io-index" 1392 | checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" 1393 | dependencies = [ 1394 | "matchers", 1395 | "nu-ansi-term", 1396 | "once_cell", 1397 | "regex", 1398 | "sharded-slab", 1399 | "smallvec", 1400 | "thread_local", 1401 | "tracing", 1402 | "tracing-core", 1403 | "tracing-log", 1404 | ] 1405 | 1406 | [[package]] 1407 | name = "try-lock" 1408 | version = "0.2.5" 1409 | source = "registry+https://github.com/rust-lang/crates.io-index" 1410 | checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" 1411 | 1412 | [[package]] 1413 | name = "unicode-ident" 1414 | version = "1.0.13" 1415 | source = "registry+https://github.com/rust-lang/crates.io-index" 1416 | checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" 1417 | 1418 | [[package]] 1419 | name = "utf8parse" 1420 | version = "0.2.2" 1421 | source = "registry+https://github.com/rust-lang/crates.io-index" 1422 | checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" 1423 | 1424 | [[package]] 1425 | name = "valuable" 1426 | version = "0.1.0" 1427 | source = "registry+https://github.com/rust-lang/crates.io-index" 1428 | checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" 1429 | 1430 | [[package]] 1431 | name = "want" 1432 | version = "0.3.1" 1433 | source = "registry+https://github.com/rust-lang/crates.io-index" 1434 | checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" 1435 | dependencies = [ 1436 | "try-lock", 1437 | ] 1438 | 1439 | [[package]] 1440 | name = "wasi" 1441 | version = "0.11.0+wasi-snapshot-preview1" 1442 | source = "registry+https://github.com/rust-lang/crates.io-index" 1443 | checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" 1444 | 1445 | [[package]] 1446 | name = "winapi" 1447 | version = "0.3.9" 1448 | source = "registry+https://github.com/rust-lang/crates.io-index" 1449 | checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" 1450 | dependencies = [ 1451 | "winapi-i686-pc-windows-gnu", 1452 | "winapi-x86_64-pc-windows-gnu", 1453 | ] 1454 | 1455 | [[package]] 1456 | name = "winapi-i686-pc-windows-gnu" 1457 | version = "0.4.0" 1458 | source = "registry+https://github.com/rust-lang/crates.io-index" 1459 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 1460 | 1461 | [[package]] 1462 | name = "winapi-x86_64-pc-windows-gnu" 1463 | version = "0.4.0" 1464 | source = "registry+https://github.com/rust-lang/crates.io-index" 1465 | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 1466 | 1467 | [[package]] 1468 | name = "windows-sys" 1469 | version = "0.52.0" 1470 | source = "registry+https://github.com/rust-lang/crates.io-index" 1471 | checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" 1472 | dependencies = [ 1473 | "windows-targets", 1474 | ] 1475 | 1476 | [[package]] 1477 | name = "windows-sys" 1478 | version = "0.59.0" 1479 | source = "registry+https://github.com/rust-lang/crates.io-index" 1480 | checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" 1481 | dependencies = [ 1482 | "windows-targets", 1483 | ] 1484 | 1485 | [[package]] 1486 | name = "windows-targets" 1487 | version = "0.52.6" 1488 | source = "registry+https://github.com/rust-lang/crates.io-index" 1489 | checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" 1490 | dependencies = [ 1491 | "windows_aarch64_gnullvm", 1492 | "windows_aarch64_msvc", 1493 | "windows_i686_gnu", 1494 | "windows_i686_gnullvm", 1495 | "windows_i686_msvc", 1496 | "windows_x86_64_gnu", 1497 | "windows_x86_64_gnullvm", 1498 | "windows_x86_64_msvc", 1499 | ] 1500 | 1501 | [[package]] 1502 | name = "windows_aarch64_gnullvm" 1503 | version = "0.52.6" 1504 | source = "registry+https://github.com/rust-lang/crates.io-index" 1505 | checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" 1506 | 1507 | [[package]] 1508 | name = "windows_aarch64_msvc" 1509 | version = "0.52.6" 1510 | source = "registry+https://github.com/rust-lang/crates.io-index" 1511 | checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" 1512 | 1513 | [[package]] 1514 | name = "windows_i686_gnu" 1515 | version = "0.52.6" 1516 | source = "registry+https://github.com/rust-lang/crates.io-index" 1517 | checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" 1518 | 1519 | [[package]] 1520 | name = "windows_i686_gnullvm" 1521 | version = "0.52.6" 1522 | source = "registry+https://github.com/rust-lang/crates.io-index" 1523 | checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" 1524 | 1525 | [[package]] 1526 | name = "windows_i686_msvc" 1527 | version = "0.52.6" 1528 | source = "registry+https://github.com/rust-lang/crates.io-index" 1529 | checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" 1530 | 1531 | [[package]] 1532 | name = "windows_x86_64_gnu" 1533 | version = "0.52.6" 1534 | source = "registry+https://github.com/rust-lang/crates.io-index" 1535 | checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" 1536 | 1537 | [[package]] 1538 | name = "windows_x86_64_gnullvm" 1539 | version = "0.52.6" 1540 | source = "registry+https://github.com/rust-lang/crates.io-index" 1541 | checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" 1542 | 1543 | [[package]] 1544 | name = "windows_x86_64_msvc" 1545 | version = "0.52.6" 1546 | source = "registry+https://github.com/rust-lang/crates.io-index" 1547 | checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" 1548 | 1549 | [[package]] 1550 | name = "zerocopy" 1551 | version = "0.7.35" 1552 | source = "registry+https://github.com/rust-lang/crates.io-index" 1553 | checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" 1554 | dependencies = [ 1555 | "byteorder", 1556 | "zerocopy-derive", 1557 | ] 1558 | 1559 | [[package]] 1560 | name = "zerocopy-derive" 1561 | version = "0.7.35" 1562 | source = "registry+https://github.com/rust-lang/crates.io-index" 1563 | checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" 1564 | dependencies = [ 1565 | "proc-macro2", 1566 | "quote", 1567 | "syn", 1568 | ] 1569 | --------------------------------------------------------------------------------