private bool DecodeBytes(FramingConnection connection, ref ReadOnlySequence <byte> buffer)
        {
            var decoder = connection.FramingDecoder as ServerSingletonDecoder;

            Fx.Assert(decoder != null, "FramingDecoder must be a non-null ServerSingletonDecoder");
            while (!connection.EOF && buffer.Length > 0)
            {
                int bytesRead = decoder.Decode(buffer);
                if (bytesRead > 0)
                {
                    buffer = buffer.Slice(bytesRead);
                }

                switch (decoder.CurrentState)
                {
                case ServerSingletonDecoder.State.EnvelopeStart:
                    // we're at the envelope
                    return(true);

                case ServerSingletonDecoder.State.End:
                    connection.EOF = true;
                    return(false);
                }
            }

            return(false);
        }
        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);
            }
        }
 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 inputPipe   = connection.Input;
            var modeDecoder = new ServerModeDecoder();

            try
            {
                await modeDecoder.ReadModeAsync(inputPipe);
            }
            catch (CommunicationException e)
            {
                // see if we need to send back a framing fault
                string framingFault;
                if (FramingEncodingString.TryGetFaultString(e, out framingFault))
                {
                    // TODO: Timeouts
                    await connection.SendFaultAsync(framingFault, Timeout.InfiniteTimeSpan /*GetRemainingTimeout()*/,
                                                    ConnectionOrientedTransportDefaults.MaxViaSize + ConnectionOrientedTransportDefaults.MaxContentTypeSize);
                }

                return; // Completing the returned Task causes the connection to be closed if needed and cleans everything up.
            }

            connection.FramingMode = modeDecoder.Mode;
            await _next(connection);

            // One .NET Framework, with the way that AspNetCore closes a connection, it sometimes doesn't send the
            // final bytes if those bytes haven't been sent yet. Delaying completeing the connection to compensate.
            await Task.Delay(5);

            // AspNetCore 2.1 doesn't close the connection. 2.2+ does so these lines can eventually be rmoved.
            connection.RawTransport.Input.Complete();
            connection.RawTransport.Output.Complete();
        }
        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 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);
        }
 private void PrepareMessage(FramingConnection connection, Message message)
 {
     if (connection.SecurityMessageProperty != null)
     {
         message.Properties.Security = (SecurityMessageProperty)connection.SecurityMessageProperty.CreateCopy();
     }
 }
예제 #8
0
        public static async Task WriteMessageAsync(Message message, FramingConnection connection, bool isRequest,
                                                   IDefaultCommunicationTimeouts settings, CancellationToken token)
        {
            byte[] endBytes = null;
            if (message != null)
            {
                MessageEncoder messageEncoder     = connection.MessageEncoderFactory.Encoder;
                byte[]         envelopeStartBytes = SingletonEncoder.EnvelopeStartBytes;

                bool writeStreamed;
                if (isRequest)
                {
                    endBytes      = SingletonEncoder.EnvelopeEndFramingEndBytes;
                    writeStreamed = TransferModeHelper.IsRequestStreamed(connection.TransferMode);
                }
                else
                {
                    endBytes      = SingletonEncoder.EnvelopeEndBytes;
                    writeStreamed = TransferModeHelper.IsResponseStreamed(connection.TransferMode);
                }

                if (writeStreamed)
                {
                    await connection.Output.WriteAsync(envelopeStartBytes, token);

                    Stream connectionStream = new StreamingOutputConnectionStream(connection, settings);
                    // TODO: Determine if timeout stream is needed as StreamingOutputConnectionStream implements some timeout functionality
                    //Stream writeTimeoutStream = new TimeoutStream(connectionStream, ref timeoutHelper);
                    await messageEncoder.WriteMessageAsync(message, connectionStream);

                    await connection.Output.FlushAsync();
                }
                else
                {
                    ArraySegment <byte> messageData = messageEncoder.WriteMessage(message,
                                                                                  int.MaxValue, connection.BufferManager, envelopeStartBytes.Length + IntEncoder.MaxEncodedSize);
                    messageData = SingletonEncoder.EncodeMessageFrame(messageData);
                    Buffer.BlockCopy(envelopeStartBytes, 0, messageData.Array, messageData.Offset - envelopeStartBytes.Length,
                                     envelopeStartBytes.Length);
                    await connection.Output.WriteAsync(new ArraySegment <byte>(messageData.Array, messageData.Offset - envelopeStartBytes.Length,
                                                                               messageData.Count + envelopeStartBytes.Length), token);

                    await connection.Output.FlushAsync();

                    connection.BufferManager.ReturnBuffer(messageData.Array);
                }
            }
            else if (isRequest) // context handles response end bytes
            {
                endBytes = SingletonEncoder.EndBytes;
            }

            if (endBytes != null)
            {
                await connection.Output.WriteAsync(endBytes, token);

                await connection.Output.FlushAsync();
            }
        }
예제 #9
0
        public static async Task UpgradeConnectionAsync(FramingConnection connection)
        {
            connection.RawStream = new RawStream(connection.Input, connection.Output);
            var upgradeAcceptor = connection.StreamUpgradeAcceptor;
            var stream          = await upgradeAcceptor.AcceptUpgradeAsync(connection.RawStream);

            CreatePipelineFromStream(connection, stream);
        }
 public StreamedFramingRequestContext(FramingConnection connection, Message requestMessage, Stream inputStream)
     : base(requestMessage, connection.ServiceDispatcher.Binding.CloseTimeout, connection.ServiceDispatcher.Binding.SendTimeout)
 {
     _connection     = connection;
     _requestMessage = requestMessage;
     _inputStream    = inputStream;
     _tcs            = new TaskCompletionSource <object>(TaskCreationOptions.RunContinuationsAsynchronously);
 }
        public static async Task UpgradeConnectionAsync(FramingConnection connection)
        {
            Stream stream          = new Microsoft.AspNetCore.Server.Kestrel.Core.Adapter.Internal.RawStream(connection.Input, connection.Output);
            var    upgradeAcceptor = connection.StreamUpgradeAcceptor;

            stream = await upgradeAcceptor.AcceptUpgradeAsync(stream);

            CreatePipelineFromStream(connection, stream);
        }
        private void EnsureDecoderAtEof(FramingConnection connection)
        {
            var decoder = connection.ServerSessionDecoder;

            if (!(decoder.CurrentState == ServerSessionDecoder.State.End || decoder.CurrentState == ServerSessionDecoder.State.EnvelopeEnd))
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(decoder.CreatePrematureEOFException());
            }
        }
 public SingletonInputConnectionStream(FramingConnection connection,
                                       IDefaultCommunicationTimeouts defaultTimeouts)
 {
     _connection         = connection;
     _timeouts           = defaultTimeouts;
     decoder             = new SingletonMessageDecoder();
     chunkBytesRemaining = 0;
     _timeoutHelper      = new TimeoutHelper(_timeouts.ReceiveTimeout);
 }
예제 #14
0
        public async Task OnConnectedAsync(FramingConnection connection)
        {
            var inputPipe   = connection.Input;
            var modeDecoder = new ServerModeDecoder();
            await modeDecoder.ReadModeAsync(inputPipe);

            connection.FramingMode = modeDecoder.Mode;
            await _next(connection);
        }
        public async Task OnConnectedAsync(FramingConnection connection)
        {
            using (_appLifetime.ApplicationStopped.Register(() =>
            {
                connection.RawTransport.Input.Complete();
                connection.RawTransport.Output.Complete();
            }))
            {
                IConnectionReuseHandler reuseHandler = null;
                do
                {
                    var inputPipe   = connection.Input;
                    var modeDecoder = new ServerModeDecoder();
                    try
                    {
                        if (!await modeDecoder.ReadModeAsync(inputPipe))
                        {
                            break; // Input pipe closed
                        }
                    }
                    catch (CommunicationException e)
                    {
                        // see if we need to send back a framing fault
                        string framingFault;
                        if (FramingEncodingString.TryGetFaultString(e, out framingFault))
                        {
                            // TODO: Timeouts
                            await connection.SendFaultAsync(framingFault, Timeout.InfiniteTimeSpan /*GetRemainingTimeout()*/,
                                                            ConnectionOrientedTransportDefaults.MaxViaSize + ConnectionOrientedTransportDefaults.MaxContentTypeSize);
                        }

                        return; // Completing the returned Task causes the connection to be closed if needed and cleans everything up.
                    }

                    connection.FramingMode = modeDecoder.Mode;
                    await _next(connection);

                    // Unwrap the connection.
                    // TODO: Investigate calling Dispose on the wrapping stream to improve cleanup. nb: .NET Framework does not call Dispose.
                    connection.Transport = connection.RawTransport;
                    // connection.ServiceDispatcher is null until later middleware layers are executed.
                    if (reuseHandler == null)
                    {
                        reuseHandler = connection.ServiceDispatcher.Binding.GetProperty <IConnectionReuseHandler>(new BindingParameterCollection());
                    }
                } while (await reuseHandler.ReuseConnectionAsync(connection, _appLifetime.ApplicationStopping));

                // On .NET Framework, with the way that AspNetCore closes a connection, it sometimes doesn't send the
                // final bytes if those bytes haven't been sent yet. Delaying completeing the connection to compensate.
                await Task.Delay(5);
            }

            // AspNetCore 2.1 doesn't close the connection. 2.2+ does so these lines can eventually be removed.
            connection.RawTransport.Input.Complete();
            connection.RawTransport.Output.Complete();
        }
예제 #16
0
        public RawStream(FramingConnection connection)
        {
#if DEBUG
            _connection = connection;
#endif
            _input    = connection.Input;
            _output   = connection.Output;
            _canRead  = true;
            _thisLock = new object();
        }
예제 #17
0
        public async Task OnConnectedAsync(FramingConnection connection)
        {
            var decoder = new ServerSessionDecoder(ConnectionOrientedTransportDefaults.MaxViaSize, ConnectionOrientedTransportDefaults.MaxContentTypeSize);
            ReadOnlySequence <byte> buffer;

            while (decoder.CurrentState != ServerSessionDecoder.State.PreUpgradeStart)
            {
                var readResult = await connection.Input.ReadAsync();

                buffer = readResult.Buffer;

                while (buffer.Length > 0)
                {
                    int bytesDecoded;
                    try
                    {
                        bytesDecoded = decoder.Decode(buffer);
                    }
                    catch (CommunicationException e)
                    {
                        // see if we need to send back a framing fault
                        string framingFault;
                        if (FramingEncodingString.TryGetFaultString(e, out framingFault))
                        {
                            // TODO: Drain the rest of the data and send a fault then close the connection
                            //byte[] drainBuffer = new byte[128];
                            //InitialServerConnectionReader.SendFault(
                            //    Connection, framingFault, drainBuffer, GetRemainingTimeout(),
                            //    MaxViaSize + MaxContentTypeSize);
                            //base.Close(GetRemainingTimeout());
                        }
                        throw;
                    }

                    if (bytesDecoded > 0)
                    {
                        buffer = buffer.Slice(bytesDecoded);
                    }

                    if (decoder.CurrentState == ServerSessionDecoder.State.PreUpgradeStart)
                    {
                        // We now know the Via address (which endpoint the client is connecting to).
                        // The connection now needs to be handled by the correct endpoint which can
                        // handle upgrades etc.
                        break; //exit loop
                    }
                }

                connection.Input.AdvanceTo(buffer.Start);
            }

            connection.ServerSessionDecoder = decoder;

            await _next(connection);
        }
        public static async Task UpgradeConnectionAsync(FramingConnection connection, string contentType)
        {
            var duplexPipeStream = new DuplexPipeStream(connection.Input, connection.Output);

            connection.RawStream = duplexPipeStream;
            StreamUpgradeAcceptor upgradeAcceptor = connection.StreamUpgradeAcceptor;
            Stream stream = await upgradeAcceptor.AcceptUpgradeAsync(connection.RawStream);

            duplexPipeStream.SetContentType(contentType);
            CreatePipelineFromStream(connection, stream);
        }
예제 #19
0
 public ServerFramingDuplexSessionChannel(FramingConnection connection, ITransportFactorySettings settings,
                                          bool exposeConnectionProperty, IServiceProvider serviceProvider)
     : base(connection, settings, exposeConnectionProperty)
 {
     Connection       = connection;
     upgradeAcceptor  = connection.StreamUpgradeAcceptor;
     _serviceProvider = serviceProvider;
     //if (upgradeAcceptor != null)
     //{
     //    this.channelBindingProvider = upgrade.GetProperty<IStreamUpgradeChannelBindingProvider>();
     //    this.upgradeAcceptor = upgrade.CreateUpgradeAcceptor();
     //}
 }
예제 #20
0
 public async Task OnConnectedAsync(FramingConnection connection)
 {
     // If the remote client aborts or the connection, AspNetCore throws an exceptions which
     // bubbles all the way up to here and causes a critical level event to be logged. This is a normal thing
     // to happen so just swallowing the exception to suppress the critical log output.
     try
     {
         await OnConnectedCoreAsync(connection);
     }
     catch (Microsoft.AspNetCore.Connections.ConnectionAbortedException) { }
     catch (Microsoft.AspNetCore.Connections.ConnectionResetException) { }
     catch (CoreWCF.Security.SecurityNegotiationException) { } // TODO: Work out where this needs to be caught
     catch (System.IO.IOException) { }                         // TODO: Work out where this needs to be caught
 }
        private void PrepareMessage(FramingConnection connection, Message message)
        {
            if (connection.SecurityMessageProperty != null)
            {
                message.Properties.Security = (SecurityMessageProperty)connection.SecurityMessageProperty.CreateCopy();
            }

            IPEndPoint remoteEndPoint = connection.RemoteEndpoint;

            // pipes will return null
            if (remoteEndPoint != null)
            {
                var remoteEndpointProperty = new RemoteEndpointMessageProperty(remoteEndPoint);
                message.Properties.Add(RemoteEndpointMessageProperty.Name, remoteEndpointProperty);
            }
        }
        public async Task OnConnectedAsync(FramingConnection connection)
        {
            await EnsureChannelAsync(connection);

            // 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 timeoutHelper  = new TimeoutHelper(((IDefaultCommunicationTimeouts)_replyChannel).ReceiveTimeout);
            var requestContext = await ReceiveRequestAsync(connection, timeoutHelper.RemainingTime());

            await _channelDispatcher.DispatchAsync(requestContext);

            await requestContext.ReplySent;
            //await channelDispatcher.DispatchAsync();
            //await requestContext.ReplySent;
        }
        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;
                }
            }
        }
        private async Task <Message> ReceiveMessageAsync(FramingConnection connection)
        {
            // TODO: Apply timeouts
            Message message;
            ReadOnlySequence <byte> buffer = ReadOnlySequence <byte> .Empty;

            for (; ;)
            {
                var readResult = await connection.Input.ReadAsync();

                if (readResult.IsCompleted || readResult.Buffer.Length == 0)
                {
                    if (!readResult.IsCompleted)
                    {
                        connection.Input.AdvanceTo(readResult.Buffer.Start);
                    }
                    EnsureDecoderAtEof(connection);
                    connection.EOF = true;
                }

                if (connection.EOF)
                {
                    return(null);
                }

                buffer  = readResult.Buffer;
                message = DecodeMessage(connection, ref buffer);
                connection.Input.AdvanceTo(buffer.Start);

                if (message != null)
                {
                    PrepareMessage(connection, message);
                    return(message);
                }
                else if (connection.EOF) // could have read the END record under DecodeMessage
                {
                    return(null);
                }

                if (buffer.Length != 0)
                {
                    throw Fx.AssertAndThrow("Receive: DecodeMessage() should consume the outstanding buffer or return a message.");
                }
            }
        }
        private static void ValidateContentType(FramingConnection connection, FramingDecoder decoder)
        {
            MessageEncoderFactory messageEncoderFactory = connection.MessageEncoderFactory;
            MessageEncoder        messageEncoder        = messageEncoderFactory.CreateSessionEncoder();

            connection.MessageEncoder = messageEncoder;

            if (!messageEncoder.IsContentTypeSupported(decoder.ContentType))
            {
                // TODO: Send fault response
                //SendFault(FramingEncodingString.ContentTypeInvalidFault, ref timeoutHelper);
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ProtocolException(SR.Format(
                                                                                                    SR.ContentTypeMismatch, decoder.ContentType, messageEncoder.ContentType)));
            }

            if (messageEncoder is ICompressedMessageEncoder compressedMessageEncoder && compressedMessageEncoder.CompressionEnabled)
            {
                compressedMessageEncoder.SetSessionContentType(decoder.ContentType);
            }
        }
        private static void ProcessUpgradeRequest(FramingConnection connection, ServerSessionDecoder decoder)
        {
            var upgradeAcceptor = connection.StreamUpgradeAcceptor;

            if (upgradeAcceptor == null)
            {
                // TODO: SendFault
                //SendFault(FramingEncodingString.UpgradeInvalidFault, ref timeoutHelper);
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                          new ProtocolException(SR.Format(SR.UpgradeRequestToNonupgradableService, decoder.Upgrade)));
            }

            if (!upgradeAcceptor.CanUpgrade(decoder.Upgrade))
            {
                // TODO: SendFault
                //SendFault(FramingEncodingString.UpgradeInvalidFault, ref timeoutHelper);
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                          new ProtocolException(SR.Format(SR.UpgradeProtocolNotSupported, decoder.Upgrade)));
            }
        }
        private static void SetupSecurityIfNecessary(FramingConnection connection)
        {
            if (connection.StreamUpgradeAcceptor is StreamSecurityUpgradeAcceptor securityUpgradeAcceptor)
            {
                Security.SecurityMessageProperty remoteSecurity = securityUpgradeAcceptor.GetRemoteSecurity();

                if (remoteSecurity == null)
                {
                    Exception securityFailedException = new ProtocolException(
                        SR.Format(SR.RemoteSecurityNotNegotiatedOnStreamUpgrade, connection.Via));
                    //WriteAuditFailure(securityUpgradeAcceptor, securityFailedException);
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(securityFailedException);
                }
                else
                {
                    connection.SecurityMessageProperty = remoteSecurity;
                    // Audit Authentication Success
                    //WriteAuditEvent(securityUpgradeAcceptor, AuditLevel.Success, null);
                }
            }
        }
        private void PrepareMessage(FramingConnection connection, Message message)
        {
            message.Properties.Via      = connection.Via;
            message.Properties.Security = (connection.SecurityMessageProperty != null) ? (SecurityMessageProperty)connection.SecurityMessageProperty.CreateCopy() : null;

            IPEndPoint remoteEndPoint = connection.RemoteEndpoint;

            // pipes will return null
            if (remoteEndPoint != null)
            {
                var remoteEndpointProperty = new RemoteEndpointMessageProperty(remoteEndPoint);
                message.Properties.Add(RemoteEndpointMessageProperty.Name, remoteEndpointProperty);
            }

            // TODO: ChannelBindingToken
            //if (this.channelBindingToken != null)
            //{
            //    ChannelBindingMessageProperty property = new ChannelBindingMessageProperty(this.channelBindingToken, false);
            //    property.AddTo(message);
            //    property.Dispose(); //message.Properties.Add() creates a copy...
            //}
        }
예제 #29
0
        public async Task OnConnectedAsync(FramingConnection connection)
        {
            var  decoder = new ServerSingletonDecoder(ConnectionOrientedTransportDefaults.MaxViaSize, ConnectionOrientedTransportDefaults.MaxContentTypeSize, connection.Logger);
            bool success = false;

            try
            {
                ReadOnlySequence <byte> buffer;
                while (decoder.CurrentState != ServerSingletonDecoder.State.PreUpgradeStart)
                {
                    System.IO.Pipelines.ReadResult readResult = await connection.Input.ReadAsync();

                    buffer = readResult.Buffer;

                    while (buffer.Length > 0)
                    {
                        int bytesDecoded = decoder.Decode(buffer);
                        if (bytesDecoded > 0)
                        {
                            buffer = buffer.Slice(bytesDecoded);
                        }

                        if (decoder.CurrentState == ServerSingletonDecoder.State.PreUpgradeStart)
                        {
                            // We now know the Via address (which endpoint the client is connecting to).
                            // The connection now needs to be handled by the correct endpoint which can
                            // handle upgrades etc.
                            break; //exit loop
                        }
                    }

                    connection.Input.AdvanceTo(buffer.Start);
                }

                success = true;
            }
            catch (CommunicationException exception)
            {
                DiagnosticUtility.TraceHandledException(exception, TraceEventType.Information);
            }
            catch (OperationCanceledException exception)
            {
                //if (TD.ReceiveTimeoutIsEnabled())
                //{
                //    TD.ReceiveTimeout(exception.Message);
                //}
                DiagnosticUtility.TraceHandledException(exception, TraceEventType.Information);
            }
            catch (TimeoutException exception)
            {
                //if (TD.ReceiveTimeoutIsEnabled())
                //{
                //    TD.ReceiveTimeout(exception.Message);
                //}
                DiagnosticUtility.TraceHandledException(exception, TraceEventType.Information);
            }
            catch (Exception e)
            {
                if (Fx.IsFatal(e))
                {
                    throw;
                }
                if (!TransportExceptionHandler.HandleTransportExceptionHelper(e))
                {
                    throw;
                }
                // containment -- all exceptions abort the reader, no additional containment action necessary
            }
            finally
            {
                if (!success)
                {
                    // TODO: On .NET Framework, this Abort call via a long winding path of plumbing will trigger a new pending Accept
                    // as this connection establishment handshake has failed. Some back pressure mechanism needs to be implemented to
                    // stop extra incoming connection handshakes from being started. Maybe a semaphore which is async waited at initial
                    // incoming request and then released on completion of handshake or on an exception. It also closes the connection
                    // so that's all that's happening here for now. Returning and completing the task will cause the connection to be closed.
                    connection.Abort();
                }
            }

            if (success)
            {
                connection.FramingDecoder = decoder;
                await _next(connection);
            }
            // else:
            //   returning will close the connection if it hasn't already been.
        }
        public override Task OnConnectedAsync(ConnectionContext context)
        {
            var connection = new FramingConnection(context);

            return(_handshake(connection));
        }