blob: 75d8906a691804b14d3a8b0bd98c09a60d17588e [file] [log] [blame]
Jan Tattermusche5e57ad2015-08-05 14:54:08 -07001#region Copyright notice and license
2
Jan Tattermusch7897ae92017-06-07 22:57:36 +02003// Copyright 2015 gRPC authors.
Jan Tattermusche5e57ad2015-08-05 14:54:08 -07004//
Jan Tattermusch7897ae92017-06-07 22:57:36 +02005// Licensed under the Apache License, Version 2.0 (the "License");
6// you may not use this file except in compliance with the License.
7// You may obtain a copy of the License at
Jan Tattermusche5e57ad2015-08-05 14:54:08 -07008//
Jan Tattermusch7897ae92017-06-07 22:57:36 +02009// http://www.apache.org/licenses/LICENSE-2.0
Jan Tattermusche5e57ad2015-08-05 14:54:08 -070010//
Jan Tattermusch7897ae92017-06-07 22:57:36 +020011// Unless required by applicable law or agreed to in writing, software
12// distributed under the License is distributed on an "AS IS" BASIS,
13// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14// See the License for the specific language governing permissions and
15// limitations under the License.
Jan Tattermusche5e57ad2015-08-05 14:54:08 -070016
17#endregion
18
19using System;
20using System.Threading;
21
22using Grpc.Core.Internal;
23using Grpc.Core.Utils;
24
25namespace Grpc.Core
26{
27 /// <summary>
28 /// Options for calls made by client.
29 /// </summary>
Jan Tattermusch9698b5b2015-08-10 16:40:19 -070030 public struct CallOptions
Jan Tattermusche5e57ad2015-08-05 14:54:08 -070031 {
Jan Tattermusch9698b5b2015-08-10 16:40:19 -070032 Metadata headers;
33 DateTime? deadline;
34 CancellationToken cancellationToken;
35 WriteOptions writeOptions;
36 ContextPropagationToken propagationToken;
Jan Tattermusch5bd70052015-10-06 16:47:49 -070037 CallCredentials credentials;
Jan Tattermusch0faf80c2016-11-22 16:05:07 +010038 CallFlags flags;
Jan Tattermusche5e57ad2015-08-05 14:54:08 -070039
40 /// <summary>
Jan Tattermusch9698b5b2015-08-10 16:40:19 -070041 /// Creates a new instance of <c>CallOptions</c> struct.
Jan Tattermusche5e57ad2015-08-05 14:54:08 -070042 /// </summary>
43 /// <param name="headers">Headers to be sent with the call.</param>
44 /// <param name="deadline">Deadline for the call to finish. null means no deadline.</param>
45 /// <param name="cancellationToken">Can be used to request cancellation of the call.</param>
Jan Tattermuschbff90ac2015-08-06 21:30:26 -070046 /// <param name="writeOptions">Write options that will be used for this call.</param>
Jan Tattermusch392fae22015-08-08 22:21:57 -070047 /// <param name="propagationToken">Context propagation token obtained from <see cref="ServerCallContext"/>.</param>
Jan Tattermusch74f39e12015-09-23 20:14:56 -070048 /// <param name="credentials">Credentials to use for this call.</param>
Jan Tattermusch9698b5b2015-08-10 16:40:19 -070049 public CallOptions(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken),
Jan Tattermusch058f5552016-12-02 16:52:26 +010050 WriteOptions writeOptions = null, ContextPropagationToken propagationToken = null, CallCredentials credentials = null)
Jan Tattermusche5e57ad2015-08-05 14:54:08 -070051 {
Jan Tattermusch9698b5b2015-08-10 16:40:19 -070052 this.headers = headers;
53 this.deadline = deadline;
54 this.cancellationToken = cancellationToken;
Jan Tattermusch5321d492015-08-07 23:21:27 -070055 this.writeOptions = writeOptions;
Jan Tattermusch392fae22015-08-08 22:21:57 -070056 this.propagationToken = propagationToken;
Jan Tattermusch74f39e12015-09-23 20:14:56 -070057 this.credentials = credentials;
Jan Tattermusch058f5552016-12-02 16:52:26 +010058 this.flags = default(CallFlags);
Jan Tattermusche5e57ad2015-08-05 14:54:08 -070059 }
60
61 /// <summary>
62 /// Headers to send at the beginning of the call.
63 /// </summary>
64 public Metadata Headers
65 {
66 get { return headers; }
67 }
68
69 /// <summary>
70 /// Call deadline.
71 /// </summary>
Jan Tattermusch9698b5b2015-08-10 16:40:19 -070072 public DateTime? Deadline
Jan Tattermusche5e57ad2015-08-05 14:54:08 -070073 {
74 get { return deadline; }
75 }
76
77 /// <summary>
Jan Tattermusch6acc07d2016-06-03 17:03:30 -070078 /// Token that can be used for cancelling the call on the client side.
79 /// Cancelling the token will request cancellation
80 /// of the remote call. Best effort will be made to deliver the cancellation
81 /// notification to the server and interaction of the call with the server side
82 /// will be terminated. Unless the call finishes before the cancellation could
83 /// happen (there is an inherent race),
84 /// the call will finish with <c>StatusCode.Cancelled</c> status.
Jan Tattermusche5e57ad2015-08-05 14:54:08 -070085 /// </summary>
86 public CancellationToken CancellationToken
87 {
88 get { return cancellationToken; }
89 }
Jan Tattermuschbff90ac2015-08-06 21:30:26 -070090
91 /// <summary>
92 /// Write options that will be used for this call.
93 /// </summary>
94 public WriteOptions WriteOptions
95 {
Mathieu Leenhardtc1d2ecb2016-02-04 22:32:14 +010096 get { return this.writeOptions; }
Jan Tattermuschbff90ac2015-08-06 21:30:26 -070097 }
Jan Tattermusch392fae22015-08-08 22:21:57 -070098
99 /// <summary>
100 /// Token for propagating parent call context.
101 /// </summary>
102 public ContextPropagationToken PropagationToken
103 {
Mathieu Leenhardtc1d2ecb2016-02-04 22:32:14 +0100104 get { return this.propagationToken; }
Jan Tattermusch392fae22015-08-08 22:21:57 -0700105 }
Jan Tattermusch9698b5b2015-08-10 16:40:19 -0700106
107 /// <summary>
Jan Tattermusch74f39e12015-09-23 20:14:56 -0700108 /// Credentials to use for this call.
109 /// </summary>
Jan Tattermusch5bd70052015-10-06 16:47:49 -0700110 public CallCredentials Credentials
Jan Tattermusch74f39e12015-09-23 20:14:56 -0700111 {
Mathieu Leenhardtc1d2ecb2016-02-04 22:32:14 +0100112 get { return this.credentials; }
Jan Tattermusch74f39e12015-09-23 20:14:56 -0700113 }
114
115 /// <summary>
Jan Tattermusch058f5552016-12-02 16:52:26 +0100116 /// If <c>true</c> and and channel is in <c>ChannelState.TransientFailure</c>, the call will attempt waiting for the channel to recover
117 /// instead of failing immediately (which is the default "FailFast" semantics).
118 /// Note: experimental API that can change or be removed without any prior notice.
119 /// </summary>
120 public bool IsWaitForReady
121 {
122 get { return (this.flags & CallFlags.WaitForReady) == CallFlags.WaitForReady; }
123 }
124
125 /// <summary>
Jan Tattermusch0faf80c2016-11-22 16:05:07 +0100126 /// Flags to use for this call.
127 /// </summary>
Jan Tattermusch058f5552016-12-02 16:52:26 +0100128 internal CallFlags Flags
Jan Tattermusch0faf80c2016-11-22 16:05:07 +0100129 {
130 get { return this.flags; }
131 }
132
133 /// <summary>
Jan Tattermusch9698b5b2015-08-10 16:40:19 -0700134 /// Returns new instance of <see cref="CallOptions"/> with
135 /// <c>Headers</c> set to the value provided. Values of all other fields are preserved.
136 /// </summary>
Jan Tattermusch12855fc2015-08-24 16:43:23 -0700137 /// <param name="headers">The headers.</param>
Jan Tattermusch9698b5b2015-08-10 16:40:19 -0700138 public CallOptions WithHeaders(Metadata headers)
139 {
140 var newOptions = this;
141 newOptions.headers = headers;
142 return newOptions;
143 }
144
145 /// <summary>
146 /// Returns new instance of <see cref="CallOptions"/> with
147 /// <c>Deadline</c> set to the value provided. Values of all other fields are preserved.
148 /// </summary>
Jan Tattermusch12855fc2015-08-24 16:43:23 -0700149 /// <param name="deadline">The deadline.</param>
Jan Tattermusch9698b5b2015-08-10 16:40:19 -0700150 public CallOptions WithDeadline(DateTime deadline)
151 {
152 var newOptions = this;
153 newOptions.deadline = deadline;
154 return newOptions;
155 }
156
157 /// <summary>
158 /// Returns new instance of <see cref="CallOptions"/> with
159 /// <c>CancellationToken</c> set to the value provided. Values of all other fields are preserved.
160 /// </summary>
Jan Tattermusch12855fc2015-08-24 16:43:23 -0700161 /// <param name="cancellationToken">The cancellation token.</param>
Jan Tattermusch9698b5b2015-08-10 16:40:19 -0700162 public CallOptions WithCancellationToken(CancellationToken cancellationToken)
163 {
164 var newOptions = this;
165 newOptions.cancellationToken = cancellationToken;
166 return newOptions;
167 }
168
169 /// <summary>
Mathieu Leenhardtc1d2ecb2016-02-04 22:32:14 +0100170 /// Returns new instance of <see cref="CallOptions"/> with
171 /// <c>WriteOptions</c> set to the value provided. Values of all other fields are preserved.
172 /// </summary>
Mathieu Leenhardtced27482016-02-04 22:57:49 +0100173 /// <param name="writeOptions">The write options.</param>
Mathieu Leenhardtc1d2ecb2016-02-04 22:32:14 +0100174 public CallOptions WithWriteOptions(WriteOptions writeOptions)
175 {
176 var newOptions = this;
177 newOptions.writeOptions = writeOptions;
178 return newOptions;
179 }
180
181 /// <summary>
182 /// Returns new instance of <see cref="CallOptions"/> with
183 /// <c>PropagationToken</c> set to the value provided. Values of all other fields are preserved.
184 /// </summary>
185 /// <param name="propagationToken">The context propagation token.</param>
186 public CallOptions WithPropagationToken(ContextPropagationToken propagationToken)
187 {
188 var newOptions = this;
189 newOptions.propagationToken = propagationToken;
190 return newOptions;
191 }
192
193 /// <summary>
194 /// Returns new instance of <see cref="CallOptions"/> with
195 /// <c>Credentials</c> set to the value provided. Values of all other fields are preserved.
196 /// </summary>
197 /// <param name="credentials">The call credentials.</param>
198 public CallOptions WithCredentials(CallCredentials credentials)
199 {
200 var newOptions = this;
201 newOptions.credentials = credentials;
202 return newOptions;
203 }
204
205 /// <summary>
Jan Tattermusch058f5552016-12-02 16:52:26 +0100206 /// Returns new instance of <see cref="CallOptions"/> with "WaitForReady" semantics enabled/disabled.
207 /// <see cref="IsWaitForReady"/>.
208 /// Note: experimental API that can change or be removed without any prior notice.
209 /// </summary>
210 public CallOptions WithWaitForReady(bool waitForReady = true)
211 {
212 if (waitForReady)
213 {
214 return WithFlags(this.flags | CallFlags.WaitForReady);
215 }
216 return WithFlags(this.flags & ~CallFlags.WaitForReady);
217 }
218
219 /// <summary>
Jan Tattermusch0faf80c2016-11-22 16:05:07 +0100220 /// Returns new instance of <see cref="CallOptions"/> with
221 /// <c>Flags</c> set to the value provided. Values of all other fields are preserved.
222 /// </summary>
223 /// <param name="flags">The call flags.</param>
Jan Tattermusch058f5552016-12-02 16:52:26 +0100224 internal CallOptions WithFlags(CallFlags flags)
Jan Tattermusch0faf80c2016-11-22 16:05:07 +0100225 {
226 var newOptions = this;
227 newOptions.flags = flags;
228 return newOptions;
229 }
230
231 /// <summary>
Jan Tattermusch9698b5b2015-08-10 16:40:19 -0700232 /// Returns a new instance of <see cref="CallOptions"/> with
233 /// all previously unset values set to their defaults and deadline and cancellation
234 /// token propagated when appropriate.
235 /// </summary>
236 internal CallOptions Normalize()
237 {
238 var newOptions = this;
239 if (propagationToken != null)
240 {
241 if (propagationToken.Options.IsPropagateDeadline)
242 {
Jan Tattermusch7a3ee6a2016-02-18 10:36:02 -0800243 GrpcPreconditions.CheckArgument(!newOptions.deadline.HasValue,
Jan Tattermusch9698b5b2015-08-10 16:40:19 -0700244 "Cannot propagate deadline from parent call. The deadline has already been set explicitly.");
245 newOptions.deadline = propagationToken.ParentDeadline;
246 }
247 if (propagationToken.Options.IsPropagateCancellation)
248 {
Jan Tattermusch7a3ee6a2016-02-18 10:36:02 -0800249 GrpcPreconditions.CheckArgument(!newOptions.cancellationToken.CanBeCanceled,
Jan Tattermusch9698b5b2015-08-10 16:40:19 -0700250 "Cannot propagate cancellation token from parent call. The cancellation token has already been set to a non-default value.");
Jan Tattermusch3d45afe2015-12-10 18:11:22 -0800251 newOptions.cancellationToken = propagationToken.ParentCancellationToken;
Jan Tattermusch9698b5b2015-08-10 16:40:19 -0700252 }
253 }
254
255 newOptions.headers = newOptions.headers ?? Metadata.Empty;
256 newOptions.deadline = newOptions.deadline ?? DateTime.MaxValue;
257 return newOptions;
258 }
Jan Tattermusche5e57ad2015-08-05 14:54:08 -0700259 }
260}