api_client: Add ability to send file descriptors

Allow the user to send a list of file descriptors along with the HTTP
request.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
This commit is contained in:
Sebastien Boeuf 2021-07-20 15:31:32 +02:00
parent 0ac4545c5b
commit 9af2968a7d
3 changed files with 26 additions and 5 deletions

3
Cargo.lock generated
View File

@ -51,6 +51,9 @@ checksum = "595d3cfa7a60d4555cb5067b99f07142a08ea778de5cf993f7b75c7d8fabc486"
[[package]] [[package]]
name = "api_client" name = "api_client"
version = "0.1.0" version = "0.1.0"
dependencies = [
"vmm-sys-util",
]
[[package]] [[package]]
name = "arc-swap" name = "arc-swap"

View File

@ -3,3 +3,6 @@ name = "api_client"
version = "0.1.0" version = "0.1.0"
authors = ["The Cloud Hypervisor Authors"] authors = ["The Cloud Hypervisor Authors"]
edition = "2018" edition = "2018"
[dependencies]
vmm-sys-util = "0.8.0"

View File

@ -5,10 +5,13 @@
use std::fmt; use std::fmt;
use std::io::{Read, Write}; use std::io::{Read, Write};
use std::os::unix::io::RawFd;
use vmm_sys_util::sock_ctrl_msg::ScmSocket;
#[derive(Debug)] #[derive(Debug)]
pub enum Error { pub enum Error {
Socket(std::io::Error), Socket(std::io::Error),
SocketSendFds(vmm_sys_util::errno::Error),
StatusCodeParsing(std::num::ParseIntError), StatusCodeParsing(std::num::ParseIntError),
MissingProtocol, MissingProtocol,
ContentLengthParsing(std::num::ParseIntError), ContentLengthParsing(std::num::ParseIntError),
@ -20,6 +23,7 @@ impl fmt::Display for Error {
use Error::*; use Error::*;
match self { match self {
Socket(e) => write!(f, "Error writing to or reading from HTTP socket: {}", e), Socket(e) => write!(f, "Error writing to or reading from HTTP socket: {}", e),
SocketSendFds(e) => write!(f, "Error writing to or reading from HTTP socket: {}", e),
StatusCodeParsing(e) => write!(f, "Error parsing HTTP status code: {}", e), StatusCodeParsing(e) => write!(f, "Error parsing HTTP status code: {}", e),
MissingProtocol => write!(f, "HTTP output is missing protocol statement"), MissingProtocol => write!(f, "HTTP output is missing protocol statement"),
ContentLengthParsing(e) => write!(f, "Error parsing HTTP Content-Length field: {}", e), ContentLengthParsing(e) => write!(f, "Error parsing HTTP Content-Length field: {}", e),
@ -133,21 +137,23 @@ fn parse_http_response(socket: &mut dyn Read) -> Result<Option<String>, Error> {
} }
} }
pub fn simple_api_command<T: Read + Write>( pub fn simple_api_command_with_fds<T: Read + Write + ScmSocket>(
socket: &mut T, socket: &mut T,
method: &str, method: &str,
c: &str, c: &str,
request_body: Option<&str>, request_body: Option<&str>,
request_fds: Vec<RawFd>,
) -> Result<(), Error> { ) -> Result<(), Error> {
socket socket
.write_all( .send_with_fds(
format!( &[format!(
"{} /api/v1/vm.{} HTTP/1.1\r\nHost: localhost\r\nAccept: */*\r\n", "{} /api/v1/vm.{} HTTP/1.1\r\nHost: localhost\r\nAccept: */*\r\n",
method, c method, c
) )
.as_bytes(), .as_bytes()],
&request_fds,
) )
.map_err(Error::Socket)?; .map_err(Error::SocketSendFds)?;
if let Some(request_body) = request_body { if let Some(request_body) = request_body {
socket socket
@ -170,3 +176,12 @@ pub fn simple_api_command<T: Read + Write>(
} }
Ok(()) Ok(())
} }
pub fn simple_api_command<T: Read + Write + ScmSocket>(
socket: &mut T,
method: &str,
c: &str,
request_body: Option<&str>,
) -> Result<(), Error> {
simple_api_command_with_fds(socket, method, c, request_body, Vec::new())
}