pub fn bind_and_run(
        &mut self,
        path: PathBuf,
        process_time_reporter: ProcessTimeReporter,
        seccomp_filter: BpfProgramRef,
        api_payload_limit: usize,
        socket_ready: mpsc::Sender<bool>,
    ) -> Result<()> {
        let mut server = HttpServer::new(path).unwrap_or_else(|e| {
            error!("Error creating the HTTP server: {}", e);
            std::process::exit(vmm::FcExitCode::GenericError as i32);
        });
        // Announce main thread that the socket path was created.
        // As per the doc, "A send operation can only fail if the receiving end of a channel is disconnected".
        // so this means that the main thread has exited.
        socket_ready
            .send(true)
            .expect("No one to signal that the socket path is ready!");
        // Set the api payload size limit.
        server.set_payload_max_size(api_payload_limit);

        // Store process start time metric.
        process_time_reporter.report_start_time();
        // Store process CPU start time metric.
        process_time_reporter.report_cpu_start_time();

        // Load seccomp filters on the API thread.
        // Execution panics if filters cannot be loaded, use --no-seccomp if skipping filters
        // altogether is the desired behaviour.
        if let Err(e) = seccompiler::apply_filter(seccomp_filter) {
            panic!(
                "Failed to set the requested seccomp filters on the API thread: {}",
                e
            );
        }

        server.start_server().expect("Cannot start HTTP server");

        loop {
            let request_vec = match server.requests() {
                Ok(vec) => vec,
                Err(e) => {
                    // print request error, but keep server running
                    error!("API Server error on retrieving incoming request: {}", e);
                    continue;
                }
            };
            for server_request in request_vec {
                let request_processing_start_us =
                    utils::time::get_time_us(utils::time::ClockType::Monotonic);
                server
                    .respond(
                        // Use `self.handle_request()` as the processing callback.
                        server_request.process(|request| {
                            self.handle_request(request, request_processing_start_us)
                        }),
                    )
                    .or_else(|e| {
                        error!("API Server encountered an error on response: {}", e);
                        Ok(())
                    })?;

                let delta_us = utils::time::get_time_us(utils::time::ClockType::Monotonic)
                    - request_processing_start_us;
                debug!("Total previous API call duration: {} us.", delta_us);

                if self.shutdown_flag {
                    server.flush_outgoing_writes();
                    debug!(
                        "/shutdown-internal request received, API server thread now ending itself"
                    );
                    return Ok(());
                }
            }
        }
    }
/// Starts the HTTP Server by binding to the socket path provided as
/// an argument.
///
/// # Arguments
///
/// * `path` - the socket path on which the server will wait for requests.
/// * `start_time_us` - the timestamp for when the process was started in us.
/// * `start_time_cpu_us` - the timestamp for when the process was started in CPU us.
/// * `seccomp_filter` - the seccomp filter to apply.
///
/// # Example
///
/// ```
/// use api_server::ApiServer;
/// use logger::ProcessTimeReporter;
/// use std::env::consts::ARCH;
/// use std::{
///     convert::TryInto,
///     io::Read,
///     io::Write,
///     os::unix::net::UnixStream,
///     path::PathBuf,
///     sync::mpsc::{channel, Receiver, Sender},
///     sync::{Arc, Barrier},
///     thread,
///     time::Duration,
/// };
/// use utils::{eventfd::EventFd, tempfile::TempFile};
/// use vmm::rpc_interface::VmmData;
/// use vmm::seccomp_filters::{get_filters, SeccompConfig};
/// use vmm::vmm_config::instance_info::InstanceInfo;
/// use vmm::HTTP_MAX_PAYLOAD_SIZE;
///
/// let mut tmp_socket = TempFile::new().unwrap();
/// tmp_socket.remove().unwrap();
/// let path_to_socket = tmp_socket.as_path().to_str().unwrap().to_owned();
/// let api_thread_path_to_socket = path_to_socket.clone();
/// let to_vmm_fd = EventFd::new(libc::EFD_NONBLOCK).unwrap();
/// let (api_request_sender, _from_api) = channel();
/// let (to_api, vmm_response_receiver) = channel();
/// let time_reporter = ProcessTimeReporter::new(Some(1), Some(1), Some(1));
/// let seccomp_filters = get_filters(SeccompConfig::None).unwrap();
/// let payload_limit = HTTP_MAX_PAYLOAD_SIZE;
/// let (socket_ready_sender, socket_ready_receiver): (Sender<bool>, Receiver<bool>) = channel();
///
/// thread::Builder::new()
///     .name("fc_api_test".to_owned())
///     .spawn(move || {
///         ApiServer::new(api_request_sender, vmm_response_receiver, to_vmm_fd)
///             .bind_and_run(
///                 PathBuf::from(api_thread_path_to_socket),
///                 time_reporter,
///                 seccomp_filters.get("api").unwrap(),
///                 payload_limit,
///                 socket_ready_sender,
///             )
///             .unwrap();
///     })
///     .unwrap();
///
/// socket_ready_receiver.recv().unwrap();
/// to_api
///     .send(Box::new(Ok(VmmData::InstanceInformation(
///         InstanceInfo::default(),
///     ))))
///     .unwrap();
/// let mut sock = UnixStream::connect(PathBuf::from(path_to_socket)).unwrap();
/// // Send a GET instance-info request.
/// assert!(sock.write_all(b"GET / HTTP/1.1\r\n\r\n").is_ok());
/// let mut buf: [u8; 100] = [0; 100];
/// assert!(sock.read(&mut buf[..]).unwrap() > 0);
/// ```
Starts the HTTP Server by binding to the socket path provided as
an argument.
Starts the HTTP Server by binding to the socket path provided as an argument .
pub fn bind_and_run(
        &mut self,
        path: PathBuf,
        process_time_reporter: ProcessTimeReporter,
        seccomp_filter: BpfProgramRef,
        api_payload_limit: usize,
        socket_ready: mpsc::Sender<bool>,
    ) -> Result<()> {
        let mut server = HttpServer::new(path).unwrap_or_else(|e| {
            error!("Error creating the HTTP server: {}", e);
            std::process::exit(vmm::FcExitCode::GenericError as i32);
        });
        // Announce main thread that the socket path was created.
        // As per the doc, "A send operation can only fail if the receiving end of a channel is disconnected".
        // so this means that the main thread has exited.
        socket_ready
            .send(true)
            .expect("No one to signal that the socket path is ready!");
        // Set the api payload size limit.
        server.set_payload_max_size(api_payload_limit);
        // Store process start time metric.
        process_time_reporter.report_start_time();
        // Store process CPU start time metric.
        process_time_reporter.report_cpu_start_time();
        // Load seccomp filters on the API thread.
        // Execution panics if filters cannot be loaded, use --no-seccomp if skipping filters
        // altogether is the desired behaviour.
        if let Err(e) = seccompiler::apply_filter(seccomp_filter) {
            panic!(
                "Failed to set the requested seccomp filters on the API thread: {}",
                e
            );
        }
        server.start_server().expect("Cannot start HTTP server");
        loop {
            let request_vec = match server.requests() {
                Ok(vec) => vec,
                Err(e) => {
                    // print request error, but keep server running
                    error!("API Server error on retrieving incoming request: {}", e);
                    continue;
                }
            };
            for server_request in request_vec {
                let request_processing_start_us =
                    utils::time::get_time_us(utils::time::ClockType::Monotonic);
                server
                    .respond(
                        // Use `self.handle_request()` as the processing callback.
                        server_request.process(|request| {
                            self.handle_request(request, request_processing_start_us)
                        }),
                    )
                    .or_else(|e| {
                        error!("API Server encountered an error on response: {}", e);
                        Ok(())
                    })?;
                let delta_us = utils::time::get_time_us(utils::time::ClockType::Monotonic)
                    - request_processing_start_us;
                debug!("Total previous API call duration: {} us.", delta_us);
                if self.shutdown_flag {
                    server.flush_outgoing_writes();
                    debug!(
                        "/shutdown-internal request received, API server thread now ending itself"
                    );
                    return Ok(());
                }
            }
        }
    }
pub fn bind_and_run ( & mut self , path : PathBuf , process_time_reporter : ProcessTimeReporter , seccomp_filter : BpfProgramRef , api_payload_limit : usize , socket_ready : mpsc :: Sender < bool > , ) -> Result < ( ) > { let mut server = HttpServer :: new ( path ) . unwrap_or_else ( | e | { error ! ( " " e ) ; std :: process :: exit ( vmm :: FcExitCode :: GenericError as i32 ) ; } ) ; // Announce main thread that the socket path was created. // As per the doc, "A send operation can only fail if the receiving end of a channel is disconnected". // so this means that the main thread has exited. socket_ready . send ( true ) . expect ( " " ) ; // Set the api payload size limit. server . set_payload_max_size ( api_payload_limit ) ; // Store process start time metric. process_time_reporter . report_start_time ( ) ; // Store process CPU start time metric. process_time_reporter . report_cpu_start_time ( ) ; // Load seccomp filters on the API thread. // Execution panics if filters cannot be loaded, use --no-seccomp if skipping filters // altogether is the desired behaviour. if let Err ( e ) = seccompiler :: apply_filter ( seccomp_filter ) { panic ! ( " " e ) ; } server . start_server ( ) . expect ( " " ) ; loop { let request_vec = match server . requests ( ) { Ok ( vec ) => vec , Err ( e ) => { // print request error, but keep server running error ! ( " " e ) ; continue ; } } ; for server_request in request_vec { let request_processing_start_us = utils :: time :: get_time_us ( utils :: time :: ClockType :: Monotonic ) ; server . respond ( // Use `self.handle_request()` as the processing callback. server_request . process ( | request | { self . handle_request ( request , request_processing_start_us ) } ) , ) . or_else ( | e | { error ! ( " " e ) ; Ok ( ( ) ) } ) ? ; let delta_us = utils :: time :: get_time_us ( utils :: time :: ClockType :: Monotonic ) - request_processing_start_us ; debug ! ( " " delta_us ) ; if self . shutdown_flag { server . flush_outgoing_writes ( ) ; debug ! ( " " ) ; return Ok ( ( ) ) ; } } } }
Starts the HTTP Server by binding to the socket path provided as
an argument.
Starts the HTTP Server by binding to the socket path provided as an argument .
&mut self
path
PathBuf
process_time_reporter
ProcessTimeReporter
seccomp_filter
BpfProgramRef
api_payload_limit
usize
socket_ready
mpsc::Sender<bool>
&mut self
path
PathBuf
process_time_reporter
ProcessTimeReporter
seccomp_filter
BpfProgramRef
api_payload_limit
usize
socket_ready
mpsc::Sender<bool>
example
```
use api_server::ApiServer;
use logger::ProcessTimeReporter;
use std::env::consts::ARCH;
use std::{
convert::TryInto,
io::Read,
io::Write,
os::unix::net::UnixStream,
path::PathBuf,
sync::mpsc::{channel, Receiver, Sender},
sync::{Arc, Barrier},
thread,
time::Duration,
};
use utils::{eventfd::EventFd, tempfile::TempFile};
use vmm::rpc_interface::VmmData;
use vmm::seccomp_filters::{get_filters, SeccompConfig};
use vmm::vmm_config::instance_info::InstanceInfo;
use vmm::HTTP_MAX_PAYLOAD_SIZE.

let mut tmp_socket = TempFile::new().unwrap();
tmp_socket.remove().unwrap();
let path_to_socket = tmp_socket.as_path().to_str().unwrap().to_owned();
let api_thread_path_to_socket = path_to_socket.clone();
let to_vmm_fd = EventFd::new(libc::EFD_NONBLOCK).unwrap();
let (api_request_sender, _from_api) = channel();
let (to_api, vmm_response_receiver) = channel();
let time_reporter = ProcessTimeReporter::new(Some(1), Some(1), Some(1));
let seccomp_filters = get_filters(SeccompConfig::None).unwrap();
let payload_limit = HTTP_MAX_PAYLOAD_SIZE;
let (socket_ready_sender, socket_ready_receiver): (Sender, Receiver) = channel().

:Builder::new()
.name("fc_api_test".to_owned())
.spawn(move || {
ApiServer::new(api_request_sender, vmm_response_receiver, to_vmm_fd)
.bind_and_run(
PathBuf::from(api_thread_path_to_socket),
time_reporter,
seccomp_filters.get("api").unwrap(),
payload_limit,
socket_ready_sender,
)
.unwrap();
})
.unwrap().

socket_ready_receiver.recv().unwrap();
to_api
.send(Box::new(Ok(VmmData::InstanceInformation(
InstanceInfo::default(),
))))
.unwrap();
let mut sock = UnixStream::connect(PathBuf::from(path_to_socket)).unwrap();
Send a GET instance-info request.
` ` ` use api_server :: ApiServer ; use logger :: ProcessTimeReporter ; use std :: env :: consts :: ARCH ; use std :: { convert :: TryInto io :: Read io :: Write os :: unix :: net :: UnixStream path :: PathBuf sync :: mpsc :: { channel Receiver Sender } sync :: { Arc Barrier } thread time :: Duration } ; use utils :: { eventfd :: EventFd tempfile :: TempFile } ; use vmm :: rpc_interface :: VmmData ; use vmm :: seccomp_filters :: { get_filters SeccompConfig } ; use vmm :: vmm_config :: instance_info :: InstanceInfo ; use vmm :: HTTP_MAX_PAYLOAD_SIZE . let mut tmp_socket = TempFile :: new () . unwrap () ; tmp_socket . remove () . unwrap () ; let path_to_socket = tmp_socket . as_path () . to_str () . unwrap () . to_owned () ; let api_thread_path_to_socket = path_to_socket . clone () ; let to_vmm_fd = EventFd :: new ( libc :: EFD_NONBLOCK ) . unwrap () ; let ( api_request_sender _from_api ) = channel () ; let ( to_api vmm_response_receiver ) = channel () ; let time_reporter = ProcessTimeReporter :: new ( Some ( 1 ) Some ( 1 ) Some ( 1 )) ; let seccomp_filters = get_filters ( SeccompConfig :: None ) . unwrap () ; let payload_limit = HTTP_MAX_PAYLOAD_SIZE ; let ( socket_ready_sender socket_ready_receiver ) : ( Sender Receiver ) = channel () . : Builder :: new () . name ( " fc_api_test " . to_owned () ) . spawn ( move || { ApiServer :: new ( api_request_sender vmm_response_receiver to_vmm_fd ) . bind_and_run ( PathBuf :: from ( api_thread_path_to_socket ) time_reporter seccomp_filters . get ( " api " ) . unwrap () payload_limit socket_ready_sender ) . unwrap () ; } ) . unwrap () . socket_ready_receiver . recv () . unwrap () ; to_api . send ( Box :: new ( Ok ( VmmData :: InstanceInformation ( InstanceInfo :: default () )))) . unwrap () ; let mut sock = UnixStream :: connect ( PathBuf :: from ( path_to_socket )) . unwrap () ; Send a GET instance - info request .