THRIFT-4839: Remove embedded buffering/framed options from TCP transports
Client: netstd
Patch: Kyle Smith + minor changes by Jens Geyer

This closes #1770
diff --git a/lib/netstd/Thrift/Server/TSimpleAsyncServer.cs b/lib/netstd/Thrift/Server/TSimpleAsyncServer.cs
index 813d3f3..bdaa348 100644
--- a/lib/netstd/Thrift/Server/TSimpleAsyncServer.cs
+++ b/lib/netstd/Thrift/Server/TSimpleAsyncServer.cs
@@ -33,24 +33,58 @@
         private readonly int _clientWaitingDelay;
         private volatile Task _serverTask;
 
-        public TSimpleAsyncServer(ITAsyncProcessor processor, TServerTransport serverTransport,
-            TProtocolFactory inputProtocolFactory, TProtocolFactory outputProtocolFactory,
-            ILoggerFactory loggerFactory, int clientWaitingDelay = 10)
-            : this(new TSingletonProcessorFactory(processor), serverTransport,
-                new TTransportFactory(), new TTransportFactory(),
-                inputProtocolFactory, outputProtocolFactory,
-                loggerFactory.CreateLogger(nameof(TSimpleAsyncServer)), clientWaitingDelay)
+        public TSimpleAsyncServer(ITProcessorFactory itProcessorFactory,
+            TServerTransport serverTransport,
+            TTransportFactory inputTransportFactory,
+            TTransportFactory outputTransportFactory,
+            TProtocolFactory inputProtocolFactory,
+            TProtocolFactory outputProtocolFactory,
+            ILogger logger,
+            int clientWaitingDelay = 10)
+            : base(itProcessorFactory,
+                  serverTransport,
+                  inputTransportFactory,
+                  outputTransportFactory,
+                  inputProtocolFactory,
+                  outputProtocolFactory,
+                  logger)
+        {
+            _clientWaitingDelay = clientWaitingDelay;
+        }
+
+        public TSimpleAsyncServer(ITProcessorFactory itProcessorFactory,
+            TServerTransport serverTransport,
+            TTransportFactory inputTransportFactory,
+            TTransportFactory outputTransportFactory,
+            TProtocolFactory inputProtocolFactory,
+            TProtocolFactory outputProtocolFactory,
+            ILoggerFactory loggerFactory,
+            int clientWaitingDelay = 10)
+            : this(itProcessorFactory,
+                  serverTransport,
+                  inputTransportFactory,
+                  outputTransportFactory,
+                  inputProtocolFactory,
+                  outputProtocolFactory,
+                  loggerFactory.CreateLogger<TSimpleAsyncServer>())
         {
         }
 
-        public TSimpleAsyncServer(ITProcessorFactory itProcessorFactory, TServerTransport serverTransport,
-            TTransportFactory inputTransportFactory, TTransportFactory outputTransportFactory,
-            TProtocolFactory inputProtocolFactory, TProtocolFactory outputProtocolFactory,
-            ILogger logger, int clientWaitingDelay = 10)
-            : base(itProcessorFactory, serverTransport, inputTransportFactory, outputTransportFactory,
-                inputProtocolFactory, outputProtocolFactory, logger)
+        public TSimpleAsyncServer(ITAsyncProcessor processor,
+            TServerTransport serverTransport,
+            TProtocolFactory inputProtocolFactory,
+            TProtocolFactory outputProtocolFactory,
+            ILoggerFactory loggerFactory,
+            int clientWaitingDelay = 10)
+            : this(new TSingletonProcessorFactory(processor),
+                  serverTransport,
+                  null, // defaults to TTransportFactory()
+                  null, // defaults to TTransportFactory()
+                  inputProtocolFactory,
+                  outputProtocolFactory,
+                  loggerFactory.CreateLogger(nameof(TSimpleAsyncServer)),
+                  clientWaitingDelay)
         {
-            _clientWaitingDelay = clientWaitingDelay;
         }
 
         public override async Task ServeAsync(CancellationToken cancellationToken)
diff --git a/lib/netstd/Thrift/Server/TThreadPoolAsyncServer.cs b/lib/netstd/Thrift/Server/TThreadPoolAsyncServer.cs
index 1c76b68..20e659d 100644
--- a/lib/netstd/Thrift/Server/TThreadPoolAsyncServer.cs
+++ b/lib/netstd/Thrift/Server/TThreadPoolAsyncServer.cs
@@ -68,7 +68,7 @@
 
         public TThreadPoolAsyncServer(ITAsyncProcessor processor, TServerTransport serverTransport, ILogger logger = null)
             : this(new TSingletonProcessorFactory(processor), serverTransport,
-             new TTransportFactory(), new TTransportFactory(),
+             null, null, // defaults to TTransportFactory()
              new TBinaryProtocol.Factory(), new TBinaryProtocol.Factory(),
              new Configuration(), logger)
         {
diff --git a/lib/netstd/Thrift/Thrift.csproj b/lib/netstd/Thrift/Thrift.csproj
index 86de1f8..d093803 100644
--- a/lib/netstd/Thrift/Thrift.csproj
+++ b/lib/netstd/Thrift/Thrift.csproj
@@ -39,7 +39,6 @@
   </PropertyGroup>
 
   <ItemGroup>
-    <PackageReference Include="Microsoft.AspNetCore" Version="2.2.0" />
     <PackageReference Include="Microsoft.AspNetCore.Http.Abstractions" Version="2.2.0" />
     <PackageReference Include="Microsoft.Extensions.Logging" Version="2.2.0" />
     <PackageReference Include="Microsoft.Extensions.Logging.Console" Version="2.2.0" />
diff --git a/lib/netstd/Thrift/Transport/Server/TNamedPipeServerTransport.cs b/lib/netstd/Thrift/Transport/Server/TNamedPipeServerTransport.cs
index cd5683b..8147d67 100644
--- a/lib/netstd/Thrift/Transport/Server/TNamedPipeServerTransport.cs
+++ b/lib/netstd/Thrift/Transport/Server/TNamedPipeServerTransport.cs
@@ -34,10 +34,8 @@
         ///     This is the address of the Pipe on the localhost.
         /// </summary>
         private readonly string _pipeAddress;
-
         private bool _asyncMode = true;
         private volatile bool _isPending = true;
-
         private NamedPipeServerStream _stream = null;
 
         public TNamedPipeServerTransport(string pipeAddress)
diff --git a/lib/netstd/Thrift/Transport/Server/TServerSocketTransport.cs b/lib/netstd/Thrift/Transport/Server/TServerSocketTransport.cs
index 4f46f99..0f90841 100644
--- a/lib/netstd/Thrift/Transport/Server/TServerSocketTransport.cs
+++ b/lib/netstd/Thrift/Transport/Server/TServerSocketTransport.cs
@@ -16,7 +16,6 @@
 // under the License.
 
 using System;
-using System.Diagnostics;
 using System.Net;
 using System.Net.Sockets;
 using System.Threading;
@@ -30,20 +29,17 @@
     public class TServerSocketTransport : TServerTransport
     {
         private readonly int _clientTimeout;
-        private readonly Buffering _buffering;
         private TcpListener _server;
 
-        public TServerSocketTransport(TcpListener listener, int clientTimeout = 0, Buffering buffering = Buffering.None)
+        public TServerSocketTransport(TcpListener listener, int clientTimeout = 0)
         {
             _server = listener;
             _clientTimeout = clientTimeout;
-            _buffering = buffering;
         }
 
-        public TServerSocketTransport(int port, int clientTimeout = 0, Buffering buffering = Buffering.None)
+        public TServerSocketTransport(int port, int clientTimeout = 0)
+            : this(null, clientTimeout)
         {
-            _clientTimeout = clientTimeout;
-            _buffering = buffering;
             try
             {
                 // Make server socket
@@ -102,21 +98,6 @@
                         Timeout = _clientTimeout
                     };
 
-                    switch (_buffering)
-                    {
-                        case Buffering.BufferedTransport:
-                            tSocketTransport = new TBufferedTransport(tSocketTransport);
-                            break;
-
-                        case Buffering.FramedTransport:
-                            tSocketTransport = new TFramedTransport(tSocketTransport);
-                            break;
-
-                        default:
-                            Debug.Assert(_buffering == Buffering.None);
-                            break;
-                    }
-
                     return tSocketTransport;
                 }
                 catch (Exception)
diff --git a/lib/netstd/Thrift/Transport/Server/TTlsServerSocketTransport.cs b/lib/netstd/Thrift/Transport/Server/TTlsServerSocketTransport.cs
index edfaced..5070919 100644
--- a/lib/netstd/Thrift/Transport/Server/TTlsServerSocketTransport.cs
+++ b/lib/netstd/Thrift/Transport/Server/TTlsServerSocketTransport.cs
@@ -16,7 +16,6 @@
 // under the License.
 
 using System;
-using System.Diagnostics;
 using System.Net;
 using System.Net.Security;
 using System.Net.Sockets;
@@ -36,13 +35,11 @@
         private readonly LocalCertificateSelectionCallback _localCertificateSelectionCallback;
         private readonly X509Certificate2 _serverCertificate;
         private readonly SslProtocols _sslProtocols;
-        private readonly Buffering _buffering;
         private TcpListener _server;
                
         public TTlsServerSocketTransport(
             TcpListener listener,
             X509Certificate2 certificate,
-            Buffering buffering = Buffering.None,
             RemoteCertificateValidationCallback clientCertValidator = null,
             LocalCertificateSelectionCallback localCertificateSelectionCallback = null,
             SslProtocols sslProtocols = SslProtocols.Tls12)
@@ -54,7 +51,6 @@
             }
 
             _serverCertificate = certificate;
-            _buffering = buffering;
             _clientCertValidator = clientCertValidator;
             _localCertificateSelectionCallback = localCertificateSelectionCallback;
             _sslProtocols = sslProtocols;
@@ -64,23 +60,11 @@
         public TTlsServerSocketTransport(
             int port,
             X509Certificate2 certificate,
-            Buffering buffering = Buffering.None,
             RemoteCertificateValidationCallback clientCertValidator = null,
             LocalCertificateSelectionCallback localCertificateSelectionCallback = null,
             SslProtocols sslProtocols = SslProtocols.Tls12)
+            : this(null, certificate, clientCertValidator, localCertificateSelectionCallback)
         {
-            if (!certificate.HasPrivateKey)
-            {
-                throw new TTransportException(TTransportException.ExceptionType.Unknown,
-                    "Your server-certificate needs to have a private key");
-            }
-
-            _serverCertificate = certificate;
-            _buffering = buffering;
-            _clientCertValidator = clientCertValidator;
-            _localCertificateSelectionCallback = localCertificateSelectionCallback;
-            _sslProtocols = sslProtocols;
-
             try
             {
                 // Create server socket
@@ -137,25 +121,8 @@
                     _localCertificateSelectionCallback, _sslProtocols);
 
                 await tTlsSocket.SetupTlsAsync();
-
-                TTransport trans = tTlsSocket;
-
-                switch(_buffering)
-                {
-                    case Buffering.BufferedTransport:
-                        trans = new TBufferedTransport(trans);
-                        break;
-
-                    case Buffering.FramedTransport:
-                        trans = new TFramedTransport(trans);
-                        break;
-
-                    default:
-                        Debug.Assert(_buffering == Buffering.None);
-                        break;
-                }
                 
-                return trans;
+                return tTlsSocket;
             }
             catch (Exception ex)
             {
diff --git a/lib/netstd/Thrift/Transport/TFramedTransport.cs b/lib/netstd/Thrift/Transport/TFramedTransport.cs
index 6d0802d..fe7793e 100644
--- a/lib/netstd/Thrift/Transport/TFramedTransport.cs
+++ b/lib/netstd/Thrift/Transport/TFramedTransport.cs
@@ -22,15 +22,6 @@
 
 namespace Thrift.Transport
 {
-    // it does not make much sense to use buffered when we already use framed
-    public enum Buffering
-    {
-        None,
-        BufferedTransport,
-        FramedTransport
-    }
-
-
     // ReSharper disable once InconsistentNaming
     public class TFramedTransport : TTransport
     {
diff --git a/test/netstd/Server/TestServer.cs b/test/netstd/Server/TestServer.cs
index 1aa8a77..82b36eb 100644
--- a/test/netstd/Server/TestServer.cs
+++ b/test/netstd/Server/TestServer.cs
@@ -50,9 +50,16 @@
         NamedPipe
     }
 
+    internal enum BufferChoice
+    {
+        None,
+        Buffered,
+        Framed
+    }
+
     internal class ServerParam
     {
-        internal Buffering buffering = Buffering.None;
+        internal BufferChoice buffering = BufferChoice.None;
         internal ProtocolChoice protocol = ProtocolChoice.Binary;
         internal TransportChoice transport = TransportChoice.Socket;
         internal int port = 9090;
@@ -75,11 +82,11 @@
                 }
                 else if (args[i] == "-b" || args[i] == "--buffered" || args[i] == "--transport=buffered")
                 {
-                    buffering = Buffering.BufferedTransport;
+                    buffering = BufferChoice.Buffered;
                 }
                 else if (args[i] == "-f" || args[i] == "--framed" || args[i] == "--transport=framed")
                 {
-                    buffering = Buffering.FramedTransport;
+                    buffering = BufferChoice.Framed;
                 }
                 else if (args[i] == "--binary" || args[i] == "--protocol=binary")
                 {
@@ -539,11 +546,8 @@
                 }
 
 
-                TTransportFactory transFactory = null;
-
-                // Transport
+                // Endpoint transport (mandatory)
                 TServerTransport trans;
-
                 switch (param.transport)
                 {
                     case TransportChoice.NamedPipe:
@@ -559,34 +563,34 @@
                             throw new InvalidOperationException("Certificate doesn't contain private key");
                         }
 
-                        transFactory = new TTransportFactory(); // framed/buffered is built into socket transports
-                        trans = new TTlsServerSocketTransport( param.port, cert, param.buffering,
+                        trans = new TTlsServerSocketTransport( param.port, cert,
                             (sender, certificate, chain, errors) => true, 
                             null, SslProtocols.Tls | SslProtocols.Tls11 | SslProtocols.Tls12);
                         break;
 
                     case TransportChoice.Socket:
                     default:  
-                        transFactory = new TTransportFactory(); // framed/buffered is built into socket transports
-                        trans = new TServerSocketTransport(param.port, 0, param.buffering);
+                        trans = new TServerSocketTransport(param.port, 0);
                         break;
                 }
 
-                // add layered transport, if not already set above
-                if (transFactory == null)
+                // Layered transport (mandatory)
+                TTransportFactory transFactory = null;
+                switch (param.buffering)
                 {
-                    switch (param.buffering)
-                    {
-                        case Buffering.FramedTransport:
-                            transFactory = new TFramedTransport.Factory();
-                            break;
-                        case Buffering.BufferedTransport:
-                            transFactory = new TBufferedTransport.Factory();
-                            break;
-                    }
+                    case BufferChoice.Framed:
+                        transFactory = new TFramedTransport.Factory();
+                        break;
+                    case BufferChoice.Buffered:
+                        transFactory = new TBufferedTransport.Factory();
+                        break;
+                    default:
+                        Debug.Assert(param.buffering == BufferChoice.None, "unhandled case");
+                        transFactory = null;  // no layered transprt
+                        break;
                 }
 
-                // Protocol
+                // Protocol (mandatory)
                 TProtocolFactory proto;
                 switch (param.protocol)
                 {
@@ -617,8 +621,8 @@
                 var where = (! string.IsNullOrEmpty(param.pipe)) ? "on pipe " + param.pipe : "on port " + param.port;
                 Console.WriteLine("Starting the AsyncBaseServer " + where +
                                   " with processor TPrototypeProcessorFactory prototype factory " +
-                                  (param.buffering == Buffering.BufferedTransport ? " with buffered transport" : "") +
-                                  (param.buffering == Buffering.FramedTransport ? " with framed transport" : "") +
+                                  (param.buffering == BufferChoice.Buffered ? " with buffered transport" : "") +
+                                  (param.buffering == BufferChoice.Framed ? " with framed transport" : "") +
                                   (param.transport == TransportChoice.TlsSocket ? " with encryption" : "") +
                                   (param.protocol == ProtocolChoice.Compact ? " with compact protocol" : "") +
                                   (param.protocol == ProtocolChoice.Json ? " with json protocol" : "") +
diff --git a/tutorial/netstd/Client/Client.csproj b/tutorial/netstd/Client/Client.csproj
index 70eae15..a1470a9 100644
--- a/tutorial/netstd/Client/Client.csproj
+++ b/tutorial/netstd/Client/Client.csproj
@@ -30,6 +30,10 @@
   </PropertyGroup>
 
   <ItemGroup>
+    <PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="2.2.0" />
+  </ItemGroup>
+
+  <ItemGroup>
     <ProjectReference Include="..\Interfaces\Interfaces.csproj" />
     <ProjectReference Include="..\..\..\lib\netstd\Thrift\Thrift.csproj" />
   </ItemGroup>
diff --git a/tutorial/netstd/Client/Program.cs b/tutorial/netstd/Client/Program.cs
index 4b68cee..f9509fa 100644
--- a/tutorial/netstd/Client/Program.cs
+++ b/tutorial/netstd/Client/Program.cs
@@ -32,6 +32,7 @@
 using tutorial;
 using shared;
 using Microsoft.Extensions.DependencyInjection;
+using System.Diagnostics;
 
 namespace Client
 {
@@ -47,17 +48,20 @@
     Client.exe -help
         will diplay help information 
 
-    Client.exe -tr:<transport> -pr:<protocol> -mc:<numClients>
+    Client.exe -tr:<transport> -bf:<buffering> -pr:<protocol> -mc:<numClients>
         will run client with specified arguments (tcp transport and binary protocol by default) and with 1 client
 
 Options:
     -tr (transport): 
         tcp - (default) tcp transport will be used (host - ""localhost"", port - 9090)
-        tcpbuffered - buffered transport over tcp will be used (host - ""localhost"", port - 9090)
         namedpipe - namedpipe transport will be used (pipe address - "".test"")
         http - http transport will be used (address - ""http://localhost:9090"")        
         tcptls - tcp tls transport will be used (host - ""localhost"", port - 9090)
-        framed - tcp framed transport will be used (host - ""localhost"", port - 9090)
+
+    -bf (buffering): 
+        none - (default) no buffering will be used
+        buffered - buffered transport will be used
+        framed - framed transport will be used
 
     -pr (protocol): 
         binary - (default) binary protocol will be used
@@ -139,29 +143,57 @@
 
         private static TTransport GetTransport(string[] args)
         {
-            var transport = args.FirstOrDefault(x => x.StartsWith("-tr"))?.Split(':')?[1];
+            TTransport transport = new TSocketTransport(IPAddress.Loopback, 9090);
 
-            Transport selectedTransport;
-            if (Enum.TryParse(transport, true, out selectedTransport))
+            // construct endpoint transport
+            var transportArg = args.FirstOrDefault(x => x.StartsWith("-tr"))?.Split(':')?[1];
+            if (Enum.TryParse(transportArg, true, out Transport selectedTransport))
             {
                 switch (selectedTransport)
                 {
                     case Transport.Tcp:
-                        return new TSocketTransport(IPAddress.Loopback, 9090);
+                        transport = new TSocketTransport(IPAddress.Loopback, 9090);
+                        break;
+
                     case Transport.NamedPipe:
-                        return new TNamedPipeTransport(".test");
+                        transport = new TNamedPipeTransport(".test");
+                        break;
+
                     case Transport.Http:
-                        return new THttpTransport(new Uri("http://localhost:9090"), null);
-                    case Transport.TcpBuffered:
-                        return new TBufferedTransport(new TSocketTransport(IPAddress.Loopback, 9090));
+                        transport = new THttpTransport(new Uri("http://localhost:9090"), null);
+                        break;
+
                     case Transport.TcpTls:
-                        return new TTlsSocketTransport(IPAddress.Loopback, 9090, GetCertificate(), CertValidator, LocalCertificateSelectionCallback);
-                    case Transport.Framed:
-                        return new TFramedTransport(new TSocketTransport(IPAddress.Loopback, 9090));
+                        transport = new TTlsSocketTransport(IPAddress.Loopback, 9090, GetCertificate(), CertValidator, LocalCertificateSelectionCallback);
+                        break;
+
+                    default:
+                        Debug.Assert(false, "unhandled case");
+                        break;
                 }
             }
 
-            return new TSocketTransport(IPAddress.Loopback, 9090);
+            // optionally add layered transport(s)
+            var bufferingArg = args.FirstOrDefault(x => x.StartsWith("-bf"))?.Split(':')?[1];
+            if (Enum.TryParse<Buffering>(bufferingArg, out var selectedBuffering))
+            {
+                switch (selectedBuffering)
+                {
+                    case Buffering.Buffered:
+                        transport = new TBufferedTransport(transport);
+                        break;
+
+                    case Buffering.Framed:
+                        transport = new TFramedTransport(transport);
+                        break;
+
+                    default: // layered transport(s) are optional
+                        Debug.Assert(selectedBuffering == Buffering.None, "unhandled case");
+                        break;
+                }
+            }
+
+            return transport;
         }
 
         private static int GetNumberOfClients(string[] args)
@@ -231,6 +263,9 @@
                     case Protocol.Multiplexed:
                         // it returns BinaryProtocol to avoid making wrapped protocol as public in TProtocolDecorator (in RunClientAsync it will be wrapped into Multiplexed protocol)
                         return new Tuple<Protocol, TProtocol>(selectedProtocol, new TBinaryProtocol(transport));
+                    default:
+                        Debug.Assert(false, "unhandled case");
+                        break;
                 }
             }
 
@@ -363,5 +398,12 @@
             Json,
             Multiplexed
         }
+
+        private enum Buffering
+        {
+            None,
+            Buffered,
+            Framed
+        }
     }
 }
diff --git a/tutorial/netstd/Server/Program.cs b/tutorial/netstd/Server/Program.cs
index c5e26d1..25e7dae 100644
--- a/tutorial/netstd/Server/Program.cs
+++ b/tutorial/netstd/Server/Program.cs
@@ -36,6 +36,7 @@
 using tutorial;
 using shared;
 using Thrift.Processor;
+using System.Diagnostics;
 
 namespace Server
 {
@@ -85,17 +86,20 @@
     Server.exe -help
         will diplay help information 
 
-    Server.exe -tr:<transport> -pr:<protocol>
-        will run server with specified arguments (tcp transport and binary protocol by default)
+    Server.exe -tr:<transport> -bf:<buffering> -pr:<protocol>
+        will run server with specified arguments (tcp transport, no buffering, and binary protocol by default)
 
 Options:
     -tr (transport): 
         tcp - (default) tcp transport will be used (host - ""localhost"", port - 9090)
-        tcpbuffered - tcp buffered transport will be used (host - ""localhost"", port - 9090)
         namedpipe - namedpipe transport will be used (pipe address - "".test"")
         http - http transport will be used (http address - ""localhost:9090"")
         tcptls - tcp transport with tls will be used (host - ""localhost"", port - 9090)
-        framed - tcp framed transport will be used (host - ""localhost"", port - 9090)
+
+    -bf (buffering): 
+        none - (default) no buffering will be used
+        buffered - buffered transport will be used
+        framed - framed transport will be used
 
     -pr (protocol): 
         binary - (default) binary protocol will be used
@@ -111,6 +115,7 @@
         private static async Task RunAsync(string[] args, CancellationToken cancellationToken)
         {
             var selectedTransport = GetTransport(args);
+            var selectedBuffering = GetBuffering(args);
             var selectedProtocol = GetProtocol(args);
 
             if (selectedTransport == Transport.Http)
@@ -119,7 +124,7 @@
             }
             else
             {
-                await RunSelectedConfigurationAsync(selectedTransport, selectedProtocol, cancellationToken);
+                await RunSelectedConfigurationAsync(selectedTransport, selectedBuffering, selectedProtocol, cancellationToken);
             }
         }
 
@@ -132,6 +137,15 @@
             return selectedProtocol;
         }
 
+        private static Buffering GetBuffering(string[] args)
+        {
+            var buffering = args.FirstOrDefault(x => x.StartsWith("-bf"))?.Split(":")?[1];
+
+            Enum.TryParse<Buffering>(buffering, out var selectedBuffering);
+
+            return selectedBuffering;
+        }
+
         private static Transport GetTransport(string[] args)
         {
             var transport = args.FirstOrDefault(x => x.StartsWith("-tr"))?.Split(':')?[1];
@@ -141,10 +155,9 @@
             return selectedTransport;
         }
 
-        private static async Task RunSelectedConfigurationAsync(Transport transport, Protocol protocol, CancellationToken cancellationToken)
+        private static async Task RunSelectedConfigurationAsync(Transport transport, Buffering buffering, Protocol protocol, CancellationToken cancellationToken)
         {
             var handler = new CalculatorAsyncHandler();
-            ITAsyncProcessor processor = null;
 
             TServerTransport serverTransport = null;
             switch (transport)
@@ -152,23 +165,36 @@
                 case Transport.Tcp:
                     serverTransport = new TServerSocketTransport(9090);
                     break;
-                case Transport.TcpBuffered:
-                    serverTransport = new TServerSocketTransport(port: 9090, clientTimeout: 10000, buffering: Buffering.BufferedTransport);
-                    break;
                 case Transport.NamedPipe:
                     serverTransport = new TNamedPipeServerTransport(".test");
                     break;
                 case Transport.TcpTls:
-                    serverTransport = new TTlsServerSocketTransport(9090, GetCertificate(), Buffering.None, ClientCertValidator, LocalCertificateSelectionCallback);
-                    break;
-                case Transport.Framed:
-                    serverTransport = new TServerFramedTransport(9090);
+                    serverTransport = new TTlsServerSocketTransport(9090, GetCertificate(), ClientCertValidator, LocalCertificateSelectionCallback);
                     break;
             }
 
-            TProtocolFactory inputProtocolFactory;
-            TProtocolFactory outputProtocolFactory;
+            TTransportFactory inputTransportFactory = null;
+            TTransportFactory outputTransportFactory = null;
+            switch (buffering)
+            {
+                case Buffering.Buffered:
+                    inputTransportFactory = new TBufferedTransport.Factory();
+                    outputTransportFactory = new TBufferedTransport.Factory();
+                    break;
 
+                case Buffering.Framed:
+                    inputTransportFactory = new TFramedTransport.Factory();
+                    outputTransportFactory = new TFramedTransport.Factory();
+                    break;
+
+                default: // layered transport(s) are optional
+                    Debug.Assert(buffering == Buffering.None, "unhandled case");
+                    break;
+            }
+
+            TProtocolFactory inputProtocolFactory = null;
+            TProtocolFactory outputProtocolFactory = null;
+            ITAsyncProcessor processor = null;
             switch (protocol)
             {
                 case Protocol.Binary:
@@ -210,15 +236,25 @@
                     throw new ArgumentOutOfRangeException(nameof(protocol), protocol, null);
             }
 
+
             try
             {
                 Logger.LogInformation(
                     $"Selected TAsyncServer with {serverTransport} transport, {processor} processor and {inputProtocolFactory} protocol factories");
 
-                var fabric = ServiceCollection.BuildServiceProvider().GetService<ILoggerFactory>();
-                var server = new TSimpleAsyncServer(processor, serverTransport, inputProtocolFactory, outputProtocolFactory, fabric);
+                var loggerFactory = ServiceCollection.BuildServiceProvider().GetService<ILoggerFactory>();
+
+                var server = new TSimpleAsyncServer(
+                    itProcessorFactory: new TSingletonProcessorFactory(processor),
+                    serverTransport: serverTransport,
+                    inputTransportFactory: inputTransportFactory,
+                    outputTransportFactory: outputTransportFactory,
+                    inputProtocolFactory: inputProtocolFactory,
+                    outputProtocolFactory: outputProtocolFactory,
+                    logger: loggerFactory.CreateLogger<TSimpleAsyncServer>());
 
                 Logger.LogInformation("Starting the server...");
+
                 await server.ServeAsync(cancellationToken);
             }
             catch (Exception x)
@@ -266,11 +302,16 @@
         private enum Transport
         {
             Tcp,
-            TcpBuffered,
             NamedPipe,
             Http,
             TcpTls,
-            Framed
+        }
+
+        private enum Buffering
+        {
+            None,
+            Buffered,
+            Framed,
         }
 
         private enum Protocol