pub struct Client { /* private fields */ }Expand description
A connection to one host of a service. One request in flight at a time;
open a second Client for parallel calls. Dropping it closes the
connection, which the host treats as a disconnect (jobs started with
cancel_on_disconnect are cancelled).
Implementations§
Source§impl Client
impl Client
Sourcepub fn connect(
suite: &Suite,
service: &str,
app: &str,
) -> Result<Client, ServiceError>
pub fn connect( suite: &Suite, service: &str, app: &str, ) -> Result<Client, ServiceError>
Discover the live host of service on suite and say hello as app,
bounded by DEFAULT_DEADLINE.
The host is not authenticated. Discovery is a file (service.json) and a socket path
that any program running as the same user can write or bind, and suite itself may have
come from an environment variable. The transport proves only that whatever answered runs
as the current user, so the hello and every request, including any secret in one, go to
that program. A client that sends secrets, or that acts on what the host answers, must use
Client::connect_expecting instead.
Sourcepub fn connect_with(
suite: &Suite,
service: &str,
app: &str,
deadline: Option<Duration>,
) -> Result<Client, ServiceError>
pub fn connect_with( suite: &Suite, service: &str, app: &str, deadline: Option<Duration>, ) -> Result<Client, ServiceError>
Like Client::connect with an explicit deadline for connect + hello,
which also becomes the client’s per-request deadline (None = unbounded).
The host is not authenticated: see Client::connect.
Sourcepub fn connect_config(config: &ClientConfig) -> Result<Client, ServiceError>
pub fn connect_config(config: &ClientConfig) -> Result<Client, ServiceError>
Connect through a ClientConfig: the suite and deadline come from the configuration,
and ClientConfig::ignore_env_overrides is honoured. The host is still not
authenticated (see Client::connect); this hardens only where the client looks.
Sourcepub fn connect_expecting(
config: &ClientConfig,
expect: &HostExpectation,
) -> Result<Client, ConnectError>
pub fn connect_expecting( config: &ClientConfig, expect: &HostExpectation, ) -> Result<Client, ConnectError>
Discover the host of the configured service, verify it is the program expect names, and
only then say hello.
The OS is asked who is on the listening end of the connected socket: its uid must equal
this process’s, and its executable (read from the kernel for that process, canonicalised)
must be one of expect’s. The process id is proven stable across the read (start time,
and on macOS the audit token, before and after, and the pid re-read from the socket). A
caller-supplied HostExpectation::with_verifier check then runs. Platforms: macOS
(getpeereid, LOCAL_PEERPID, proc_pidpath), Linux (SO_PEERCRED, /proc/<pid>/exe),
Windows (the pipe’s server process: its token user, a held process handle,
QueryFullProcessImageNameW); elsewhere the refusal is
HostIdentityReason::Unverified and nothing is
sent. See the README, “Verifying the host”.
Order. The check runs after the kernel has completed the socket connect and before
anything is written. Nothing application-level precedes it: no hello, no request, no
length prefix. The only thing the other side can observe of a refused attempt is a
connection that closes without a byte. The deadline in config bounds the whole attempt.
A refusal is ConnectError::HostIdentity, distinct from ConnectError::Service
(no record, unreachable, timeout, hello refused). It is not retryable. The check is made
once, at connect, for the life of the connection.
Sourcepub fn verified_host(&self) -> Option<&HostProcess>
pub fn verified_host(&self) -> Option<&HostProcess>
The host process the OS identified and this client verified, for a client opened with
Client::connect_expecting; None for one opened with Client::connect or
Client::connect_with, whose host was never checked.
Sourcepub fn set_deadline(&self, deadline: Option<Duration>)
pub fn set_deadline(&self, deadline: Option<Duration>)
Set the per-request deadline for later calls (None = unbounded).
pub fn record(&self) -> &ServiceRecord
Sourcepub fn hello(&self) -> &Value
pub fn hello(&self) -> &Value
The host’s hello: service, role, rank, version, and the methods this app may call.
Sourcepub fn abort(&self)
pub fn abort(&self)
Close the connection from any thread. A request blocked in
Client::call returns connection_closed; the host sees the disconnect.
pub fn call(&self, method: &str, params: Value) -> Result<Value, ServiceError>
Sourcepub fn call_events(
&self,
method: &str,
params: Value,
on_event: &mut dyn FnMut(&Value),
) -> Result<Value, ServiceError>
pub fn call_events( &self, method: &str, params: Value, on_event: &mut dyn FnMut(&Value), ) -> Result<Value, ServiceError>
Like Client::call, streaming the request’s event frames to on_event.
The per-request deadline starts when this method is entered and covers waiting for the connection (another call in flight), the write, and the reply: one monotonic deadline.
Sourcepub fn call_events_until(
&self,
method: &str,
params: Value,
deadline: Option<Instant>,
on_event: &mut dyn FnMut(&Value),
) -> Result<Value, ServiceError>
pub fn call_events_until( &self, method: &str, params: Value, deadline: Option<Instant>, on_event: &mut dyn FnMut(&Value), ) -> Result<Value, ServiceError>
Like Client::call_events, bounded by an absolute monotonic deadline (None =
unbounded) that the caller fixed earlier. Waiting for a request already in flight on this
connection counts against it: when it passes first, this returns the typed timeout without
aborting the connection, because the request that holds it is not this one’s.
Source§impl Client
impl Client
Sourcepub fn call_retrying(
suite: &Suite,
service: &str,
app: &str,
method: &str,
params: Value,
policy: RetryPolicy,
on_event: &mut dyn FnMut(&Value),
) -> Result<Value, ServiceError>
pub fn call_retrying( suite: &Suite, service: &str, app: &str, method: &str, params: Value, policy: RetryPolicy, on_event: &mut dyn FnMut(&Value), ) -> Result<Value, ServiceError>
Connect, call, and on a retryable error (host handoff, closed connection,
service unavailable) re-read discovery and resubmit the whole request.
The host is not authenticated: see Client::connect.
Sourcepub fn call_retrying_expecting(
config: &ClientConfig,
expect: &HostExpectation,
method: &str,
params: Value,
policy: RetryPolicy,
on_event: &mut dyn FnMut(&Value),
) -> Result<Value, ServiceError>
pub fn call_retrying_expecting( config: &ClientConfig, expect: &HostExpectation, method: &str, params: Value, policy: RetryPolicy, on_event: &mut dyn FnMut(&Value), ) -> Result<Value, ServiceError>
Client::call_retrying that verifies the host on every attempt, as
Client::connect_expecting does. A host identity refusal is not retryable and is
returned at once as a ServiceError with code host_identity
(ERROR_HOST_IDENTITY); it is never replayed against another attempt. The per-attempt
deadline is policy.request_deadline, not the configuration’s.