Exemple #1
0
        PipeFilterResult DoFilter_BeforeWriting(ref SmartBuffer buffer, SortedSet <PipeFilter> filters, CancellationToken cancellationToken)
        {
            PipeFilterResult rt = default;

            foreach (var f in filters)
            {
                _logger?.LogInformation($"DefaultPipe DoFilter_BeforeWriting {f.ToString()}...");
                PipeFilterContext ctx = new PipeFilterContext(f.Client, buffer.Memory, buffer.SignificantLength);
                try
                {
                    rt = f.BeforeWriting(ctx);
                    if (!rt.Continue || cancellationToken.IsCancellationRequested)
                    {
                        buffer.Dispose();
                        rt.Buffer?.Dispose();
                        break;
                    }
                    buffer.Dispose();
                    buffer = rt.Buffer;
                    //next filter
                }
                catch (Exception ex)
                {
                    _logger?.LogError(ex, $"DefaultPipe DoFilter_BeforeWriting {f.ToString()} error.");
                    buffer.Dispose();
                    rt = new PipeFilterResult(ctx.Client, null, false);
                    break;
                }
            }

            return(rt);
        }
        PipeFilterResult ExecuteFilter_BeforeWriting(IClient client, SmartBuffer memory, SortedSet <PipeFilter> filters, CancellationToken cancellationToken)
        {
            SmartBuffer prevFilterMemory = memory;
            bool        @continue        = true;

            foreach (var filter in filters.Reverse())
            {
                try
                {
                    var result = filter.BeforeWriting(new PipeFilterContext(client, prevFilterMemory.SignificanMemory));
                    prevFilterMemory.Dispose();
                    prevFilterMemory = result.Buffer;
                    @continue        = result.Continue;
                    if (!result.Continue)
                    {
                        break;
                    }
                    if (cancellationToken.IsCancellationRequested)
                    {
                        break;
                    }
                }
                catch (Exception ex)
                {
                    @continue = false;
                    _logger?.LogError(ex, $"ExecuteFilter_BeforeWriting [{client.EndPoint.ToString()}].");
                }
            }
            return(new PipeFilterResult(client, prevFilterMemory, @continue));
        }
        /// <summary>
        /// Write to the client.
        /// </summary>
        /// <param name="data"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async ValueTask <WriteResult> Write(ReadOnlyMemory <byte> data, CancellationToken cancellationToken)
        {
            if (data.IsEmpty)
            {
                _logger?.LogWarning($"PipeWriter Try to write empty memory. [{Client.EndPoint.ToString()}].");
                return(new WriteResult(Failed, 0));
            }

            ReadOnlyMemory <byte> toWrite            = data;
            SmartBuffer           filterResultBuffer = null;

            if (FilterEnabled && FilterChain.Count > 0)
            {
                var result = ExecuteFilter(data, cancellationToken);
                if (!result.Continue)
                {
                    result.Buffer?.Dispose();
                    _logger?.LogInformation($"Pipe broke by filter [{Client.EndPoint.ToString()}].");
                    return(new WriteResult(BrokeByFilter, 0));
                }
                else
                {
                    filterResultBuffer = result.Buffer;
                    toWrite            = null != filterResultBuffer ? filterResultBuffer.SignificantMemory : ReadOnlyMemory <byte> .Empty;
                }
            }
            _logger?.LogInformation($"{toWrite.Length} bytes left after [OnWriting] filtering.");
            if (!toWrite.IsEmpty)
            {
                int written = await Client.WriteAsync(toWrite, cancellationToken);

                filterResultBuffer?.Dispose();

                if (0 >= written)
                {
                    return(new WriteResult(Failed, written));
                }
                else
                {
                    return(new WriteResult(Succeeded, written));
                }
            }
            else
            {
                return(new WriteResult(Succeeded, 0));
            }
        }
        /// <summary>
        /// Execute filters.
        /// </summary>
        /// <param name="data"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        protected ClientFilterResult ExecuteFilter(ReadOnlyMemory <byte> data, CancellationToken cancellationToken)
        {
            SmartBuffer prevFilterMemory = null;
            bool        @continue        = true;
            int         time             = 0;

            foreach (var filter in FilterChain)
            {
                try
                {
                    if (time > 0 && null == prevFilterMemory)
                    {
                        @continue = true; break;
                    }
                    var result = filter.OnReading(new ClientFilterContext(Client, null == prevFilterMemory ? data : prevFilterMemory.SignificantMemory));
                    time++;
                    prevFilterMemory?.Dispose();
                    prevFilterMemory = result.Buffer;
                    @continue        = result.Continue;
                    if (!result.Continue)
                    {
                        break;
                    }
                    if (cancellationToken.IsCancellationRequested)
                    {
                        break;
                    }
                }
                catch (Exception ex)
                {
                    @continue = false;
                    _logger?.LogError(ex, $"PipeReader ExecuteFilter_OnReading [{Client.EndPoint.ToString()}].");
                }
            }
            return(new ClientFilterResult(Client, prevFilterMemory, @continue));
        }
        /// <summary>
        /// Execute filters.
        /// </summary>
        /// <param name="client"></param>
        /// <param name="data"></param>
        /// <param name="filters"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        ClientFilterResult ExecuteFilter_BeforeWriting(IClient client, ReadOnlyMemory <byte> data, SortedSet <IClientWriterFilter> filters, CancellationToken cancellationToken)
        {
            SmartBuffer prevFilterMemory = null;
            bool        @continue        = true;
            int         time             = 0;

            foreach (var filter in filters.Reverse())//emm
            {
                try
                {
                    if (time > 0 && null == prevFilterMemory)
                    {
                        @continue = true; break;
                    }
                    var result = filter.BeforeWriting(new ClientFilterContext(client, null == prevFilterMemory ? data : prevFilterMemory.SignificantMemory));
                    time++;
                    prevFilterMemory?.Dispose();
                    prevFilterMemory = result.Buffer;
                    @continue        = result.Continue;
                    if (!result.Continue)
                    {
                        break;
                    }
                    if (cancellationToken.IsCancellationRequested)
                    {
                        break;
                    }
                }
                catch (Exception ex)
                {
                    @continue = false;
                    _logger?.LogError(ex, $"ExecuteFilter_BeforeWriting [{client.EndPoint.ToString()}].");
                }
            }
            return(new ClientFilterResult(client, prevFilterMemory, @continue));
        }
Exemple #6
0
        async Task PipeB2A(CancellationToken cancellationToken)
        {
            SmartBuffer buffer = SmartBuffer.Rent(_bufferSize);//read buff

            buffer.SignificantLength = await ClientB.ReadAsync(buffer.Memory, cancellationToken);


            if (buffer.SignificantLength > 0)
            {
                if (_filtersB.Count > 0)
                {
                    bool locked = false;
                    try
                    {
                        DoFilter_Lock(ref locked);

                        PipeFilterResult filterResult = DoFilter_AfterReading(ref buffer, _filtersB, cancellationToken);
                        if (!filterResult.Continue || cancellationToken.IsCancellationRequested)
                        {
                            ReportBroken();
                            return;
                        }
                        else
                        {
                            buffer = filterResult.Buffer;
                        }

                        DoFilter_UnLock(ref locked);
                    }
                    finally
                    {
                        DoFilter_UnLock(ref locked);
                    }
                }//end FilterB
                if (_filtersA.Count > 0)
                {
                    bool locked = false;
                    try
                    {
                        DoFilter_Lock(ref locked);

                        PipeFilterResult filterResult = DoFilter_BeforeWriting(ref buffer, _filtersA, cancellationToken);
                        if (!filterResult.Continue || cancellationToken.IsCancellationRequested)
                        {
                            ReportBroken();
                            return;
                        }
                        else
                        {
                            buffer = filterResult.Buffer;
                        }

                        DoFilter_UnLock(ref locked);
                    }
                    finally
                    {
                        DoFilter_UnLock(ref locked);
                    }
                }//end FilterA

                int written = await ClientA.WriteAsync(buffer.Memory, cancellationToken);//Pipe

                _logger?.LogInformation($"DefaultPipe Pipe B to A {written} bytes.");
                if (written < 0)
                {
                    ClientA.Close();
                    buffer.Dispose();
                    ReportBroken();
                    return;
                }
            }
            else if (0 == buffer.SignificantLength)
            {
                _logger?.LogInformation($"DefaultPipe read = 0.");
            }
            else//<0
            {
                _logger?.LogInformation($"DefaultPipe error, read={buffer.SignificantLength}.");
                ClientB.Close();
                ReportBroken();
                return;
            }


            buffer.Dispose();//free memory.

            if (!cancellationToken.IsCancellationRequested)
            {
                await PipeB2A(cancellationToken);//continue.
            }
        }