public async Task <bool> ReuseConnectionAsync(FramingConnection connection, CancellationToken cancellationToken) { if (cancellationToken.IsCancellationRequested) { return(false); } if (!_connectionPoolSemaphore.Wait(0)) { //if (DiagnosticUtility.ShouldTraceWarning) //{ // TraceUtility.TraceEvent(TraceEventType.Warning, // TraceCode.ServerMaxPooledConnectionsQuotaReached, // SR.GetString(SR.TraceCodeServerMaxPooledConnectionsQuotaReached, maxPooledConnections), // new StringTraceRecord("MaxOutboundConnectionsPerEndpoint", maxPooledConnections.ToString(CultureInfo.InvariantCulture)), // this, null); //} //if (TD.ServerMaxPooledConnectionsQuotaReachedIsEnabled()) //{ // TD.ServerMaxPooledConnectionsQuotaReached(); //} // No space left in the connection pool return(false); } try { connection.Reset(); CancellationToken ct = new TimeoutHelper(_idleTimeout).GetCancellationToken(); using (var linkedCts = CancellationTokenSource.CreateLinkedTokenSource( new TimeoutHelper(_idleTimeout).GetCancellationToken(), cancellationToken)) { System.IO.Pipelines.ReadResult readResult = await connection.Input.ReadAsync(linkedCts.Token); connection.Input.AdvanceTo(readResult.Buffer.Start); // Don't consume any bytes. The pending read is to know when a new client connects. if (readResult.Buffer.IsEmpty && !readResult.IsCompleted && !readResult.IsCanceled) { // After pending read is canceled, next ReadAsync can return immediately with a 0 byte response so another ReadAsync call is needed readResult = await connection.Input.ReadAsync(linkedCts.Token); connection.Input.AdvanceTo(readResult.Buffer.Start); // Don't consume any bytes. The pending read is to know when a new client connects. } } return(true); } catch (Exception) { return(false); } finally { _connectionPoolSemaphore.Release(); } }
public async Task <Message> ReceiveAsync(CancellationToken token) { // TODO: Apply timeouts Message message; ReadOnlySequence <byte> buffer = ReadOnlySequence <byte> .Empty; for (; ;) { System.IO.Pipelines.ReadResult readResult = await _connection.Input.ReadAsync(token); if (readResult.IsCompleted || readResult.Buffer.Length == 0) { if (!readResult.IsCompleted) { _connection.Input.AdvanceTo(readResult.Buffer.Start); } EnsureDecoderAtEof(); _connection.EOF = true; } if (_connection.EOF) { return(null); } buffer = readResult.Buffer; message = DecodeMessage(ref buffer); _connection.Input.AdvanceTo(buffer.Start); _connection.Logger.ReceivedMessage(message); if (message != null) { PrepareMessage(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."); } } }
public static async Task <string> GetRequestBody(this HttpContext context) { HttpRequest request = context.Request; string contentType = request.ContentType.ToLower(); if (request.Method.ToLower() == "post" && (contentType == "json" || contentType == "application/json")) { request.Body.Seek(0, SeekOrigin.Begin); System.IO.Pipelines.ReadResult r = await request.BodyReader.ReadAsync(); using (StreamReader reader = new StreamReader(request.Body, Encoding.UTF8)) { await reader.ReadToEndAsync(); }; } return(JsonConvert.SerializeObject(request.Query)); }
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 abstract bool TryRead(out System.IO.Pipelines.ReadResult result);
public async Task OnConnectedAsync(FramingConnection connection) { bool success = false; try { var decoder = connection.FramingDecoder as ServerSessionDecoder; Fx.Assert(decoder != null, "FramingDecoder must be non-null and an instance of ServerSessionDecoder"); // first validate our content type ValidateContentType(connection, decoder); // next read any potential upgrades and finish consuming the preamble ReadOnlySequence <byte> buffer; while (true) { System.IO.Pipelines.ReadResult readResult = await connection.Input.ReadAsync(); buffer = readResult.Buffer; if (readResult.IsCompleted) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(decoder.CreatePrematureEOFException()); } while (buffer.Length > 0) { int bytesDecoded = decoder.Decode(buffer); if (bytesDecoded > 0) { buffer = buffer.Slice(bytesDecoded); } switch (decoder.CurrentState) { case ServerSessionDecoder.State.UpgradeRequest: ProcessUpgradeRequest(connection, decoder); // accept upgrade await connection.Output.WriteAsync(ServerSessionEncoder.UpgradeResponseBytes); await connection.Output.FlushAsync(); //await context.Transport.Output.WriteAsync //Connection.Write(ServerSessionEncoder.UpgradeResponseBytes, 0, ServerSessionEncoder.UpgradeResponseBytes.Length, true, timeoutHelper.RemainingTime()); try { connection.Input.AdvanceTo(buffer.Start); buffer = ReadOnlySequence <byte> .Empty; await UpgradeConnectionAsync(connection, decoder.Upgrade); // TODO: ChannelBinding //if (this.channelBindingProvider != null && this.channelBindingProvider.IsChannelBindingSupportEnabled) //{ // this.SetChannelBinding(this.channelBindingProvider.GetChannelBinding(this.upgradeAcceptor, ChannelBindingKind.Endpoint)); //} //this.connectionBuffer = Connection.AsyncReadBuffer; } catch (Exception exception) { if (Fx.IsFatal(exception)) { throw; } // Audit Authentication Failure //WriteAuditFailure(upgradeAcceptor as StreamSecurityUpgradeAcceptor, exception); throw; } break; case ServerSessionDecoder.State.Start: SetupSecurityIfNecessary(connection); // we've finished the preamble. Ack and continue to the next middleware. await connection.Output.WriteAsync(ServerSessionEncoder.AckResponseBytes); await connection.Output.FlushAsync(); connection.Input.AdvanceTo(buffer.Start); await _next(connection); success = true; return; } } } } finally { if (!success) { connection.Abort(); } } }
/// <summary> /// 处理浏览器 /// </summary> /// <param name="browser"></param> /// <returns></returns> public static void ProcessBrowserAsync(ConnectionContext browser) { Task.Run(async() => { //最终网站 SocketConnect target = new SocketConnect(); try { while (true) { System.IO.Pipelines.ReadResult result = await browser.Transport.Input.ReadAsync(); if (!result.Buffer.IsEmpty) { var message = Message.ParsePack(result.Buffer.ToArray()); if (message.Item1 != null) { var data = message.Item1.Content; //var data = Crypto.DecryptAES(message.Item1.Content); Socket5Info socket5Info = new Socket5Info(); if (socket5Info.TryParse(data)) { await target.ConnectAsync(System.Text.Encoding.UTF8.GetString(socket5Info.Address), socket5Info.Port); //连接到服务器 //var ipEndPoint = await GetIpEndPointAsync(System.Text.Encoding.UTF8.GetString(socket5Info.Address), socket5Info.Port); //if(ipEndPoint == null) //{ // break; //} //await target.ConnectAsync(ipEndPoint.Address,ipEndPoint.Port); byte[] sendData = new byte[] { 0x05, 0x00, 0x00, 0x01, 0x7f, 0x00, 0x00, 0x01, 0x1f, 0x40 }; //发送确认到浏览器 await browser.Transport.Output.WriteAsync(sendData); ProcessTargetServer(browser, target); } else { //发送数据到目标服务器 await target.TcpClient.Client.SendAsync(data, SocketFlags.None); } browser.Transport.Input.AdvanceTo(result.Buffer.GetPosition(message.Item2)); } else { browser.Transport.Input.AdvanceTo(result.Buffer.GetPosition(0)); } } else { if (result.IsCompleted || result.IsCanceled) { break; } } } await browser.Transport.Input.CompleteAsync(); } catch (Exception ex) { Console.WriteLine(ex.Message); } }); }
public async Task OnConnectedAsync(FramingConnection connection) { TimeSpan receiveTimeout = connection.ServiceDispatcher.Binding.ReceiveTimeout; var timeoutHelper = new TimeoutHelper(receiveTimeout); bool success = false; try { var decoder = connection.FramingDecoder as ServerSingletonDecoder; Fx.Assert(decoder != null, "FramingDecoder must be non-null and an instance of ServerSessionDecoder"); // first validate our content type //ValidateContentType(connection, decoder); UpgradeState upgradeState = UpgradeState.None; // next read any potential upgrades and finish consuming the preamble ReadOnlySequence <byte> buffer = ReadOnlySequence <byte> .Empty; while (true) { if (buffer.Length == 0 && CanReadAndDecode(upgradeState)) { System.IO.Pipelines.ReadResult readResult = await connection.Input.ReadAsync(); buffer = readResult.Buffer; if (readResult.IsCompleted) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(decoder.CreatePrematureEOFException()); } } while (true) { if (CanReadAndDecode(upgradeState)) { Fx.Assert(buffer.Length > 0, "There must be something in the buffer to decode"); int bytesDecoded = decoder.Decode(buffer); if (bytesDecoded > 0) { buffer = buffer.Slice(bytesDecoded); if (buffer.Length == 0) { connection.Input.AdvanceTo(buffer.Start); } } } switch (decoder.CurrentState) { case ServerSingletonDecoder.State.UpgradeRequest: switch (upgradeState) { case UpgradeState.None: //change the state so that we don't read/decode until it is safe ChangeUpgradeState(ref upgradeState, UpgradeState.VerifyingUpgradeRequest); break; case UpgradeState.VerifyingUpgradeRequest: if (connection.StreamUpgradeAcceptor == null) { await connection.SendFaultAsync(FramingEncodingString.UpgradeInvalidFault, timeoutHelper.RemainingTime(), TransportDefaults.MaxDrainSize); throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( new ProtocolException(SR.Format(SR.UpgradeRequestToNonupgradableService, decoder.Upgrade))); } if (!connection.StreamUpgradeAcceptor.CanUpgrade(decoder.Upgrade)) { await connection.SendFaultAsync(FramingEncodingString.UpgradeInvalidFault, timeoutHelper.RemainingTime(), TransportDefaults.MaxDrainSize); throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ProtocolException(SR.Format(SR.UpgradeProtocolNotSupported, decoder.Upgrade))); } ChangeUpgradeState(ref upgradeState, UpgradeState.WritingUpgradeAck); // accept upgrade await connection.Output.WriteAsync(ServerSingletonEncoder.UpgradeResponseBytes, timeoutHelper.GetCancellationToken()); await connection.Output.FlushAsync(timeoutHelper.GetCancellationToken()); ChangeUpgradeState(ref upgradeState, UpgradeState.UpgradeAckSent); break; case UpgradeState.UpgradeAckSent: // This state was used to capture any extra read bytes into PreReadConnection but we don't need to do that when using pipes. // This extra state transition has been left here to maintain the same state transitions as on .NET Framework to make comparison easier. ChangeUpgradeState(ref upgradeState, UpgradeState.BeginUpgrade); break; case UpgradeState.BeginUpgrade: // Set input pipe so that the next read will return all the unconsumed bytes. // If all bytes have already been consumed so the buffer has 0 length, AdvanceTo would throw // as it's already been called. if (buffer.Length > 0) { connection.Input.AdvanceTo(buffer.Start); } buffer = ReadOnlySequence <byte> .Empty; try { await UpgradeConnectionAsync(connection, decoder.Upgrade); ChangeUpgradeState(ref upgradeState, UpgradeState.EndUpgrade); } catch (Exception exception) { if (Fx.IsFatal(exception)) { throw; } throw; } break; case UpgradeState.EndUpgrade: //Must be a different state here than UpgradeComplete so that we don't try to read from the connection ChangeUpgradeState(ref upgradeState, UpgradeState.UpgradeComplete); break; case UpgradeState.UpgradeComplete: //Client is doing more than one upgrade, reset the state ChangeUpgradeState(ref upgradeState, UpgradeState.VerifyingUpgradeRequest); break; } break; case ServerSingletonDecoder.State.Start: SetupSecurityIfNecessary(connection); if (upgradeState == UpgradeState.UpgradeComplete || //We have done at least one upgrade, but we are now done. upgradeState == UpgradeState.None) //no upgrade, just send the preample end bytes { ChangeUpgradeState(ref upgradeState, UpgradeState.WritingPreambleEnd); // we've finished the preamble. Ack and return. await connection.Output.WriteAsync(ServerSessionEncoder.AckResponseBytes); await connection.Output.FlushAsync(); //terminal state ChangeUpgradeState(ref upgradeState, UpgradeState.PreambleEndSent); } // If all bytes have already been consumed so the buffer has 0 length, AdvanceTo would throw // as it's already been called. if (buffer.Length > 0) { connection.Input.AdvanceTo(buffer.Start); } success = true; await _next(connection); return; } if (buffer.Length == 0) { break; } } } } finally { if (!success) { connection.Abort(); } } }