private async Task EnsureChannelAsync(FramingConnection connection)
 {
     if (_replyChannel == null)
     {
         using (await _lock.TakeLockAsync())
         {
             if (_replyChannel == null)
             {
                 var be  = connection.ServiceDispatcher.Binding.CreateBindingElements();
                 var tbe = be.Find <TransportBindingElement>();
                 ITransportFactorySettings settings = new NetFramingTransportSettings
                 {
                     CloseTimeout           = connection.ServiceDispatcher.Binding.CloseTimeout,
                     OpenTimeout            = connection.ServiceDispatcher.Binding.OpenTimeout,
                     ReceiveTimeout         = connection.ServiceDispatcher.Binding.ReceiveTimeout,
                     SendTimeout            = connection.ServiceDispatcher.Binding.SendTimeout,
                     ManualAddressing       = tbe.ManualAddressing,
                     BufferManager          = connection.BufferManager,
                     MaxReceivedMessageSize = tbe.MaxReceivedMessageSize,
                     MessageEncoderFactory  = connection.MessageEncoderFactory
                 };
                 _replyChannel      = new ConnectionOrientedTransportReplyChannel(settings, null, _servicesScopeFactory.CreateScope().ServiceProvider);
                 _channelDispatcher = await connection.ServiceDispatcher.CreateServiceChannelDispatcherAsync(_replyChannel);
             }
         }
     }
 }
        public async Task OnConnectedAsync(FramingConnection connection)
        {
            var be  = connection.ServiceDispatcher.Binding.CreateBindingElements();
            var tbe = be.Find <TransportBindingElement>();
            ITransportFactorySettings settings = new NetFramingTransportSettings
            {
                CloseTimeout           = connection.ServiceDispatcher.Binding.CloseTimeout,
                OpenTimeout            = connection.ServiceDispatcher.Binding.OpenTimeout,
                ReceiveTimeout         = connection.ServiceDispatcher.Binding.ReceiveTimeout,
                SendTimeout            = connection.ServiceDispatcher.Binding.SendTimeout,
                ManualAddressing       = tbe.ManualAddressing,
                BufferManager          = connection.BufferManager,
                MaxReceivedMessageSize = tbe.MaxReceivedMessageSize,
                MessageEncoderFactory  = connection.MessageEncoderFactory
            };
            var scope   = _servicesScopeFactory.CreateScope();
            var channel = new ServerFramingDuplexSessionChannel(connection, settings, false, _servicesScopeFactory.CreateScope().ServiceProvider);
            await channel.OpenAsync();

            var decoder           = connection.ServerSessionDecoder;
            var serviceDispatcher = connection.ServiceDispatcher;

            while (true)
            {
                Message message = await ReceiveMessageAsync(connection);

                if (message == null)
                {
                    return; // No more messages
                }
                // TODO: Create a correctly timing out ct
                await serviceDispatcher.DispatchAsync(new DuplexRequestContext(channel, message, connection.ServiceDispatcher.Binding), channel, CancellationToken.None);
            }
        }
        public async Task OnConnectedAsync(FramingConnection connection)
        {
            var be  = connection.ServiceDispatcher.Binding.CreateBindingElements();
            var tbe = be.Find <TransportBindingElement>();
            ITransportFactorySettings settings = new NetFramingTransportSettings
            {
                CloseTimeout           = connection.ServiceDispatcher.Binding.CloseTimeout,
                OpenTimeout            = connection.ServiceDispatcher.Binding.OpenTimeout,
                ReceiveTimeout         = connection.ServiceDispatcher.Binding.ReceiveTimeout,
                SendTimeout            = connection.ServiceDispatcher.Binding.SendTimeout,
                ManualAddressing       = tbe.ManualAddressing,
                BufferManager          = connection.BufferManager,
                MaxReceivedMessageSize = tbe.MaxReceivedMessageSize,
                MessageEncoderFactory  = connection.MessageEncoderFactory
            };
            var timeoutHelper = new TimeoutHelper(settings.ReceiveTimeout);
            var channel       = new InputChannel(settings, null, _servicesScopeFactory.CreateScope().ServiceProvider);
            await channel.OpenAsync();

            var channelDispatcher = connection.ServiceDispatcher.CreateServiceChannelDispatcher(channel);

            // TODO: I think that the receive timeout starts counting at the start of the preamble on .NET Framework. This implementation basically resets the timer
            // after the preamble has completed. This probably needs to be addressed otherwise worse case you could end up taking 2X as long to timeout.
            // I believe the preamble should really use the OpenTimeout but that's not how this is implemented on .NET Framework.

            var requestContext = (StreamedFramingRequestContext) await ReceiveRequestAsync(connection, timeoutHelper.RemainingTime());

            _ = channelDispatcher.DispatchAsync(requestContext, CancellationToken.None);
            await requestContext.ReplySent;
            await Task.Delay(5);
        }
        public async Task OnConnectedAsync(FramingConnection connection)
        {
            if (!_transportSettingsCache.TryGetValue(connection.ServiceDispatcher, out ITransportFactorySettings settings))
            {
                BindingElementCollection be  = connection.ServiceDispatcher.Binding.CreateBindingElements();
                TransportBindingElement  tbe = be.Find <TransportBindingElement>();
                settings = new NetFramingTransportSettings
                {
                    CloseTimeout           = connection.ServiceDispatcher.Binding.CloseTimeout,
                    OpenTimeout            = connection.ServiceDispatcher.Binding.OpenTimeout,
                    ReceiveTimeout         = connection.ServiceDispatcher.Binding.ReceiveTimeout,
                    SendTimeout            = connection.ServiceDispatcher.Binding.SendTimeout,
                    ManualAddressing       = tbe.ManualAddressing,
                    BufferManager          = connection.BufferManager,
                    MaxReceivedMessageSize = tbe.MaxReceivedMessageSize,
                    MessageEncoderFactory  = connection.MessageEncoderFactory
                };
            }

            var channel = new ServerFramingDuplexSessionChannel(connection, settings, false, _servicesScopeFactory.CreateScope().ServiceProvider);

            channel.ChannelDispatcher = await connection.ServiceDispatcher.CreateServiceChannelDispatcherAsync(channel);

            await channel.StartReceivingAsync();
        }
        public async Task OnConnectedAsync(FramingConnection connection)
        {
            var be  = connection.ServiceDispatcher.Binding.CreateBindingElements();
            var tbe = be.Find <TransportBindingElement>();
            ITransportFactorySettings settings = new NetFramingTransportSettings
            {
                CloseTimeout           = connection.ServiceDispatcher.Binding.CloseTimeout,
                OpenTimeout            = connection.ServiceDispatcher.Binding.OpenTimeout,
                ReceiveTimeout         = connection.ServiceDispatcher.Binding.ReceiveTimeout,
                SendTimeout            = connection.ServiceDispatcher.Binding.SendTimeout,
                ManualAddressing       = tbe.ManualAddressing,
                BufferManager          = connection.BufferManager,
                MaxReceivedMessageSize = tbe.MaxReceivedMessageSize,
                MessageEncoderFactory  = connection.MessageEncoderFactory
            };

            var channel = new ServerFramingDuplexSessionChannel(connection, settings, false, _servicesScopeFactory.CreateScope().ServiceProvider);
            await channel.OpenAsync();

            using (_appLifetime.ApplicationStopping.Register(() =>
            {
                _ = channel.CloseAsync();
            }))
            {
                var channelDispatcher = connection.ServiceDispatcher.CreateServiceChannelDispatcher(channel);
                while (true)
                {
                    Message message = await ReceiveMessageAsync(connection);

                    if (message == null)
                    {
                        await channel.CloseAsync();

                        return; // No more messages
                    }
                    var requestContext = new DuplexRequestContext(channel, message, connection.ServiceDispatcher.Binding);
                    // TODO: Create a correctly timing out ct
                    // We don't await DispatchAsync because in a concurrent service we want to read the next request before the previous
                    // request has finished.
                    _ = channelDispatcher.DispatchAsync(requestContext, CancellationToken.None);
                    // TODO: Now there's a channel dispatcher, have that handle negotiateing a Task which completes when it's time to get the next request
                    await requestContext.OperationDispatching;
                }
            }
        }