#region Copyright notice and license // Copyright 2015-2016 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.Collections.Generic; using System.Threading; using System.Threading.Tasks; using Grpc.Core; using Grpc.Core.Utils; namespace Math { /// <summary> /// Implementation of MathService server /// </summary> public class MathServiceImpl : Math.MathBase { public override Task<DivReply> Div(DivArgs request, ServerCallContext context) { return Task.FromResult(DivInternal(request)); } public override async Task Fib(FibArgs request, IServerStreamWriter<Num> responseStream, ServerCallContext context) { var limit = request.Limit > 0 ? request.Limit : long.MaxValue; var fibEnumerator = FibInternal(limit).GetEnumerator(); // Keep streaming the sequence until the call is cancelled. // Use CancellationToken from ServerCallContext to detect the cancellation. while (!context.CancellationToken.IsCancellationRequested && fibEnumerator.MoveNext()) { await responseStream.WriteAsync(fibEnumerator.Current); await Task.Delay(100); } } public override async Task<Num> Sum(IAsyncStreamReader<Num> requestStream, ServerCallContext context) { long sum = 0; await requestStream.ForEachAsync(num => { sum += num.Num_; return TaskUtils.CompletedTask; }); return new Num { Num_ = sum }; } public override async Task DivMany(IAsyncStreamReader<DivArgs> requestStream, IServerStreamWriter<DivReply> responseStream, ServerCallContext context) { await requestStream.ForEachAsync(async divArgs => await responseStream.WriteAsync(DivInternal(divArgs))); } static DivReply DivInternal(DivArgs args) { if (args.Divisor == 0) { // One can finish the RPC with non-ok status by throwing RpcException instance. // Alternatively, resulting status can be set using ServerCallContext.Status throw new RpcException(new Status(StatusCode.InvalidArgument, "Division by zero")); } long quotient = args.Dividend / args.Divisor; long remainder = args.Dividend % args.Divisor; return new DivReply { Quotient = quotient, Remainder = remainder }; } static IEnumerable<Num> FibInternal(long n) { long a = 1; yield return new Num { Num_ = a }; long b = 1; for (long i = 0; i < n - 1; i++) { long temp = a; a = b; b = temp + b; yield return new Num { Num_ = a }; } } } }