blob: 594e46b1598f0485386dfa17ff5ef1eef5c922a3 [file] [log] [blame]
Jan Tattermuscha7fff862015-02-13 11:08:08 -08001#region Copyright notice and license
2
Jan Tattermuschaf77b3d2015-02-13 11:22:21 -08003// Copyright 2015, Google Inc.
Jan Tattermuscha7fff862015-02-13 11:08:08 -08004// All rights reserved.
Craig Tiller190d3602015-02-18 09:23:38 -08005//
Jan Tattermuscha7fff862015-02-13 11:08:08 -08006// Redistribution and use in source and binary forms, with or without
7// modification, are permitted provided that the following conditions are
8// met:
Craig Tiller190d3602015-02-18 09:23:38 -08009//
Jan Tattermuscha7fff862015-02-13 11:08:08 -080010// * Redistributions of source code must retain the above copyright
11// notice, this list of conditions and the following disclaimer.
12// * Redistributions in binary form must reproduce the above
13// copyright notice, this list of conditions and the following disclaimer
14// in the documentation and/or other materials provided with the
15// distribution.
16// * Neither the name of Google Inc. nor the names of its
17// contributors may be used to endorse or promote products derived from
18// this software without specific prior written permission.
Craig Tiller190d3602015-02-18 09:23:38 -080019//
Jan Tattermuscha7fff862015-02-13 11:08:08 -080020// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31
32#endregion
33
Jan Tattermusch8ce5e8b2015-02-05 10:56:49 -080034using System;
Jan Tattermusch7ca61792015-05-18 14:28:22 -070035using System.Collections.Generic;
Jan Tattermuscha29d0f32015-03-04 17:54:56 -080036using System.Linq;
Jan Tattermuscha5272b62015-04-30 11:56:46 -070037using System.Threading.Tasks;
Jan Tattermusch30868622015-02-19 09:22:33 -080038using Grpc.Core.Internal;
Jan Tattermuscha29d0f32015-03-04 17:54:56 -080039using Grpc.Core.Utils;
Jan Tattermusch8ce5e8b2015-02-05 10:56:49 -080040
Jan Tattermusch286975f2015-03-12 14:04:36 -070041namespace Grpc.Core.Internal
Jan Tattermusch8ce5e8b2015-02-05 10:56:49 -080042{
43 internal interface IServerCallHandler
44 {
Jan Tattermusch04eb89c2015-06-12 13:03:05 -070045 Task HandleCall(string methodName, CallSafeHandle call, GrpcEnvironment environment);
Jan Tattermusch8ce5e8b2015-02-05 10:56:49 -080046 }
47
Jan Tattermuscha5272b62015-04-30 11:56:46 -070048 internal class UnaryServerCallHandler<TRequest, TResponse> : IServerCallHandler
Jan Tattermuschbdb1b482015-05-06 14:46:25 -070049 where TRequest : class
50 where TResponse : class
Jan Tattermusch8ce5e8b2015-02-05 10:56:49 -080051 {
52 readonly Method<TRequest, TResponse> method;
Jan Tattermuscha5272b62015-04-30 11:56:46 -070053 readonly UnaryServerMethod<TRequest, TResponse> handler;
Jan Tattermusch8ce5e8b2015-02-05 10:56:49 -080054
Jan Tattermuscha5272b62015-04-30 11:56:46 -070055 public UnaryServerCallHandler(Method<TRequest, TResponse> method, UnaryServerMethod<TRequest, TResponse> handler)
Jan Tattermusch8ce5e8b2015-02-05 10:56:49 -080056 {
57 this.method = method;
58 this.handler = handler;
59 }
60
Jan Tattermusch04eb89c2015-06-12 13:03:05 -070061 public async Task HandleCall(string methodName, CallSafeHandle call, GrpcEnvironment environment)
Jan Tattermusch8ce5e8b2015-02-05 10:56:49 -080062 {
Jan Tattermuscha29d0f32015-03-04 17:54:56 -080063 var asyncCall = new AsyncCallServer<TRequest, TResponse>(
Jan Tattermusch15111f52015-02-05 18:15:14 -080064 method.ResponseMarshaller.Serializer,
Jan Tattermusch04eb89c2015-06-12 13:03:05 -070065 method.RequestMarshaller.Deserializer,
66 environment);
Jan Tattermusch8ce5e8b2015-02-05 10:56:49 -080067
Jan Tattermuscha29d0f32015-03-04 17:54:56 -080068 asyncCall.Initialize(call);
Jan Tattermuscha5272b62015-04-30 11:56:46 -070069 var finishedTask = asyncCall.ServerSideCallAsync();
70 var requestStream = new ServerRequestStream<TRequest, TResponse>(asyncCall);
71 var responseStream = new ServerResponseStream<TRequest, TResponse>(asyncCall);
Craig Tiller190d3602015-02-18 09:23:38 -080072
Jan Tattermusche5c44602015-05-01 11:12:34 -070073 Status status = Status.DefaultSuccess;
74 try
75 {
Jan Tattermusch7ca61792015-05-18 14:28:22 -070076 Preconditions.CheckArgument(await requestStream.MoveNext());
77 var request = requestStream.Current;
Jan Tattermusche5c44602015-05-01 11:12:34 -070078 // TODO(jtattermusch): we need to read the full stream so that native callhandle gets deallocated.
Jan Tattermusch7ca61792015-05-18 14:28:22 -070079 Preconditions.CheckArgument(!await requestStream.MoveNext());
Jan Tattermusch8ab1f7e2015-05-06 15:56:30 -070080 var context = new ServerCallContext(); // TODO(jtattermusch): initialize the context
81 var result = await handler(context, request);
Jan Tattermusch43dc50b2015-05-18 15:27:19 -070082 await responseStream.WriteAsync(result);
Jan Tattermusche5c44602015-05-01 11:12:34 -070083 }
84 catch (Exception e)
85 {
86 Console.WriteLine("Exception occured in handler: " + e);
87 status = HandlerUtils.StatusFromException(e);
88 }
Jan Tattermusch8c2dd9d2015-05-04 09:20:43 -070089 try
90 {
Jan Tattermusch43dc50b2015-05-18 15:27:19 -070091 await responseStream.WriteStatusAsync(status);
Jan Tattermusch8c2dd9d2015-05-04 09:20:43 -070092 }
93 catch (OperationCanceledException)
94 {
95 // Call has been already cancelled.
96 }
Jan Tattermuscha5272b62015-04-30 11:56:46 -070097 await finishedTask;
Jan Tattermusch8ce5e8b2015-02-05 10:56:49 -080098 }
99 }
100
Jan Tattermuscha5272b62015-04-30 11:56:46 -0700101 internal class ServerStreamingServerCallHandler<TRequest, TResponse> : IServerCallHandler
Jan Tattermuschbdb1b482015-05-06 14:46:25 -0700102 where TRequest : class
103 where TResponse : class
Jan Tattermusch8ce5e8b2015-02-05 10:56:49 -0800104 {
105 readonly Method<TRequest, TResponse> method;
Jan Tattermuscha5272b62015-04-30 11:56:46 -0700106 readonly ServerStreamingServerMethod<TRequest, TResponse> handler;
Jan Tattermusch8ce5e8b2015-02-05 10:56:49 -0800107
Jan Tattermuscha5272b62015-04-30 11:56:46 -0700108 public ServerStreamingServerCallHandler(Method<TRequest, TResponse> method, ServerStreamingServerMethod<TRequest, TResponse> handler)
Jan Tattermusch8ce5e8b2015-02-05 10:56:49 -0800109 {
110 this.method = method;
111 this.handler = handler;
112 }
113
Jan Tattermusch04eb89c2015-06-12 13:03:05 -0700114 public async Task HandleCall(string methodName, CallSafeHandle call, GrpcEnvironment environment)
Jan Tattermusch8ce5e8b2015-02-05 10:56:49 -0800115 {
Jan Tattermuscha29d0f32015-03-04 17:54:56 -0800116 var asyncCall = new AsyncCallServer<TRequest, TResponse>(
Jan Tattermusch15111f52015-02-05 18:15:14 -0800117 method.ResponseMarshaller.Serializer,
Jan Tattermusch04eb89c2015-06-12 13:03:05 -0700118 method.RequestMarshaller.Deserializer,
119 environment);
Jan Tattermusch8ce5e8b2015-02-05 10:56:49 -0800120
Jan Tattermuscha29d0f32015-03-04 17:54:56 -0800121 asyncCall.Initialize(call);
Jan Tattermuscha5272b62015-04-30 11:56:46 -0700122 var finishedTask = asyncCall.ServerSideCallAsync();
123 var requestStream = new ServerRequestStream<TRequest, TResponse>(asyncCall);
124 var responseStream = new ServerResponseStream<TRequest, TResponse>(asyncCall);
Jan Tattermusch8ce5e8b2015-02-05 10:56:49 -0800125
Jan Tattermusche5c44602015-05-01 11:12:34 -0700126 Status status = Status.DefaultSuccess;
127 try
128 {
Jan Tattermusch7ca61792015-05-18 14:28:22 -0700129 Preconditions.CheckArgument(await requestStream.MoveNext());
130 var request = requestStream.Current;
Jan Tattermusche5c44602015-05-01 11:12:34 -0700131 // TODO(jtattermusch): we need to read the full stream so that native callhandle gets deallocated.
Jan Tattermusch7ca61792015-05-18 14:28:22 -0700132 Preconditions.CheckArgument(!await requestStream.MoveNext());
Jan Tattermuscha5272b62015-04-30 11:56:46 -0700133
Jan Tattermusch8ab1f7e2015-05-06 15:56:30 -0700134 var context = new ServerCallContext(); // TODO(jtattermusch): initialize the context
135 await handler(context, request, responseStream);
Jan Tattermusche5c44602015-05-01 11:12:34 -0700136 }
137 catch (Exception e)
138 {
139 Console.WriteLine("Exception occured in handler: " + e);
140 status = HandlerUtils.StatusFromException(e);
141 }
Jan Tattermusch8c2dd9d2015-05-04 09:20:43 -0700142
143 try
144 {
Jan Tattermusch43dc50b2015-05-18 15:27:19 -0700145 await responseStream.WriteStatusAsync(status);
Jan Tattermusch8c2dd9d2015-05-04 09:20:43 -0700146 }
147 catch (OperationCanceledException)
148 {
149 // Call has been already cancelled.
150 }
Jan Tattermuscha5272b62015-04-30 11:56:46 -0700151 await finishedTask;
152 }
153 }
154
155 internal class ClientStreamingServerCallHandler<TRequest, TResponse> : IServerCallHandler
Jan Tattermuschbdb1b482015-05-06 14:46:25 -0700156 where TRequest : class
157 where TResponse : class
Jan Tattermuscha5272b62015-04-30 11:56:46 -0700158 {
159 readonly Method<TRequest, TResponse> method;
160 readonly ClientStreamingServerMethod<TRequest, TResponse> handler;
161
162 public ClientStreamingServerCallHandler(Method<TRequest, TResponse> method, ClientStreamingServerMethod<TRequest, TResponse> handler)
163 {
164 this.method = method;
165 this.handler = handler;
166 }
167
Jan Tattermusch04eb89c2015-06-12 13:03:05 -0700168 public async Task HandleCall(string methodName, CallSafeHandle call, GrpcEnvironment environment)
Jan Tattermuscha5272b62015-04-30 11:56:46 -0700169 {
170 var asyncCall = new AsyncCallServer<TRequest, TResponse>(
171 method.ResponseMarshaller.Serializer,
Jan Tattermusch04eb89c2015-06-12 13:03:05 -0700172 method.RequestMarshaller.Deserializer,
173 environment);
Jan Tattermuscha5272b62015-04-30 11:56:46 -0700174
175 asyncCall.Initialize(call);
176 var finishedTask = asyncCall.ServerSideCallAsync();
177 var requestStream = new ServerRequestStream<TRequest, TResponse>(asyncCall);
178 var responseStream = new ServerResponseStream<TRequest, TResponse>(asyncCall);
Jan Tattermusch8ab1f7e2015-05-06 15:56:30 -0700179 var context = new ServerCallContext(); // TODO(jtattermusch): initialize the context
Jan Tattermuscha5272b62015-04-30 11:56:46 -0700180
Jan Tattermusche5c44602015-05-01 11:12:34 -0700181 Status status = Status.DefaultSuccess;
182 try
183 {
Jan Tattermusch8ab1f7e2015-05-06 15:56:30 -0700184 var result = await handler(context, requestStream);
Jan Tattermusch8c2dd9d2015-05-04 09:20:43 -0700185 try
186 {
Jan Tattermusch43dc50b2015-05-18 15:27:19 -0700187 await responseStream.WriteAsync(result);
Jan Tattermusch8c2dd9d2015-05-04 09:20:43 -0700188 }
189 catch (OperationCanceledException)
190 {
191 status = Status.DefaultCancelled;
192 }
193 }
Jan Tattermusche5c44602015-05-01 11:12:34 -0700194 catch (Exception e)
195 {
196 Console.WriteLine("Exception occured in handler: " + e);
197 status = HandlerUtils.StatusFromException(e);
198 }
Jan Tattermusch8c2dd9d2015-05-04 09:20:43 -0700199
200 try
201 {
Jan Tattermusch43dc50b2015-05-18 15:27:19 -0700202 await responseStream.WriteStatusAsync(status);
Jan Tattermusch8c2dd9d2015-05-04 09:20:43 -0700203 }
204 catch (OperationCanceledException)
205 {
206 // Call has been already cancelled.
207 }
Jan Tattermuscha5272b62015-04-30 11:56:46 -0700208 await finishedTask;
209 }
210 }
211
212 internal class DuplexStreamingServerCallHandler<TRequest, TResponse> : IServerCallHandler
Jan Tattermuschbdb1b482015-05-06 14:46:25 -0700213 where TRequest : class
214 where TResponse : class
Jan Tattermuscha5272b62015-04-30 11:56:46 -0700215 {
216 readonly Method<TRequest, TResponse> method;
217 readonly DuplexStreamingServerMethod<TRequest, TResponse> handler;
218
219 public DuplexStreamingServerCallHandler(Method<TRequest, TResponse> method, DuplexStreamingServerMethod<TRequest, TResponse> handler)
220 {
221 this.method = method;
222 this.handler = handler;
223 }
224
Jan Tattermusch04eb89c2015-06-12 13:03:05 -0700225 public async Task HandleCall(string methodName, CallSafeHandle call, GrpcEnvironment environment)
Jan Tattermuscha5272b62015-04-30 11:56:46 -0700226 {
227 var asyncCall = new AsyncCallServer<TRequest, TResponse>(
228 method.ResponseMarshaller.Serializer,
Jan Tattermusch04eb89c2015-06-12 13:03:05 -0700229 method.RequestMarshaller.Deserializer,
230 environment);
Jan Tattermuscha5272b62015-04-30 11:56:46 -0700231
232 asyncCall.Initialize(call);
233 var finishedTask = asyncCall.ServerSideCallAsync();
234 var requestStream = new ServerRequestStream<TRequest, TResponse>(asyncCall);
235 var responseStream = new ServerResponseStream<TRequest, TResponse>(asyncCall);
Jan Tattermusch8ab1f7e2015-05-06 15:56:30 -0700236 var context = new ServerCallContext(); // TODO(jtattermusch): initialize the context
Jan Tattermuscha5272b62015-04-30 11:56:46 -0700237
Jan Tattermusche5c44602015-05-01 11:12:34 -0700238 Status status = Status.DefaultSuccess;
239 try
240 {
Jan Tattermusch8ab1f7e2015-05-06 15:56:30 -0700241 await handler(context, requestStream, responseStream);
Jan Tattermusche5c44602015-05-01 11:12:34 -0700242 }
243 catch (Exception e)
244 {
245 Console.WriteLine("Exception occured in handler: " + e);
246 status = HandlerUtils.StatusFromException(e);
247 }
Jan Tattermusch8c2dd9d2015-05-04 09:20:43 -0700248 try
249 {
Jan Tattermusch43dc50b2015-05-18 15:27:19 -0700250 await responseStream.WriteStatusAsync(status);
Jan Tattermusch8c2dd9d2015-05-04 09:20:43 -0700251 }
252 catch (OperationCanceledException)
253 {
254 // Call has been already cancelled.
255 }
Jan Tattermuscha5272b62015-04-30 11:56:46 -0700256 await finishedTask;
Jan Tattermusch8ce5e8b2015-02-05 10:56:49 -0800257 }
258 }
259
260 internal class NoSuchMethodCallHandler : IServerCallHandler
261 {
Jan Tattermusch04eb89c2015-06-12 13:03:05 -0700262 public async Task HandleCall(string methodName, CallSafeHandle call, GrpcEnvironment environment)
Jan Tattermusch8ce5e8b2015-02-05 10:56:49 -0800263 {
264 // We don't care about the payload type here.
Jan Tattermuscha29d0f32015-03-04 17:54:56 -0800265 var asyncCall = new AsyncCallServer<byte[], byte[]>(
Jan Tattermusch04eb89c2015-06-12 13:03:05 -0700266 (payload) => payload, (payload) => payload, environment);
Jan Tattermusche5c44602015-05-01 11:12:34 -0700267
Jan Tattermuscha29d0f32015-03-04 17:54:56 -0800268 asyncCall.Initialize(call);
Jan Tattermuscha5272b62015-04-30 11:56:46 -0700269 var finishedTask = asyncCall.ServerSideCallAsync();
270 var requestStream = new ServerRequestStream<byte[], byte[]>(asyncCall);
271 var responseStream = new ServerResponseStream<byte[], byte[]>(asyncCall);
Jan Tattermusche5c44602015-05-01 11:12:34 -0700272
Jan Tattermusch43dc50b2015-05-18 15:27:19 -0700273 await responseStream.WriteStatusAsync(new Status(StatusCode.Unimplemented, "No such method."));
Jan Tattermuscha5272b62015-04-30 11:56:46 -0700274 await finishedTask;
Jan Tattermusch37afb9a2015-02-18 11:20:04 -0800275 }
Jan Tattermusch37afb9a2015-02-18 11:20:04 -0800276 }
Jan Tattermusche5c44602015-05-01 11:12:34 -0700277
278 internal static class HandlerUtils
279 {
280 public static Status StatusFromException(Exception e)
281 {
282 // TODO(jtattermusch): what is the right status code here?
283 return new Status(StatusCode.Unknown, "Exception was thrown by handler.");
284 }
285 }
Jan Tattermusch8ce5e8b2015-02-05 10:56:49 -0800286}