oasis_core_runtime/
init.rs

1//! Runtime initialization.
2use std::sync::Arc;
3
4use anyhow::Result;
5use slog::{error, info};
6
7use crate::{
8    common::logger::{get_logger, init_logger},
9    config::Config,
10    dispatcher::{Dispatcher, Initializer},
11    future::new_tokio_runtime,
12    identity::Identity,
13    protocol::{Protocol, Stream},
14    TeeType, BUILD_INFO,
15};
16
17/// Starts the runtime.
18pub fn start_runtime(initializer: Box<dyn Initializer>, config: Config) {
19    // Initialize logging.
20    init_logger(log::Level::Info);
21    let logger = get_logger("runtime");
22    info!(logger, "Runtime is starting");
23
24    // Perform TDX-specific early initialization.
25    #[cfg(feature = "tdx")]
26    if BUILD_INFO.tee_type == TeeType::Tdx {
27        crate::common::tdx::init::init();
28    }
29
30    // Initialize runtime identity with runtime attestation key and runtime encryption key.
31    let identity = Arc::new(Identity::new());
32
33    // Initialize the async Tokio runtime.
34    let tokio_runtime = new_tokio_runtime();
35    let tokio_handle = tokio_runtime.handle();
36
37    // Initialize the dispatcher.
38    let dispatcher = Dispatcher::new(tokio_handle.clone(), initializer, identity.clone());
39
40    // Connect to the runtime host.
41    info!(logger, "Establishing connection with the worker host");
42
43    let stream = match connect() {
44        Ok(stream) => stream,
45        Err(err) => {
46            error!(logger, "Failed to connect with the worker host"; "err" => %err);
47            return;
48        }
49    };
50
51    // Initialize the protocol handler loop.
52    let protocol = Arc::new(Protocol::new(
53        tokio_handle.clone(),
54        stream,
55        identity,
56        dispatcher,
57        config,
58    ));
59
60    // Start handling protocol messages. This blocks the main thread forever
61    // (or until we get a shutdown request).
62    protocol.start();
63
64    info!(logger, "Protocol handler terminated, shutting down");
65}
66
67/// Establish a connection with the host.
68fn connect() -> Result<Stream> {
69    match BUILD_INFO.tee_type {
70        #[cfg(not(target_env = "sgx"))]
71        TeeType::Sgx | TeeType::None => {
72            let stream = std::os::unix::net::UnixStream::connect(
73                std::env::var("OASIS_WORKER_HOST").unwrap_or_default(),
74            )?;
75            Ok(Stream::Unix(stream))
76        }
77
78        #[cfg(target_env = "sgx")]
79        TeeType::Sgx => {
80            let stream = std::net::TcpStream::connect("worker-host")?;
81            Ok(Stream::Tcp(stream))
82        }
83
84        #[cfg(feature = "tdx")]
85        TeeType::Tdx => {
86            /// VSOCK port used for the Runtime Host Protocol.
87            const VSOCK_PORT_RHP: u32 = 1;
88
89            // Accept first connection.
90            let listener = vsock::VsockListener::bind(&vsock::VsockAddr::new(
91                libc::VMADDR_CID_ANY,
92                VSOCK_PORT_RHP,
93            ))?;
94            let stream = listener
95                .incoming()
96                .next()
97                .ok_or(anyhow::anyhow!("failed to accept connection"))??;
98            Ok(Stream::Vsock(stream))
99        }
100
101        #[allow(unreachable_patterns)]
102        _ => Err(anyhow::anyhow!("unsupported TEE type")),
103    }
104}