using System.Net; using NLog; using SimpleRpc.Transports; using SimpleRpc.Transports.Http.Server; using SimpleRpc.Serialization.Hyperion; using ChatRoomContract; using Microsoft.Extensions.Logging; using System.Reflection; using System.Text.Json.Serialization; using Microsoft.AspNetCore.Server.Kestrel.Core; namespace ChatRoom; public class Server { /// /// Logger for this class. /// Logger log = LogManager.GetCurrentClassLogger(); /// /// Configure loggin subsystem. /// private void ConfigureLogging() { var config = new NLog.Config.LoggingConfiguration(); var console = new NLog.Targets.ConsoleTarget("console") { Layout = @"${date:format=HH\:mm\:ss}|${level}| ${message} ${exception}" }; config.AddTarget(console); config.AddRuleForAllLevels(console); LogManager.Configuration = config; } /// /// Program entry point. /// /// Command line arguments. public static void Main(string[] args) { var self = new Server(); self.Run(args); } /// /// Program body. /// /// Command line arguments. private void Run(string[] args) { //configure logging ConfigureLogging(); //indicate server is about to start log.Info("Server is about to start"); //start the server StartServer(args); } /// /// Starts integrated server. /// /// Command line arguments. private void StartServer(string[] args) { Console.Title = "Chat Room"; var logic = new ChatRoomLogic(); // Simple RPC WebApplication simpleRPCWebApplication; { ///create web app builder var builder = WebApplication.CreateBuilder(args); //configure integrated server builder.WebHost.ConfigureKestrel(opts => { opts.Listen(IPAddress.Loopback, 5001); }); //add SimpleRPC services builder.Services .AddSimpleRpcServer(new HttpServerTransportOptions { Path = "/simplerpc" }) .AddSimpleRpcHyperionSerializer(); //add our custom services builder.Services.AddSingleton(new ChatRoomSimpleRPCService(logic)); //build the server var app = builder.Build(); //add SimpleRPC middleware app.UseSimpleRpcServer(); simpleRPCWebApplication = app; } // Rest, GRPC WebApplication restGrpcWebApplication; { ///create web app builder var builder = WebApplication.CreateBuilder(args); //configure integrated server builder.WebHost.ConfigureKestrel(opts => { opts.Listen(IPAddress.Loopback, 5000, opts => { opts.Protocols = HttpProtocols.Http2; }); }); //add and configure swagger documentation generator (http://127.0.0.1:5000/swagger/) builder.Services.AddSwaggerGen(opts => { //include code comments in swagger documentation var xmlFilename = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml"; opts.IncludeXmlComments(Path.Combine(AppContext.BaseDirectory, xmlFilename)); }); //turn on support for web api controllers builder.Services .AddControllers() .AddJsonOptions(opts => { //this makes enumeration values to be strings instead of integers in opeanapi doc opts.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter()); }); //add CORS policies builder.Services.AddCors(cr => { //allow everything from everywhere cr.AddPolicy("allowAll", cp => { cp.AllowAnyOrigin(); cp.AllowAnyMethod(); cp.AllowAnyHeader(); }); }); //publish the background logic as (an internal) service through dependency injection, //otherwise it will not start until the first client calls into controller builder.Services.AddSingleton(logic); //add support for GRPC services builder.Services.AddGrpc(); builder.Services.AddSingleton(new ChatRoomGrpcService(logic)); //build the server var app = builder.Build(); //turn CORS policy on app.UseCors("allowAll"); //turn on support for swagger doc web page app.UseSwagger(); app.UseSwaggerUI(); app.MapGrpcService(); ////turn on request routing app.UseRouting(); ////configure routes app.MapControllerRoute( name: "default", pattern: "{controller}/{action=Index}/{id?}" ); restGrpcWebApplication = app; } // RabbitMQ { var service = new ChatRoomRabbitMQService( logic, RabbitMQConfig.CreateConnection(), RabbitMQConfig.ExchangeName, RabbitMQConfig.ServerQueueName ); } var restGrpcTask = restGrpcWebApplication.RunAsync(); var simpleRPCTask = simpleRPCWebApplication.RunAsync(); restGrpcTask.Wait(); simpleRPCTask.Wait(); } }