internal async Task Run() { var certificate = CertificateBuilder.Build(Attribute.Hostname); var listener = new TcpListener(IPAddress.Loopback, Attribute.Port); listener.Start(); Log.I($"[{Identifier}:{Attribute.Type}] Listening on {Attribute.Hostname}:{Attribute.Port}"); while (true) { // Log.D($"[{Identifier}] Waiting for new connection"); var client = await listener.AcceptTcpClientAsync(); // Log.D($"[{Identifier}] Got connection from {client.Client.RemoteEndPoint}"); var sslStream = new SslStream(client.GetStream(), false); try { await sslStream.AuthenticateAsServerAsync(certificate, false, SslProtocols.Tls12, false); sslStream.ReadTimeout = 5000; sslStream.WriteTimeout = 5000; using (var reader = new StreamReader(sslStream)) { IAsyncEnumerator <byte[]> responses = null; switch (Attribute.Type) { case HandlerType.Http: responses = HandleHttpRequest(reader); break; case HandlerType.Ws: responses = HandleWsRequest(reader); break; } try { await responses.ForEachAsync( async response => await sslStream.WriteAsync(response, 0, response.Length)); } catch (TaskCanceledException) { } } } catch (Exception ex) { Log.Ex(ex, $"Exception occured while handling request on {Identifier} "); } finally { sslStream.Dispose(); client.Close(); } } }
public override IAsyncEnumerator <bool> ConsumeFlow(IAsyncEnumerator <TDroplet> flow) { return(new AsyncEnumerator <bool>(async yield => { await flow.ForEachAsync(async t => { bool stored = await ConsumeDroplet(t); await yield.ReturnAsync(stored); }); })); }
public static async Task UntilAsync <T>(this IAsyncEnumerator <T> e, Func <T, bool> until, AsyncEnumerator <T> .Yield yield = null) { await e.ForEachAsync(t => { if (!until(t)) { if (yield != null) { yield.Break(); } e.Dispose(); } }); }
/// <summary> /// Collects the elements of an IAsyncEnumerator into a regular enumerable. /// </summary> public static async Task <IProducerConsumerCollection <T> > Collect <T>(this IAsyncEnumerator <T> e, int maxCount = 0) { var queue = new ConcurrentQueue <T>(); await e.ForEachAsync(t => { queue.Enqueue(t); if (--maxCount == 0) { e.Dispose(); } }); return(queue); }
/// <summary> /// Pipes an input flow into this component, then returns the piped output flow. /// </summary> public virtual IAsyncEnumerator <TOutput> PipeFlow(IAsyncEnumerator <TInput> flow, Predicate <TOutput> stop = null, int maxDroplets = 0) { // The default implementation is 1-1 dripping, while FlowMachines have a tailored and more efficient nInputs:nOutputs flowing implementation. return(new AsyncEnumerator <TOutput>(async yield => { await flow.ForEachAsync(async t => { await ConsumeDroplet(t); TOutput ret = await Drip(); if (!IsFlowStarted || (stop?.Invoke(ret) ?? false) || --maxDroplets == 0) { yield.Break(); } await yield.ReturnAsync(ret); }); })); }
/// <summary> /// Similar to (and calls) ConsumeFlow, but staunches the flow as soon as a certain droplet is found in the input flow, then starts it again. /// This is a piping tool and should not be used directly by consumers. /// </summary> public static IAsyncEnumerator <bool> ConsumeFlowUntilDroplet <T>(this IFlowConsumer <T> c, IFlowProducer <T> producer, IAsyncEnumerator <T> flow, Predicate <T> stopOn) { return(new AsyncEnumerator <bool>(async yield => { if (producer.IsFlowStarted && producer is FlowProducerBase <T> prodImpl) { await c.ConsumeFlow(new AsyncEnumerator <T>(async innerYield => { await flow.ForEachAsync(async d => { if (stopOn(d)) { innerYield.Break(); } await innerYield.ReturnAsync(d); }); })).UntilAsync(async b => { await yield.ReturnAsync(b); return b; }, yield); } })); }