#region Copyright notice and license
// Copyright 2015 gRPC authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#endregion
using System;
using System.Threading;
using Grpc.Core.Internal;
using Grpc.Core.Utils;
namespace Grpc.Core
{
///
/// Options for calls made by client.
///
public struct CallOptions
{
Metadata headers;
DateTime? deadline;
CancellationToken cancellationToken;
WriteOptions writeOptions;
ContextPropagationToken propagationToken;
CallCredentials credentials;
CallFlags flags;
///
/// Creates a new instance of CallOptions struct.
///
/// Headers to be sent with the call.
/// Deadline for the call to finish. null means no deadline.
/// Can be used to request cancellation of the call.
/// Write options that will be used for this call.
/// Context propagation token obtained from .
/// Credentials to use for this call.
public CallOptions(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken),
WriteOptions writeOptions = null, ContextPropagationToken propagationToken = null, CallCredentials credentials = null)
{
this.headers = headers;
this.deadline = deadline;
this.cancellationToken = cancellationToken;
this.writeOptions = writeOptions;
this.propagationToken = propagationToken;
this.credentials = credentials;
this.flags = default(CallFlags);
}
///
/// Headers to send at the beginning of the call.
///
public Metadata Headers
{
get { return headers; }
}
///
/// Call deadline.
///
public DateTime? Deadline
{
get { return deadline; }
}
///
/// Token that can be used for cancelling the call on the client side.
/// Cancelling the token will request cancellation
/// of the remote call. Best effort will be made to deliver the cancellation
/// notification to the server and interaction of the call with the server side
/// will be terminated. Unless the call finishes before the cancellation could
/// happen (there is an inherent race),
/// the call will finish with StatusCode.Cancelled status.
///
public CancellationToken CancellationToken
{
get { return cancellationToken; }
}
///
/// Write options that will be used for this call.
///
public WriteOptions WriteOptions
{
get { return this.writeOptions; }
}
///
/// Token for propagating parent call context.
///
public ContextPropagationToken PropagationToken
{
get { return this.propagationToken; }
}
///
/// Credentials to use for this call.
///
public CallCredentials Credentials
{
get { return this.credentials; }
}
///
/// If true and and channel is in ChannelState.TransientFailure, the call will attempt waiting for the channel to recover
/// instead of failing immediately (which is the default "FailFast" semantics).
/// Note: experimental API that can change or be removed without any prior notice.
///
public bool IsWaitForReady
{
get { return (this.flags & CallFlags.WaitForReady) == CallFlags.WaitForReady; }
}
///
/// Flags to use for this call.
///
internal CallFlags Flags
{
get { return this.flags; }
}
///
/// Returns new instance of with
/// Headers set to the value provided. Values of all other fields are preserved.
///
/// The headers.
public CallOptions WithHeaders(Metadata headers)
{
var newOptions = this;
newOptions.headers = headers;
return newOptions;
}
///
/// Returns new instance of with
/// Deadline set to the value provided. Values of all other fields are preserved.
///
/// The deadline.
public CallOptions WithDeadline(DateTime deadline)
{
var newOptions = this;
newOptions.deadline = deadline;
return newOptions;
}
///
/// Returns new instance of with
/// CancellationToken set to the value provided. Values of all other fields are preserved.
///
/// The cancellation token.
public CallOptions WithCancellationToken(CancellationToken cancellationToken)
{
var newOptions = this;
newOptions.cancellationToken = cancellationToken;
return newOptions;
}
///
/// Returns new instance of with
/// WriteOptions set to the value provided. Values of all other fields are preserved.
///
/// The write options.
public CallOptions WithWriteOptions(WriteOptions writeOptions)
{
var newOptions = this;
newOptions.writeOptions = writeOptions;
return newOptions;
}
///
/// Returns new instance of with
/// PropagationToken set to the value provided. Values of all other fields are preserved.
///
/// The context propagation token.
public CallOptions WithPropagationToken(ContextPropagationToken propagationToken)
{
var newOptions = this;
newOptions.propagationToken = propagationToken;
return newOptions;
}
///
/// Returns new instance of with
/// Credentials set to the value provided. Values of all other fields are preserved.
///
/// The call credentials.
public CallOptions WithCredentials(CallCredentials credentials)
{
var newOptions = this;
newOptions.credentials = credentials;
return newOptions;
}
///
/// Returns new instance of with "WaitForReady" semantics enabled/disabled.
/// .
/// Note: experimental API that can change or be removed without any prior notice.
///
public CallOptions WithWaitForReady(bool waitForReady = true)
{
if (waitForReady)
{
return WithFlags(this.flags | CallFlags.WaitForReady);
}
return WithFlags(this.flags & ~CallFlags.WaitForReady);
}
///
/// Returns new instance of with
/// Flags set to the value provided. Values of all other fields are preserved.
///
/// The call flags.
internal CallOptions WithFlags(CallFlags flags)
{
var newOptions = this;
newOptions.flags = flags;
return newOptions;
}
///
/// Returns a new instance of with
/// all previously unset values set to their defaults and deadline and cancellation
/// token propagated when appropriate.
///
internal CallOptions Normalize()
{
var newOptions = this;
if (propagationToken != null)
{
if (propagationToken.Options.IsPropagateDeadline)
{
GrpcPreconditions.CheckArgument(!newOptions.deadline.HasValue,
"Cannot propagate deadline from parent call. The deadline has already been set explicitly.");
newOptions.deadline = propagationToken.ParentDeadline;
}
if (propagationToken.Options.IsPropagateCancellation)
{
GrpcPreconditions.CheckArgument(!newOptions.cancellationToken.CanBeCanceled,
"Cannot propagate cancellation token from parent call. The cancellation token has already been set to a non-default value.");
newOptions.cancellationToken = propagationToken.ParentCancellationToken;
}
}
newOptions.headers = newOptions.headers ?? Metadata.Empty;
newOptions.deadline = newOptions.deadline ?? DateTime.MaxValue;
return newOptions;
}
}
}