• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #region Copyright notice and license
2 
3 // Copyright 2015 gRPC authors.
4 //
5 // 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
8 //
9 //     http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // 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.
16 
17 #endregion
18 
19 using System;
20 using System.Threading;
21 using System.Threading.Tasks;
22 
23 using Grpc.Core.Internal;
24 
25 namespace Grpc.Core
26 {
27     /// <summary>
28     /// Context for a server-side call.
29     /// </summary>
30     public class ServerCallContext
31     {
32         private readonly CallSafeHandle callHandle;
33         private readonly string method;
34         private readonly string host;
35         private readonly DateTime deadline;
36         private readonly Metadata requestHeaders;
37         private readonly CancellationToken cancellationToken;
38         private readonly Metadata responseTrailers = new Metadata();
39         private readonly Func<Metadata, Task> writeHeadersFunc;
40         private readonly IHasWriteOptions writeOptionsHolder;
41         private readonly Lazy<AuthContext> authContext;
42         private readonly Func<string> testingOnlyPeerGetter;
43         private readonly Func<AuthContext> testingOnlyAuthContextGetter;
44         private readonly Func<ContextPropagationToken> testingOnlyContextPropagationTokenFactory;
45 
46         private Status status = Status.DefaultSuccess;
47 
ServerCallContext(CallSafeHandle callHandle, string method, string host, DateTime deadline, Metadata requestHeaders, CancellationToken cancellationToken, Func<Metadata, Task> writeHeadersFunc, IHasWriteOptions writeOptionsHolder)48         internal ServerCallContext(CallSafeHandle callHandle, string method, string host, DateTime deadline, Metadata requestHeaders, CancellationToken cancellationToken,
49             Func<Metadata, Task> writeHeadersFunc, IHasWriteOptions writeOptionsHolder)
50             : this(callHandle, method, host, deadline, requestHeaders, cancellationToken, writeHeadersFunc, writeOptionsHolder, null, null, null)
51         {
52         }
53 
54         // Additional constructor params should be used for testing only
ServerCallContext(CallSafeHandle callHandle, string method, string host, DateTime deadline, Metadata requestHeaders, CancellationToken cancellationToken, Func<Metadata, Task> writeHeadersFunc, IHasWriteOptions writeOptionsHolder, Func<string> testingOnlyPeerGetter, Func<AuthContext> testingOnlyAuthContextGetter, Func<ContextPropagationToken> testingOnlyContextPropagationTokenFactory)55         internal ServerCallContext(CallSafeHandle callHandle, string method, string host, DateTime deadline, Metadata requestHeaders, CancellationToken cancellationToken,
56             Func<Metadata, Task> writeHeadersFunc, IHasWriteOptions writeOptionsHolder,
57             Func<string> testingOnlyPeerGetter, Func<AuthContext> testingOnlyAuthContextGetter, Func<ContextPropagationToken> testingOnlyContextPropagationTokenFactory)
58         {
59             this.callHandle = callHandle;
60             this.method = method;
61             this.host = host;
62             this.deadline = deadline;
63             this.requestHeaders = requestHeaders;
64             this.cancellationToken = cancellationToken;
65             this.writeHeadersFunc = writeHeadersFunc;
66             this.writeOptionsHolder = writeOptionsHolder;
67             this.authContext = new Lazy<AuthContext>(GetAuthContextEager);
68             this.testingOnlyPeerGetter = testingOnlyPeerGetter;
69             this.testingOnlyAuthContextGetter = testingOnlyAuthContextGetter;
70             this.testingOnlyContextPropagationTokenFactory = testingOnlyContextPropagationTokenFactory;
71         }
72 
73         /// <summary>
74         /// Asynchronously sends response headers for the current call to the client. This method may only be invoked once for each call and needs to be invoked
75         /// before any response messages are written. Writing the first response message implicitly sends empty response headers if <c>WriteResponseHeadersAsync</c> haven't
76         /// been called yet.
77         /// </summary>
78         /// <param name="responseHeaders">The response headers to send.</param>
79         /// <returns>The task that finished once response headers have been written.</returns>
WriteResponseHeadersAsync(Metadata responseHeaders)80         public Task WriteResponseHeadersAsync(Metadata responseHeaders)
81         {
82             return writeHeadersFunc(responseHeaders);
83         }
84 
85         /// <summary>
86         /// Creates a propagation token to be used to propagate call context to a child call.
87         /// </summary>
CreatePropagationToken(ContextPropagationOptions options = null)88         public ContextPropagationToken CreatePropagationToken(ContextPropagationOptions options = null)
89         {
90             if (testingOnlyContextPropagationTokenFactory != null)
91             {
92                 return testingOnlyContextPropagationTokenFactory();
93             }
94             return new ContextPropagationToken(callHandle, deadline, cancellationToken, options);
95         }
96 
97         /// <summary>Name of method called in this RPC.</summary>
98         public string Method
99         {
100             get
101             {
102                 return this.method;
103             }
104         }
105 
106         /// <summary>Name of host called in this RPC.</summary>
107         public string Host
108         {
109             get
110             {
111                 return this.host;
112             }
113         }
114 
115         /// <summary>Address of the remote endpoint in URI format.</summary>
116         public string Peer
117         {
118             get
119             {
120                 if (testingOnlyPeerGetter != null)
121                 {
122                     return testingOnlyPeerGetter();
123                 }
124                 // Getting the peer lazily is fine as the native call is guaranteed
125                 // not to be disposed before user-supplied server side handler returns.
126                 // Most users won't need to read this field anyway.
127                 return this.callHandle.GetPeer();
128             }
129         }
130 
131         /// <summary>Deadline for this RPC.</summary>
132         public DateTime Deadline
133         {
134             get
135             {
136                 return this.deadline;
137             }
138         }
139 
140         /// <summary>Initial metadata sent by client.</summary>
141         public Metadata RequestHeaders
142         {
143             get
144             {
145                 return this.requestHeaders;
146             }
147         }
148 
149         /// <summary>Cancellation token signals when call is cancelled.</summary>
150         public CancellationToken CancellationToken
151         {
152             get
153             {
154                 return this.cancellationToken;
155             }
156         }
157 
158         /// <summary>Trailers to send back to client after RPC finishes.</summary>
159         public Metadata ResponseTrailers
160         {
161             get
162             {
163                 return this.responseTrailers;
164             }
165         }
166 
167         /// <summary> Status to send back to client after RPC finishes.</summary>
168         public Status Status
169         {
170             get
171             {
172                 return this.status;
173             }
174 
175             set
176             {
177                 status = value;
178             }
179         }
180 
181         /// <summary>
182         /// Allows setting write options for the following write.
183         /// For streaming response calls, this property is also exposed as on IServerStreamWriter for convenience.
184         /// Both properties are backed by the same underlying value.
185         /// </summary>
186         public WriteOptions WriteOptions
187         {
188             get
189             {
190                 return writeOptionsHolder.WriteOptions;
191             }
192 
193             set
194             {
195                 writeOptionsHolder.WriteOptions = value;
196             }
197         }
198 
199         /// <summary>
200         /// Gets the <c>AuthContext</c> associated with this call.
201         /// Note: Access to AuthContext is an experimental API that can change without any prior notice.
202         /// </summary>
203         public AuthContext AuthContext
204         {
205             get
206             {
207                 if (testingOnlyAuthContextGetter != null)
208                 {
209                     return testingOnlyAuthContextGetter();
210                 }
211                 return authContext.Value;
212             }
213         }
214 
GetAuthContextEager()215         private AuthContext GetAuthContextEager()
216         {
217             using (var authContextNative = callHandle.GetAuthContext())
218             {
219                 return authContextNative.ToAuthContext();
220             }
221         }
222     }
223 
224     /// <summary>
225     /// Allows sharing write options between ServerCallContext and other objects.
226     /// </summary>
227     internal interface IHasWriteOptions
228     {
229         /// <summary>
230         /// Gets or sets the write options.
231         /// </summary>
232         WriteOptions WriteOptions { get; set; }
233     }
234 }
235