private static async Task PongServer(IPipeConnection connection) { while (true) { var result = await connection.Input.ReadAsync(); var inputBuffer = result.Buffer; if (inputBuffer.IsEmpty && result.IsCompleted) { connection.Input.Advance(inputBuffer.End); break; } if (inputBuffer.Length < 4) { connection.Input.Advance(inputBuffer.Start, inputBuffer.End); } else { bool isPing = inputBuffer.Equals(_ping); if (isPing) { await connection.Output.WriteAsync(_pong); } else { break; } connection.Input.Advance(inputBuffer.End); } } }
static async Task DoTheThingViaPipelines(string host, int port, string password, bool useTls, string certificateFile) { try { await Console.Out.WriteLineAsync(ShowDetails?$"resolving ip of '{host}'..." : "resolving ip of host"); var ip = (await Dns.GetHostAddressesAsync(host)).First(); await Console.Out.WriteLineAsync(ShowDetails?$"connecting to '{ip}:{port}'..." : "connecting to host"); using (var socket = await SocketConnection.ConnectAsync(new IPEndPoint(ip, port))) { IPipeConnection connection = socket; if (useTls) // need to think about the disposal story here? { connection = await Leto.TlsPipeline.AuthenticateClient(connection, new Leto.ClientOptions() { CertificateFile = certificateFile }); } await ExecuteWithTimeout(connection, password); } } catch (Exception ex) { await Console.Error.WriteLineAsync(ex.Message); } }
private static async Task WriteChunkedBody(this IPipeConnection connection, HttpContext context) { while (true) { var buffer = connection.Output.Alloc(); try { buffer.Ensure(1024); var bookMark = buffer.Memory; buffer.Advance(3); buffer.Write(HttpConsts.EndOfLine); if (!buffer.Memory.TryGetArray(out ArraySegment <byte> byteArray)) { throw new NotImplementedException(); } var bytesWritten = await context.Request.Body.ReadAsync(byteArray.Array, byteArray.Offset, byteArray.Count); if (bytesWritten == 0) { Encoding.ASCII.GetBytes("000").CopyTo(bookMark.Span); buffer.Write(HttpConsts.EndOfLine); return; } Encoding.ASCII.GetBytes($"{bytesWritten:XXX}").CopyTo(bookMark.Span); buffer.Advance(bytesWritten); buffer.Write(HttpConsts.EndOfLine); } finally { await buffer.FlushAsync(); } } }
public RedisConnection(IPipeConnection connection, IPEndPoint serverEndpoint, int database) { _connection = connection; Database = database; ServerEndPoint = serverEndpoint; IsDatabaseSelected = false; }
private static async Task Execute(IPipeConnection connection, string password) { await Console.Out.WriteLineAsync($"executing..."); if (password != null) { await WriteSimpleMessage(connection.Output, $"AUTH \"{password}\""); // a "success" for this would be a response that says "+OK" } await WriteSimpleMessage(connection.Output, "ECHO \"noisy in here\""); // note that because of RESP, this actually gives 2 replies; don't worry about it :) await WriteSimpleMessage(connection.Output, "PING"); var input = connection.Input; while (true) { await Console.Out.WriteLineAsync($"awaiting response..."); var result = await input.ReadAsync(); await Console.Out.WriteLineAsync($"checking response..."); var buffer = result.Buffer; if (buffer.IsEmpty && result.IsCompleted) { await Console.Out.WriteLineAsync($"done"); break; } if (!buffer.TrySliceTo((byte)'\r', (byte)'\n', out var slice, out var cursor)) { await Console.Out.WriteLineAsync($"incomplete"); input.Advance(buffer.Start, buffer.End); continue; } var reply = slice.GetAsciiString(); await Console.Out.WriteLineAsync($"<< received: '{reply}'"); if (string.Equals(reply, "+PONG", StringComparison.OrdinalIgnoreCase)) { await WriteSimpleMessage(connection.Output, "QUIT"); connection.Output.Complete(); } // input.Advance(cursor); // feels like this should work, but it doesn't var incTerminator = buffer.Slice(0, slice.Length + 2); input.Advance(incTerminator.End, incTerminator.End); } }
static async Task <Tuple <int, int, int> > PingClient(IPipeConnection connection, int messagesToSend) { ArraySegment <byte> _ping = new ArraySegment <byte>(Encoding.ASCII.GetBytes("PING")); ArraySegment <byte> _pong = new ArraySegment <byte>(Encoding.ASCII.GetBytes("PING")); int count = 0; var watch = Stopwatch.StartNew(); int sendCount = 0, replyCount = 0; for (int i = 0; i < messagesToSend; i++) { await connection.Output.WriteAsync(_ping); sendCount++; bool havePong = false; while (true) { var result = await connection.Input.ReadAsync(); var inputBuffer = result.Buffer; if (inputBuffer.IsEmpty && result.IsCompleted) { connection.Input.Advance(inputBuffer.End); break; } if (inputBuffer.Length < 4) { connection.Input.Advance(inputBuffer.Start, inputBuffer.End); } else { havePong = inputBuffer.EqualsTo(_ping); if (havePong) { count++; } connection.Input.Advance(inputBuffer.End); break; } } if (havePong) { replyCount++; } else { break; } } connection.Input.Complete(); connection.Output.Complete(); watch.Stop(); // Task.Run here so that we're not on the UV thread when we complete return(await Task.Run(() => Tuple.Create(sendCount, replyCount, (int)watch.ElapsedMilliseconds))); }
private static async Task ExecuteWithTimeout(IPipeConnection connection, string password, int timeoutMilliseconds = 5000) { var timeout = Task.Delay(timeoutMilliseconds); var success = Execute(connection, password); var winner = await Task.WhenAny(success, timeout); await Console.Out.WriteLineAsync(winner == success? "(complete)" : "(timeout)"); }
public IAppSession Create(IPipeConnection pipeConnection) { var session = new AppSession <TPackageInfo>(new TPipelineFilter()); session.Initialize(pipeConnection); session.PackageReceived += _packageHandler; return(session); }
public LoopbackPipeline(PipeOptions factory) { var backPipeline1 = new Pipe(factory); var backPipeline2 = new Pipe(factory); _clientPipeline = new TestPipeline(backPipeline1, backPipeline2); _serverPipeline = new TestPipeline(backPipeline2, backPipeline1); }
public static async Task <TlsClientPipeline> AuthenticateClient(IPipeConnection inputPipe, ClientOptions clientOptions) { var ctx = Interop.OpenSsl.SSL_CTX_new(Interop.OpenSsl.TLS_client_method()); var pipeline = new TlsClientPipeline(inputPipe, ctx, clientOptions); await pipeline.AuthenticateAsync(); return(pipeline); }
public LoopbackPipeline(PipeFactory factory) { var backPipeline1 = factory.Create(); var backPipeline2 = factory.Create(); _clientPipeline = new TestPipeline(backPipeline1, backPipeline2); _serverPipeline = new TestPipeline(backPipeline2, backPipeline1); }
private async Task OnConnection(IPipeConnection connection) { using (connection) { WebSocketConnection socket = null; try { WriteStatus(ConnectionType.Server, "Connected"); WriteStatus(ConnectionType.Server, "Parsing http request..."); var request = await ParseHttpRequest(connection.Input); try { WriteStatus(ConnectionType.Server, "Identifying protocol..."); socket = GetProtocol(connection, ref request); WriteStatus(ConnectionType.Server, $"Protocol: {WebSocketProtocol.Name}"); WriteStatus(ConnectionType.Server, "Authenticating..."); if (!await OnAuthenticateAsync(socket, ref request.Headers)) { throw new InvalidOperationException("Authentication refused"); } WriteStatus(ConnectionType.Server, "Completing handshake..."); await WebSocketProtocol.CompleteServerHandshakeAsync(ref request, socket); } finally { request.Dispose(); // can't use "ref request" or "ref headers" otherwise } WriteStatus(ConnectionType.Server, "Handshake complete hook..."); await OnHandshakeCompleteAsync(socket); connections.TryAdd(socket, socket); WriteStatus(ConnectionType.Server, "Processing incoming frames..."); await socket.ProcessIncomingFramesAsync(this); WriteStatus(ConnectionType.Server, "Exiting..."); await socket.CloseAsync(); } catch (Exception ex) {// meh, bye bye broken connection try { socket?.Dispose(); } catch { } WriteStatus(ConnectionType.Server, ex.StackTrace); WriteStatus(ConnectionType.Server, ex.GetType().Name); WriteStatus(ConnectionType.Server, ex.Message); } finally { WebSocketConnection tmp; if (socket != null) { connections.TryRemove(socket, out tmp); } try { connection.Output.Complete(); } catch { } try { connection.Input.Complete(); } catch { } } } }
private Task HandleNewClient(IPipeConnection connection) { Interlocked.Increment(ref _sessionCount); var session = _appSessionFactory.Create(connection); session.Closed += OnSessionClosed; Task.Run(async() => await ProcessRequest(session)); return(Task.CompletedTask); }
public AdaptedPipeline(IPipeConnection transport, IPipeConnection application, IPipe inputPipe, IPipe outputPipe) { _transport = transport; _application = application; Input = inputPipe; Output = outputPipe; }
static async Task <Tuple <int, int, int> > PingClient(IPipeConnection connection, int messagesToSend) { int count = 0; var watch = Stopwatch.StartNew(); int sendCount = 0, replyCount = 0; for (int i = 0; i < messagesToSend; i++) { await connection.Output.WriteAsync(_ping); sendCount++; bool havePong = false; while (true) { var result = await connection.Input.ReadAsync(); var inputBuffer = result.Buffer; if (inputBuffer.IsEmpty && result.IsCompleted) { connection.Input.Advance(inputBuffer.End); break; } if (inputBuffer.Length < 4) { connection.Input.Advance(inputBuffer.Start, inputBuffer.End); } else { havePong = inputBuffer.Equals(_ping); if (havePong) { count++; } connection.Input.Advance(inputBuffer.End); break; } } if (havePong) { replyCount++; } else { break; } } connection.Input.Complete(); connection.Output.Complete(); watch.Stop(); return(Tuple.Create(sendCount, replyCount, (int)watch.ElapsedMilliseconds)); }
public SecurePipelineConnection(IPipeConnection pipeline, PipeFactory factory, SecurePipeListener listener, ILogger <SecurePipelineConnection> logger) { _logger = logger; _listener = listener; _lowerConnection = pipeline; _outputPipe = factory.Create(); _inputPipe = factory.Create(); _handshakePipe = factory.Create(); _state = new ServerStateTls12(_listener, _logger); StartReading(); }
public void Dispose() { lock (_lock) { _logger?.LogTrace("Disposed connection"); _lowerConnection?.Dispose(); _state?.Dispose(); _lowerConnection = null; _state = null; GC.SuppressFinalize(this); } }
public static Task WriteBodyAsync(this IPipeConnection connection, HttpContext context) { if (context.Request.Headers["Transfer-Encoding"] == "chunked") { return(connection.WriteChunkedBody(context)); } if (context.Request.ContentLength > 0) { return(connection.WriteBody(context)); } return(_cachedTask); }
private Http2Connection CreateHttp2Connection(IPipeConnection transport, IPipeConnection application) { return(new Http2Connection(new Http2ConnectionContext { ConnectionId = _context.ConnectionId, ServiceContext = _context.ServiceContext, ConnectionFeatures = _context.ConnectionFeatures, MemoryPool = MemoryPool, LocalEndPoint = LocalEndPoint, RemoteEndPoint = RemoteEndPoint, Application = application, Transport = transport })); }
internal SecurePipeConnection(IPipeConnection connection, SecurePipeOptions securePipeOptions, IConnectionState connectionState) { RecordHandler = new GeneralRecordHandler(null, TlsVersion.Tls1, connection.Output); _securePipeOptions = securePipeOptions; _inputPipe = new Pipe(securePipeOptions.PipeOptions); _outputPipe = new Pipe(securePipeOptions.PipeOptions); _connection = connection; _state = connectionState; _state.Connection = this; _handshakeInput = new Pipe(securePipeOptions.PipeOptions); _handshakeOutput = new Pipe(securePipeOptions.PipeOptions); RecordHandler = new GeneralRecordHandler(_state, TlsVersion.Tls12, _connection.Output); var ignore = ReadingLoop(); }
private Http1Connection CreateHttp1Connection(IPipeConnection transport, IPipeConnection application) { return(new Http1Connection(new Http1ConnectionContext { ConnectionId = _context.ConnectionId, ConnectionFeatures = _context.ConnectionFeatures, BufferPool = BufferPool, LocalEndPoint = LocalEndPoint, RemoteEndPoint = RemoteEndPoint, ServiceContext = _context.ServiceContext, TimeoutControl = this, Transport = transport, Application = application })); }
internal TlsClientPipeline(IPipeConnection inputPipe, SSL_CTX context, ClientOptions clientOptions) { _innerConnection = inputPipe; _readInnerPipe = new Pipe(new PipeOptions(System.Buffers.MemoryPool.Default)); _writeInnerPipe = new Pipe(new PipeOptions(System.Buffers.MemoryPool.Default)); _context = context; _ssl = SSL_new(_context); _clientOptions = clientOptions; _readBio = s_ReadBio.New(); _writeBio = s_WriteBio.New(); SSL_set0_rbio(_ssl, _readBio); SSL_set0_wbio(_ssl, _writeBio); SSL_set_connect_state(_ssl); }
private static async Task WriteBody(this IPipeConnection connection, HttpContext context) { var bytesToWrite = context.Request.ContentLength.Value; while (bytesToWrite > 0) { var buffer = connection.Output.Alloc(1024); if (!buffer.Memory.TryGetArray(out ArraySegment <byte> byteArray)) { throw new NotImplementedException(); } var byteCount = await context.Request.Body.ReadAsync(byteArray.Array, byteArray.Offset, byteArray.Count); buffer.Advance(byteCount); bytesToWrite -= byteCount; await buffer.FlushAsync(); } }
public static async Task ReceiveHeaderAsync(this IPipeConnection connection, HttpContext context) { var finished = false; while (true) { var reader = await connection.Input.ReadAsync(); var buffer = reader.Buffer; try { if (!buffer.TrySliceTo(HttpConsts.HeadersEnd, out ReadableBuffer currentSlice, out ReadCursor cursor)) { continue; } buffer = buffer.Slice(cursor).Slice(HttpConsts.HeadersEnd.Length); //first line if (!currentSlice.TrySliceTo(HttpConsts.EndOfLine, out ReadableBuffer currentLine, out cursor)) { throw new InvalidOperationException(); } context.Response.StatusCode = int.Parse(currentLine.Split(HttpConsts.Space[0]).Skip(1).First().GetAsciiString()); currentSlice = currentSlice.Slice(cursor).Slice(HttpConsts.EndOfLine.Length); while (currentSlice.Length > 0) { cursor = ProcessHeader(context, ref currentSlice); } finished = true; return; } finally { if (finished) { connection.Input.Advance(buffer.Start, buffer.Start); } else { connection.Input.Advance(buffer.Start, buffer.End); } } } }
/// <summary> /// /// </summary> /// <param name="name"></param> /// <param name="cancellationToken"></param> /// <returns></returns> public async Task InitializeAsync(string name, CancellationToken cancellationToken = default) { if (IsFactory) { var client = CreateClient <Message>(name); client.MessageReceived += (_, args) => { if (args.Message == null) { OnExceptionOccurred(new InvalidOperationException("Received null message from server.")); return; } OnMessageReceived(args.Message); }; client.ExceptionOccurred += (_, args) => OnExceptionOccurred(args.Exception); await client.ConnectAsync(cancellationToken).ConfigureAwait(false); InternalConnection = client; } else { var server = CreateServer <Message>(name); server.MessageReceived += (_, args) => { if (args.Message == null) { OnExceptionOccurred(new InvalidOperationException("Received null message from client.")); return; } OnMessageReceived(args.Message); }; server.ExceptionOccurred += (_, args) => OnExceptionOccurred(args.Exception); await server.StartAsync(cancellationToken); InternalConnection = server; } }
private async Task Echo(IPipeConnection connection) { while (true) { var result = await connection.Input.ReadAsync(); var request = result.Buffer; if (request.IsEmpty && result.IsCompleted) { connection.Input.Advance(request.End); break; } var response = connection.Output.Alloc(); response.Append(request); await response.FlushAsync(); connection.Input.Advance(request.End); } }
public Http1ConnectionTests() { _pipelineFactory = new MemoryPool(); var pair = PipeFactory.CreateConnectionPair(_pipelineFactory); _transport = pair.Transport; _application = pair.Application; _serviceContext = new TestServiceContext(); _timeoutControl = new Mock <ITimeoutControl>(); _http1ConnectionContext = new Http1ConnectionContext { ServiceContext = _serviceContext, ConnectionFeatures = new FeatureCollection(), MemoryPool = _pipelineFactory, TimeoutControl = _timeoutControl.Object, Application = pair.Application, Transport = pair.Transport }; _http1Connection = new TestHttp1Connection(_http1ConnectionContext); _http1Connection.Reset(); }
private static async Task Handle(IPipeConnection connection) { while (true) { var result = await connection.Input.ReadAsync(); var request = result.Buffer; if (request.IsEmpty && result.IsCompleted) { connection.Input.Advance(request.End); break; } Console.Out.WriteLine(request.GetUtf8String()); var response = connection.Output.Alloc(); response.Append(request); await response.FlushAsync(); connection.Input.Advance(request.End); } }
private static async Task PongServer(IPipeConnection connection) { ArraySegment <byte> _ping = new ArraySegment <byte>(Encoding.ASCII.GetBytes("PING")); ArraySegment <byte> _pong = new ArraySegment <byte>(Encoding.ASCII.GetBytes("PING")); while (true) { var result = await connection.Input.ReadAsync(); var inputBuffer = result.Buffer; if (inputBuffer.IsEmpty && result.IsCompleted) { connection.Input.Advance(inputBuffer.End); break; } if (inputBuffer.Length < 4) { connection.Input.Advance(inputBuffer.Start, inputBuffer.End); } else { bool isPing = inputBuffer.EqualsTo(_ping); if (isPing) { await connection.Output.WriteAsync(_pong); } else { break; } connection.Input.Advance(inputBuffer.End); } } }
public static WritableBufferAwaitable WriteHeadersAsync(this IPipeConnection connection, HttpContext context, byte[] host) { var writer = connection.Output.Alloc(); writer.Append(context.Request.Method, TextEncoder.Utf8); writer.Write(HttpConsts.Space); writer.Append(context.Request.Path.Value, TextEncoder.Utf8); writer.Write(HttpConsts.Space); writer.Append(context.Request.Protocol, TextEncoder.Utf8); writer.Write(HttpConsts.EndOfLine); foreach (var header in context.Request.Headers) { if (header.Key == "Host" || header.Key == "Connection") { } writer.Append(header.Key, TextEncoder.Utf8); writer.Write(HttpConsts.HeaderSplit); writer.Append(string.Join(", ", header.Value), TextEncoder.Utf8); writer.Write(HttpConsts.EndOfLine); } writer.Write(host); writer.Write(HttpConsts.ConnectionHeaderBytes); return(writer.FlushAsync()); }