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(); }
protected Exception CreateException(InvalidDataException innerException, string framingFault) { Exception result = CreateException(innerException); FramingEncodingString.AddFaultString(result, framingFault); return(result); }
protected override Exception OnSizeQuotaExceeded(int size) { Exception result = new InvalidDataException(SR.Format(SR.FramingContentTypeTooLong, size)); FramingEncodingString.AddFaultString(result, FramingEncodingString.ContentTypeTooLongFault); return(result); }
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(); }
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); }
internal async Task <bool> ReadModeAsync(PipeReader inputPipe) { ReadOnlySequence <byte> buffer; while (true) { var readResult = await inputPipe.ReadAsync(); if (readResult.IsCompleted) { return(false); } buffer = readResult.Buffer; while (buffer.Length > 0) { int bytesDecoded; try { bytesDecoded = 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 (CurrentState == State.Done) { inputPipe.AdvanceTo(buffer.Start); return(true); } } inputPipe.AdvanceTo(buffer.End); } }