// Copyright (c) Microsoft. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. namespace WebSockets.Server { using System; using System.IO; using System.Net; using System.Runtime; using System.Runtime.InteropServices; using System.Security.Cryptography.X509Certificates; using System.Threading.Tasks; using DotNetty.Codecs.Http; using DotNetty.Common; using DotNetty.Handlers.Tls; using DotNetty.Transport.Bootstrapping; using DotNetty.Transport.Channels; using DotNetty.Transport.Channels.Sockets; using DotNetty.Transport.Libuv; using Examples.Common; class Program { static Program() { ResourceLeakDetector.Level = ResourceLeakDetector.DetectionLevel.Disabled; } static async Task RunServerAsync() { Console.WriteLine( $"\n{RuntimeInformation.OSArchitecture} {RuntimeInformation.OSDescription}" + $"\n{RuntimeInformation.ProcessArchitecture} {RuntimeInformation.FrameworkDescription}" + $"\nProcessor Count : {Environment.ProcessorCount}\n"); bool useLibuv = ServerSettings.UseLibuv; Console.WriteLine("Transport type : " + (useLibuv ? "Libuv" : "Socket")); if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { GCSettings.LatencyMode = GCLatencyMode.SustainedLowLatency; } Console.WriteLine($"Server garbage collection : {(GCSettings.IsServerGC ? "Enabled" : "Disabled")}"); Console.WriteLine($"Current latency mode for garbage collection: {GCSettings.LatencyMode}"); Console.WriteLine("\n"); IEventLoopGroup bossGroup; IEventLoopGroup workGroup; if (useLibuv) { var dispatcher = new DispatcherEventLoopGroup(); bossGroup = dispatcher; workGroup = new WorkerEventLoopGroup(dispatcher); } else { bossGroup = new MultithreadEventLoopGroup(1); workGroup = new MultithreadEventLoopGroup(); } X509Certificate2 tlsCertificate = null; if (ServerSettings.IsSsl) { tlsCertificate = new X509Certificate2(Path.Combine(ExampleHelper.ProcessDirectory, "dotnetty.com.pfx"), "password"); } try { var bootstrap = new ServerBootstrap(); bootstrap.Group(bossGroup, workGroup); if (useLibuv) { bootstrap.Channel(); if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) || RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { bootstrap .Option(ChannelOption.SoReuseport, true) .ChildOption(ChannelOption.SoReuseaddr, true); } } else { bootstrap.Channel(); } bootstrap .Option(ChannelOption.SoBacklog, 8192) .ChildHandler(new ActionChannelInitializer(channel => { IChannelPipeline pipeline = channel.Pipeline; if (tlsCertificate != null) { pipeline.AddLast(TlsHandler.Server(tlsCertificate)); } pipeline.AddLast(new HttpServerCodec()); pipeline.AddLast(new HttpObjectAggregator(65536)); pipeline.AddLast(new WebSocketServerHandler()); })); int port = ServerSettings.Port; IChannel bootstrapChannel = await bootstrap.BindAsync(IPAddress.Loopback, port); Console.WriteLine("Open your web browser and navigate to " + $"{(ServerSettings.IsSsl ? "https" : "http")}" + $"://127.0.0.1:{port}/"); Console.WriteLine("Listening on " + $"{(ServerSettings.IsSsl ? "wss" : "ws")}" + $"://127.0.0.1:{port}/websocket"); Console.ReadLine(); await bootstrapChannel.CloseAsync(); } finally { workGroup.ShutdownGracefullyAsync().Wait(); bossGroup.ShutdownGracefullyAsync().Wait(); } } static void Main() => RunServerAsync().Wait(); } }