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)); }
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. } }