Skip to content

Commit 5d5ded7

Browse files
committedFeb 16, 2021
Bootstrap socket location from env variable
This commit adds functionality to create a IPC connector from a URL and to bootstrap the IPC handler creation from an environment variable using this new functionality. Signed-off-by: Ionut Mihalcea <[email protected]>
1 parent 7cc28ea commit 5d5ded7

File tree

7 files changed

+66
-12
lines changed

7 files changed

+66
-12
lines changed
 

‎Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ log = "0.4.11"
1919
derivative = "2.1.1"
2020
zeroize = "1.1.0"
2121
users = "0.10.0"
22+
url = "2.2.0"
2223

2324
[dev-dependencies]
2425
mockstream = "0.0.3"

‎src/core/basic_client.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,7 @@ impl BasicClient {
202202
/// [`set_default_provider`](#method.set_default_provider)
203203
pub fn new(app_name: Option<String>) -> Result<Self> {
204204
let mut client = BasicClient {
205-
op_client: Default::default(),
205+
op_client: OperationClient::new()?,
206206
auth_data: Authentication::None,
207207
implicit_provider: ProviderID::Core,
208208
};

‎src/core/ipc_handler/mod.rs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,16 @@
11
// Copyright 2020 Contributors to the Parsec project.
22
// SPDX-License-Identifier: Apache-2.0
33
//! Types implementing an abstraction over IPC channels
4-
use crate::error::Result;
4+
use crate::error::{ClientErrorKind, Error, Result};
55
use std::io::{Read, Write};
66
use std::time::Duration;
7+
use url::Url;
78

89
pub mod unix_socket;
910

11+
/// Default timeout for client IPC requests.
12+
pub const DEFAULT_TIMEOUT: Duration = Duration::from_secs(60);
13+
1014
/// This trait is created to allow the iterator returned by incoming to iterate over a trait object
1115
/// that implements both Read and Write.
1216
pub trait ReadWrite: Read + Write {}
@@ -23,3 +27,14 @@ pub trait Connect {
2327
/// Set timeout for all produced streams.
2428
fn set_timeout(&mut self, timeout: Option<Duration>);
2529
}
30+
31+
/// Create an implementation of `Connect` from the socket URL
32+
pub fn connector_from_url(socket_url: Url) -> Result<Box<dyn Connect + Send + Sync>> {
33+
match socket_url.scheme() {
34+
"unix" => Ok(Box::from(unix_socket::Handler::new(
35+
socket_url.path().into(),
36+
Some(DEFAULT_TIMEOUT),
37+
)?)),
38+
_ => Err(Error::Client(ClientErrorKind::InvalidSocketUrl)),
39+
}
40+
}

‎src/core/ipc_handler/unix_socket.rs

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,14 @@
22
// SPDX-License-Identifier: Apache-2.0
33
//! Handler for Unix domain sockets
44
use super::{Connect, ReadWrite};
5-
use crate::error::{ClientErrorKind, Result};
5+
use crate::error::{ClientErrorKind, Error, Result};
6+
use std::os::unix::fs::FileTypeExt;
67
use std::os::unix::net::UnixStream;
78
use std::path::PathBuf;
89
use std::time::Duration;
910

10-
const DEFAULT_SOCKET_PATH: &str = "/run/parsec/parsec.sock";
11-
const DEFAULT_TIMEOUT: Duration = Duration::from_secs(60);
11+
/// Default socket path used by the service.
12+
pub const DEFAULT_SOCKET_PATH: &str = "/run/parsec/parsec.sock";
1213

1314
/// IPC handler for Unix domain sockets
1415
#[derive(Debug, Clone)]
@@ -40,16 +41,25 @@ impl Connect for Handler {
4041

4142
impl Handler {
4243
/// Create new client using given socket path and timeout duration
43-
pub fn new(path: PathBuf, timeout: Option<Duration>) -> Self {
44-
Handler { path, timeout }
44+
pub fn new(path: PathBuf, timeout: Option<Duration>) -> Result<Self> {
45+
if path.exists()
46+
&& std::fs::metadata(&path)
47+
.map_err(|_| Error::Client(ClientErrorKind::InvalidSocketAddress))?
48+
.file_type()
49+
.is_socket()
50+
{
51+
Ok(Handler { path, timeout })
52+
} else {
53+
Err(Error::Client(ClientErrorKind::InvalidSocketAddress))
54+
}
4555
}
4656
}
4757

4858
impl Default for Handler {
4959
fn default() -> Self {
5060
Handler {
5161
path: DEFAULT_SOCKET_PATH.into(),
52-
timeout: Some(DEFAULT_TIMEOUT),
62+
timeout: Some(super::DEFAULT_TIMEOUT),
5363
}
5464
}
5565
}

‎src/core/operation_client.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,11 @@ impl OperationClient {
4040
/// seconds on reads and writes on the socket. It uses the version 1.0 wire protocol
4141
/// to form requests, the direct authentication method and protobuf format as
4242
/// content type.
43-
pub fn new() -> OperationClient {
44-
Default::default()
43+
pub fn new() -> Result<OperationClient> {
44+
Ok(OperationClient {
45+
request_client: RequestClient::new()?,
46+
..Default::default()
47+
})
4548
}
4649

4750
fn operation_to_request(

‎src/core/request_client.rs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
// Copyright 2020 Contributors to the Parsec project.
22
// SPDX-License-Identifier: Apache-2.0
33
//! Request-level client
4-
use super::ipc_handler::{unix_socket, Connect};
4+
use super::ipc_handler::{self, unix_socket, Connect};
55
use crate::error::{ClientErrorKind, Result};
66
use derivative::Derivative;
77
use parsec_interface::requests::{Request, Response};
8+
use std::env;
89
use std::time::Duration;
910

1011
const DEFAULT_MAX_BODY_SIZE: usize = usize::max_value();
@@ -29,6 +30,18 @@ pub struct RequestClient {
2930
}
3031

3132
impl RequestClient {
33+
/// Creates a new `RequestClient`, bootstrapping the socket
34+
/// location.
35+
pub fn new() -> Result<Self> {
36+
Ok(RequestClient {
37+
ipc_handler: ipc_handler::connector_from_url(url::Url::parse(
38+
&env::var("PARSEC_SERVICE_ENDPOINT")
39+
.unwrap_or(format!("unix:{}", unix_socket::DEFAULT_SOCKET_PATH)),
40+
)?)?,
41+
max_body_size: DEFAULT_MAX_BODY_SIZE,
42+
})
43+
}
44+
3245
/// Send a request and get a response.
3346
pub fn process_request(&self, request: Request) -> Result<Response> {
3447
// Try to connect once, wait for a timeout until trying again.

‎src/error.rs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,10 @@ pub enum ClientErrorKind {
4444
MissingParam,
4545
/// The requested resource was not found.
4646
NotFound,
47+
/// The socket address provided is not valid
48+
InvalidSocketAddress,
49+
/// The socket URL is invalid
50+
InvalidSocketUrl,
4751
}
4852

4953
impl From<ClientErrorKind> for Error {
@@ -52,6 +56,12 @@ impl From<ClientErrorKind> for Error {
5256
}
5357
}
5458

59+
impl From<url::ParseError> for Error {
60+
fn from(_: url::ParseError) -> Self {
61+
Error::Client(ClientErrorKind::InvalidSocketUrl)
62+
}
63+
}
64+
5565
impl fmt::Display for ClientErrorKind {
5666
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
5767
match self {
@@ -67,7 +77,9 @@ impl fmt::Display for ClientErrorKind {
6777
ClientErrorKind::NoProvider => write!(f, "client is missing an implicit provider"),
6878
ClientErrorKind::NoAuthenticator => write!(f, "service is not reporting any authenticators or none of the reported ones are supported by the client"),
6979
ClientErrorKind::MissingParam => write!(f, "one of the `Option` parameters was required but was not provided"),
70-
ClientErrorKind::NotFound => write!(f, "one of the resources required in the operation was not found")
80+
ClientErrorKind::NotFound => write!(f, "one of the resources required in the operation was not found"),
81+
ClientErrorKind::InvalidSocketAddress => write!(f, "the socket address provided in the URL is not valid"),
82+
ClientErrorKind::InvalidSocketUrl => write!(f, "the socket URL is invalid"),
7183
}
7284
}
7385
}

0 commit comments

Comments
 (0)
Please sign in to comment.