blob: a3b12fca95bd58fd869da186314ccb0ea7b78966 [file] [log] [blame]
Jens Geyeraa0c8b32019-01-28 23:27:45 +01001// Licensed to the Apache Software Foundation(ASF) under one
2// or more contributor license agreements.See the NOTICE file
3// distributed with this work for additional information
4// regarding copyright ownership.The ASF licenses this file
5// to you under the Apache License, Version 2.0 (the
6// "License"); you may not use this file except in compliance
7// with the License. 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,
12// software distributed under the License is distributed on an
13// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14// KIND, either express or implied. See the License for the
15// specific language governing permissions and limitations
16// under the License.
17
Jens Geyere26b4a82024-11-12 23:53:04 +010018using Microsoft.AspNetCore.Builder;
19using Microsoft.AspNetCore.Hosting;
20using Microsoft.Extensions.Configuration;
21using Microsoft.Extensions.DependencyInjection;
22using Microsoft.Extensions.Logging;
23using shared;
Jens Geyeraa0c8b32019-01-28 23:27:45 +010024using System;
25using System.Collections.Generic;
26using System.IO;
27using System.Linq;
28using System.Net.Security;
29using System.Security.Cryptography.X509Certificates;
30using System.Threading;
31using System.Threading.Tasks;
Jens Geyeraa0c8b32019-01-28 23:27:45 +010032using Thrift;
Jens Geyere26b4a82024-11-12 23:53:04 +010033using Thrift.Processor;
Jens Geyeraa0c8b32019-01-28 23:27:45 +010034using Thrift.Protocol;
35using Thrift.Server;
36using Thrift.Transport;
37using Thrift.Transport.Server;
38using tutorial;
Jens Geyeraa0c8b32019-01-28 23:27:45 +010039
Jens Geyer0d128322021-02-25 09:42:52 +010040#pragma warning disable IDE0057 // substr
41
Jens Geyeraa0c8b32019-01-28 23:27:45 +010042namespace Server
43{
Jens Geyer4c7b9fd2021-12-04 22:48:37 +010044 public static class LoggingHelper
45 {
46 public static ILoggerFactory LogFactory { get; } = LoggerFactory.Create(builder => {
47 ConfigureLogging(builder);
48 });
49
50 public static void ConfigureLogging(ILoggingBuilder logging)
51 {
52 logging.SetMinimumLevel(LogLevel.Trace);
53 logging.AddConsole();
54 logging.AddDebug();
55 }
56
57 public static ILogger<T> CreateLogger<T>() => LogFactory.CreateLogger<T>();
58 }
59
Jens Geyeraa0c8b32019-01-28 23:27:45 +010060 public class Program
61 {
Jens Geyer4c7b9fd2021-12-04 22:48:37 +010062 private static readonly ILogger Logger = LoggingHelper.CreateLogger<Program>();
Jens Geyere26b4a82024-11-12 23:53:04 +010063 private static readonly TConfiguration Configuration = new();
Jens Geyeraa0c8b32019-01-28 23:27:45 +010064
Jens Geyere26b4a82024-11-12 23:53:04 +010065 public static async Task Main(string[] args)
Jens Geyeraa0c8b32019-01-28 23:27:45 +010066 {
Jens Geyere26b4a82024-11-12 23:53:04 +010067 args ??= [];
Jens Geyeraa0c8b32019-01-28 23:27:45 +010068
Jens Geyere26b4a82024-11-12 23:53:04 +010069 // -help is rather unusual but we leave it for compatibility
70 if (args.Any(x => x.Equals("-help") || x.Equals("--help") || x.Equals("-h") || x.Equals("-?")))
Jens Geyeraa0c8b32019-01-28 23:27:45 +010071 {
Jens Geyer4c7b9fd2021-12-04 22:48:37 +010072 DisplayHelp();
73 return;
Jens Geyeraa0c8b32019-01-28 23:27:45 +010074 }
Jens Geyer4c7b9fd2021-12-04 22:48:37 +010075
Jens Geyere26b4a82024-11-12 23:53:04 +010076 using var source = new CancellationTokenSource();
77 await RunAsync(args, source.Token);
Jens Geyer4c7b9fd2021-12-04 22:48:37 +010078
Jens Geyere26b4a82024-11-12 23:53:04 +010079 Logger.LogInformation("Press any key to stop...");
80 Console.ReadLine();
81 source.Cancel();
Jens Geyer4c7b9fd2021-12-04 22:48:37 +010082
83 Logger.LogInformation("Server stopped");
Jens Geyeraa0c8b32019-01-28 23:27:45 +010084 }
85
Jens Geyerb11f63c2019-03-14 21:12:38 +010086
Jens Geyeraa0c8b32019-01-28 23:27:45 +010087 private static void DisplayHelp()
88 {
89 Logger.LogInformation(@"
90Usage:
Kengo Sekibee4f2f2019-12-29 17:04:50 +090091 Server -help
Jens Geyeraa0c8b32019-01-28 23:27:45 +010092 will diplay help information
93
Jens Geyer0d128322021-02-25 09:42:52 +010094 Server -tr:<transport> -bf:<buffering> -pr:<protocol> [-multiplex]
Kyle Smith7b94dd42019-03-23 17:26:56 +010095 will run server with specified arguments (tcp transport, no buffering, and binary protocol by default)
Jens Geyeraa0c8b32019-01-28 23:27:45 +010096
97Options:
98 -tr (transport):
Jens Geyer0d128322021-02-25 09:42:52 +010099 tcp - (default) tcp transport (localhost:9090)
100 tcptls - tcp transport with tls (localhost:9090)
101 namedpipe - namedpipe transport (pipe "".test"")
102 http - http transport (localhost:9090)
Kyle Smith7b94dd42019-03-23 17:26:56 +0100103
104 -bf (buffering):
Jens Geyer0d128322021-02-25 09:42:52 +0100105 none - (default) no buffering
106 buffered - buffered transport
107 framed - framed transport
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100108
109 -pr (protocol):
Jens Geyer0d128322021-02-25 09:42:52 +0100110 binary - (default) binary protocol
111 compact - compact protocol
112 json - json protocol
113
114 -multiplex - adds multiplexed protocol
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100115
116Sample:
Kengo Sekibee4f2f2019-12-29 17:04:50 +0900117 Server -tr:tcp
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100118");
119 }
120
121 private static async Task RunAsync(string[] args, CancellationToken cancellationToken)
122 {
123 var selectedTransport = GetTransport(args);
Kyle Smith7b94dd42019-03-23 17:26:56 +0100124 var selectedBuffering = GetBuffering(args);
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100125 var selectedProtocol = GetProtocol(args);
Jens Geyer0d128322021-02-25 09:42:52 +0100126 var multiplex = GetMultiplex(args);
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100127
128 if (selectedTransport == Transport.Http)
129 {
Jens Geyer0d128322021-02-25 09:42:52 +0100130 if (multiplex)
Jens Geyer3cac3202022-01-31 18:04:35 +0100131 throw new Exception("This tutorial sample code does not yet allow multiplex over http (although Thrift itself of course does)");
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100132 new HttpServerSample().Run(cancellationToken);
133 }
134 else
135 {
Jens Geyer0d128322021-02-25 09:42:52 +0100136 await RunSelectedConfigurationAsync(selectedTransport, selectedBuffering, selectedProtocol, multiplex, cancellationToken);
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100137 }
138 }
139
Jens Geyer0d128322021-02-25 09:42:52 +0100140
141 private static bool GetMultiplex(string[] args)
142 {
143 var mplex = args.FirstOrDefault(x => x.StartsWith("-multiplex"));
144 return !string.IsNullOrEmpty(mplex);
145 }
146
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100147 private static Protocol GetProtocol(string[] args)
148 {
Jens Geyere26b4a82024-11-12 23:53:04 +0100149 var protocol = args.FirstOrDefault(x => x.StartsWith("-pr"))?.Split(':').Skip(1).Take(1).FirstOrDefault();
Jens Geyer0d128322021-02-25 09:42:52 +0100150 if (string.IsNullOrEmpty(protocol))
151 return Protocol.Binary;
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100152
Jens Geyer0d128322021-02-25 09:42:52 +0100153 protocol = protocol.Substring(0, 1).ToUpperInvariant() + protocol.Substring(1).ToLowerInvariant();
154 if (Enum.TryParse(protocol, true, out Protocol selectedProtocol))
155 return selectedProtocol;
156 else
157 return Protocol.Binary;
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100158 }
159
Kyle Smith7b94dd42019-03-23 17:26:56 +0100160 private static Buffering GetBuffering(string[] args)
161 {
Jens Geyere26b4a82024-11-12 23:53:04 +0100162 var buffering = args.FirstOrDefault(x => x.StartsWith("-bf"))?.Split(':').Skip(1).Take(1).FirstOrDefault();
Jens Geyer0d128322021-02-25 09:42:52 +0100163 if (string.IsNullOrEmpty(buffering))
164 return Buffering.None;
Kyle Smith7b94dd42019-03-23 17:26:56 +0100165
Jens Geyer0d128322021-02-25 09:42:52 +0100166 buffering = buffering.Substring(0, 1).ToUpperInvariant() + buffering.Substring(1).ToLowerInvariant();
167 if( Enum.TryParse<Buffering>(buffering, out var selectedBuffering))
168 return selectedBuffering;
169 else
170 return Buffering.None;
Kyle Smith7b94dd42019-03-23 17:26:56 +0100171 }
172
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100173 private static Transport GetTransport(string[] args)
174 {
Jens Geyere26b4a82024-11-12 23:53:04 +0100175 var transport = args.FirstOrDefault(x => x.StartsWith("-tr"))?.Split(':').Skip(1).Take(1).FirstOrDefault();
Jens Geyer0d128322021-02-25 09:42:52 +0100176 if (string.IsNullOrEmpty(transport))
177 return Transport.Tcp;
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100178
Jens Geyer0d128322021-02-25 09:42:52 +0100179 transport = transport.Substring(0, 1).ToUpperInvariant() + transport.Substring(1).ToLowerInvariant();
180 if( Enum.TryParse(transport, true, out Transport selectedTransport))
181 return selectedTransport;
182 else
183 return Transport.Tcp;
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100184 }
185
Jens Geyer0d128322021-02-25 09:42:52 +0100186 private static async Task RunSelectedConfigurationAsync(Transport transport, Buffering buffering, Protocol protocol, bool multiplex, CancellationToken cancellationToken)
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100187 {
Jens Geyer2b2ea622021-04-09 22:55:11 +0200188 TServerTransport serverTransport = transport switch
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100189 {
Jens Geyer2b2ea622021-04-09 22:55:11 +0200190 Transport.Tcp => new TServerSocketTransport(9090, Configuration),
Jens Geyer51fc54f2023-02-14 23:51:16 +0100191 Transport.NamedPipe => new TNamedPipeServerTransport(".test", Configuration, NamedPipeServerFlags.None, 64),
Jens Geyer2b2ea622021-04-09 22:55:11 +0200192 Transport.TcpTls => new TTlsServerSocketTransport(9090, Configuration, GetCertificate(), ClientCertValidator, LocalCertificateSelectionCallback),
193 _ => throw new ArgumentException("unsupported value $transport", nameof(transport)),
194 };
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100195
Jens Geyere26b4a82024-11-12 23:53:04 +0100196 TTransportFactory? transportFactory = buffering switch
Kyle Smith7b94dd42019-03-23 17:26:56 +0100197 {
Jens Geyer2b2ea622021-04-09 22:55:11 +0200198 Buffering.Buffered => new TBufferedTransport.Factory(),
199 Buffering.Framed => new TFramedTransport.Factory(),
200 // layered transport(s) are optional
201 Buffering.None => null,
202 _ => throw new ArgumentException("unsupported value $buffering", nameof(buffering)),
203 };
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100204
Jens Geyer2b2ea622021-04-09 22:55:11 +0200205 TProtocolFactory protocolFactory = protocol switch
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100206 {
Jens Geyer2b2ea622021-04-09 22:55:11 +0200207 Protocol.Binary => new TBinaryProtocol.Factory(),
208 Protocol.Compact => new TCompactProtocol.Factory(),
209 Protocol.Json => new TJsonProtocol.Factory(),
210 _ => throw new ArgumentException("unsupported value $protocol", nameof(protocol)),
211 };
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100212
Jens Geyer0d128322021-02-25 09:42:52 +0100213 var handler = new CalculatorAsyncHandler();
214 ITAsyncProcessor processor = new Calculator.AsyncProcessor(handler);
215
216 if (multiplex)
217 {
218 var multiplexedProcessor = new TMultiplexedProcessor();
219 multiplexedProcessor.RegisterProcessor(nameof(Calculator), processor);
220
221 processor = multiplexedProcessor;
222 }
223
Kyle Smith7b94dd42019-03-23 17:26:56 +0100224
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100225 try
226 {
227 Logger.LogInformation(
Jens Geyer4c7b9fd2021-12-04 22:48:37 +0100228 "TSimpleAsyncServer with \n{transport} transport\n{buffering} buffering\nmultiplex = {multiplex}\n{protocol} protocol",
229 transport,
230 buffering,
231 multiplex ? "yes" : "no",
232 protocol
233 );
Kyle Smith7b94dd42019-03-23 17:26:56 +0100234
235 var server = new TSimpleAsyncServer(
236 itProcessorFactory: new TSingletonProcessorFactory(processor),
237 serverTransport: serverTransport,
Jens Geyer0d128322021-02-25 09:42:52 +0100238 inputTransportFactory: transportFactory,
239 outputTransportFactory: transportFactory,
240 inputProtocolFactory: protocolFactory,
241 outputProtocolFactory: protocolFactory,
Jens Geyer4c7b9fd2021-12-04 22:48:37 +0100242 logger: LoggingHelper.CreateLogger<TSimpleAsyncServer >());
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100243
244 Logger.LogInformation("Starting the server...");
Kyle Smith7b94dd42019-03-23 17:26:56 +0100245
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100246 await server.ServeAsync(cancellationToken);
247 }
248 catch (Exception x)
249 {
Jens Geyer4c7b9fd2021-12-04 22:48:37 +0100250 Logger.LogInformation("{x}",x);
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100251 }
252 }
253
254 private static X509Certificate2 GetCertificate()
255 {
256 // due to files location in net core better to take certs from top folder
257 var certFile = GetCertPath(Directory.GetParent(Directory.GetCurrentDirectory()));
Jens Geyere26b4a82024-11-12 23:53:04 +0100258 //return new X509Certificate2(certFile, "ThriftTest");
259 return X509CertificateLoader.LoadPkcs12FromFile(certFile, "ThriftTest");
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100260 }
261
Jens Geyere26b4a82024-11-12 23:53:04 +0100262 private static string GetCertPath(DirectoryInfo? di, int maxCount = 6)
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100263 {
264 var topDir = di;
Jens Geyere26b4a82024-11-12 23:53:04 +0100265 var certFile = topDir?.EnumerateFiles("ThriftTest.pfx", SearchOption.AllDirectories).FirstOrDefault();
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100266 if (certFile == null)
267 {
268 if (maxCount == 0)
269 throw new FileNotFoundException("Cannot find file in directories");
Jens Geyere26b4a82024-11-12 23:53:04 +0100270 return GetCertPath(di?.Parent, --maxCount);
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100271 }
272
273 return certFile.FullName;
274 }
275
Jens Geyere26b4a82024-11-12 23:53:04 +0100276 private static X509Certificate2 LocalCertificateSelectionCallback(object sender,
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100277 string targetHost, X509CertificateCollection localCertificates,
Jens Geyere26b4a82024-11-12 23:53:04 +0100278 X509Certificate? remoteCertificate, string[] acceptableIssuers)
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100279 {
280 return GetCertificate();
281 }
282
Jens Geyere26b4a82024-11-12 23:53:04 +0100283 private static bool ClientCertValidator(object sender, X509Certificate? certificate, X509Chain? chain, SslPolicyErrors sslPolicyErrors)
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100284 {
285 return true;
286 }
287
288 private enum Transport
289 {
290 Tcp,
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100291 NamedPipe,
292 Http,
293 TcpTls,
Kyle Smith7b94dd42019-03-23 17:26:56 +0100294 }
295
296 private enum Buffering
297 {
298 None,
299 Buffered,
300 Framed,
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100301 }
302
303 private enum Protocol
304 {
305 Binary,
306 Compact,
307 Json,
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100308 }
309
310 public class HttpServerSample
311 {
312 public void Run(CancellationToken cancellationToken)
313 {
314 var config = new ConfigurationBuilder()
315 .AddEnvironmentVariables(prefix: "ASPNETCORE_")
316 .Build();
317
318 var host = new WebHostBuilder()
319 .UseConfiguration(config)
320 .UseKestrel()
321 .UseUrls("http://localhost:9090")
322 .UseContentRoot(Directory.GetCurrentDirectory())
323 .UseStartup<Startup>()
Jens Geyer4c7b9fd2021-12-04 22:48:37 +0100324 .ConfigureLogging((ctx,logging) => LoggingHelper.ConfigureLogging(logging))
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100325 .Build();
326
Jens Geyerb11f63c2019-03-14 21:12:38 +0100327 Logger.LogTrace("test");
328 Logger.LogCritical("test");
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100329 host.RunAsync(cancellationToken).GetAwaiter().GetResult();
330 }
331
332 public class Startup
333 {
Jens Geyerec439542019-11-01 19:19:44 +0100334 public Startup(IWebHostEnvironment env)
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100335 {
336 var builder = new ConfigurationBuilder()
337 .SetBasePath(env.ContentRootPath)
338 .AddEnvironmentVariables();
339
340 Configuration = builder.Build();
341 }
342
343 public IConfigurationRoot Configuration { get; }
344
345 // This method gets called by the runtime. Use this method to add services to the container.
346 public void ConfigureServices(IServiceCollection services)
347 {
Jens Geyer0d128322021-02-25 09:42:52 +0100348 // NOTE: this is not really the recommended way to do it
349 // because the HTTP server cannot be configured properly to e.g. accept framed or multiplex
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100350 services.AddTransient<Calculator.IAsync, CalculatorAsyncHandler>();
351 services.AddTransient<ITAsyncProcessor, Calculator.AsyncProcessor>();
352 services.AddTransient<THttpServerTransport, THttpServerTransport>();
353 }
354
355 // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
Jens Geyerec439542019-11-01 19:19:44 +0100356 public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILoggerFactory loggerFactory)
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100357 {
Jens Geyer0d128322021-02-25 09:42:52 +0100358 _ = env;
359 _ = loggerFactory;
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100360 app.UseMiddleware<THttpServerTransport>();
361 }
362 }
363 }
364
365 public class CalculatorAsyncHandler : Calculator.IAsync
366 {
Jens Geyere26b4a82024-11-12 23:53:04 +0100367 private readonly Dictionary<int, SharedStruct> _log = [];
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100368
369 public CalculatorAsyncHandler()
370 {
371 }
372
Jens Geyer2b2ea622021-04-09 22:55:11 +0200373 public async Task<SharedStruct> getStruct(int key,
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100374 CancellationToken cancellationToken)
375 {
Jens Geyer4c7b9fd2021-12-04 22:48:37 +0100376 Logger.LogInformation("GetStruct({key})", key);
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100377 return await Task.FromResult(_log[key]);
378 }
379
Jens Geyer2b2ea622021-04-09 22:55:11 +0200380 public async Task ping(CancellationToken cancellationToken)
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100381 {
Jens Geyer2b2ea622021-04-09 22:55:11 +0200382 Logger.LogInformation("Ping()");
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100383 await Task.CompletedTask;
384 }
385
Jens Geyer2b2ea622021-04-09 22:55:11 +0200386 public async Task<int> add(int num1, int num2, CancellationToken cancellationToken)
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100387 {
Jens Geyer4c7b9fd2021-12-04 22:48:37 +0100388 Logger.LogInformation("Add({num1},{num2})", num1, num2);
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100389 return await Task.FromResult(num1 + num2);
390 }
391
Jens Geyere26b4a82024-11-12 23:53:04 +0100392 public async Task<int> calculate(int logid, Work? w, CancellationToken cancellationToken)
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100393 {
Jens Geyere26b4a82024-11-12 23:53:04 +0100394 Logger.LogInformation("Calculate({logid}, [{w.Op},{w.Num1},{w.Num2}])", logid, w?.Op, w?.Num1, w?.Num2);
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100395
Jens Geyer0d128322021-02-25 09:42:52 +0100396 int val;
Jens Geyere26b4a82024-11-12 23:53:04 +0100397 switch (w?.Op)
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100398 {
399 case Operation.ADD:
400 val = w.Num1 + w.Num2;
401 break;
402
403 case Operation.SUBTRACT:
404 val = w.Num1 - w.Num2;
405 break;
406
407 case Operation.MULTIPLY:
408 val = w.Num1 * w.Num2;
409 break;
410
411 case Operation.DIVIDE:
412 if (w.Num2 == 0)
413 {
414 var io = new InvalidOperation
415 {
416 WhatOp = (int) w.Op,
417 Why = "Cannot divide by 0"
418 };
419
420 throw io;
421 }
422 val = w.Num1 / w.Num2;
423 break;
424
425 default:
426 {
427 var io = new InvalidOperation
428 {
Jens Geyere26b4a82024-11-12 23:53:04 +0100429 WhatOp = ((int?)w?.Op) ?? -1,
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100430 Why = "Unknown operation"
431 };
432
433 throw io;
434 }
435 }
436
437 var entry = new SharedStruct
438 {
439 Key = logid,
440 Value = val.ToString()
441 };
442
443 _log[logid] = entry;
444
445 return await Task.FromResult(val);
446 }
447
Jens Geyer2b2ea622021-04-09 22:55:11 +0200448 public async Task zip(CancellationToken cancellationToken)
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100449 {
Jens Geyer2b2ea622021-04-09 22:55:11 +0200450 Logger.LogInformation("Zip() with delay 100mc");
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100451 await Task.Delay(100, CancellationToken.None);
452 }
453 }
454
455 public class SharedServiceAsyncHandler : SharedService.IAsync
456 {
Jens Geyer2b2ea622021-04-09 22:55:11 +0200457 public async Task<SharedStruct> getStruct(int key, CancellationToken cancellationToken)
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100458 {
Jens Geyer4c7b9fd2021-12-04 22:48:37 +0100459 Logger.LogInformation("GetStruct({key})", key);
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100460 return await Task.FromResult(new SharedStruct()
461 {
462 Key = key,
Jens Geyer2b2ea622021-04-09 22:55:11 +0200463 Value = "GetStruct"
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100464 });
465 }
466 }
467 }
468}