2525
2626namespace FirebirdSql . Data . Client . Managed ;
2727
28- sealed class FirebirdNetworkHandlingWrapper : IDataProvider , ITracksIOFailure
28+ sealed class FirebirdNetworkHandlingWrapper : IDataProvider , ITracksIOFailure , IDisposable
2929{
3030 public const string CompressionName = "zlib" ;
3131 public const string EncryptionName = "Arc4" ;
@@ -46,19 +46,23 @@ sealed class FirebirdNetworkHandlingWrapper : IDataProvider, ITracksIOFailure
4646 Org . BouncyCastle . Crypto . Engines . RC4Engine _decryptor ;
4747 Org . BouncyCastle . Crypto . Engines . RC4Engine _encryptor ;
4848
49+ bool _disposed ;
50+
4951 public FirebirdNetworkHandlingWrapper ( IDataProvider dataProvider )
5052 {
5153 _dataProvider = dataProvider ;
5254
5355 _outputBuffer = new ByteRingBuffer ( PreferredBufferSize ) ;
5456 _inputBuffer = new ByteRingBuffer ( PreferredBufferSize ) ;
5557 _readBuffer = new byte [ PreferredBufferSize ] ;
58+ _disposed = false ;
5659 }
5760
5861 public bool IOFailed { get ; set ; }
5962
6063 public int Read ( byte [ ] buffer , int offset , int count )
6164 {
65+ EnsureNotDisposed ( ) ;
6266 if ( count <= 0 )
6367 return 0 ;
6468
@@ -92,6 +96,7 @@ public int Read(byte[] buffer, int offset, int count)
9296
9397 public int Read ( Span < byte > buffer , int offset , int count )
9498 {
99+ EnsureNotDisposed ( ) ;
95100 if ( count <= 0 )
96101 return 0 ;
97102
@@ -119,6 +124,7 @@ public int Read(Span<byte> buffer, int offset, int count)
119124
120125 public async ValueTask < int > ReadAsync ( byte [ ] buffer , int offset , int count , CancellationToken cancellationToken = default )
121126 {
127+ EnsureNotDisposed ( ) ;
122128 if ( count <= 0 )
123129 return 0 ;
124130
@@ -152,6 +158,7 @@ public async ValueTask<int> ReadAsync(byte[] buffer, int offset, int count, Canc
152158
153159 public async ValueTask < int > ReadAsync ( Memory < byte > buffer , int offset , int count , CancellationToken cancellationToken = default )
154160 {
161+ EnsureNotDisposed ( ) ;
155162 if ( count <= 0 )
156163 return 0 ;
157164
@@ -187,6 +194,7 @@ public async ValueTask<int> ReadAsync(Memory<byte> buffer, int offset, int count
187194
188195 public void Write ( ReadOnlySpan < byte > buffer )
189196 {
197+ EnsureNotDisposed ( ) ;
190198 if ( buffer . IsEmpty )
191199 return ;
192200
@@ -209,6 +217,7 @@ public void Write(ReadOnlySpan<byte> buffer)
209217
210218 public void Write ( byte [ ] buffer , int offset , int count )
211219 {
220+ EnsureNotDisposed ( ) ;
212221 if ( buffer == null || count <= 0 )
213222 return ;
214223
@@ -230,6 +239,7 @@ public void Write(byte[] buffer, int offset, int count)
230239 }
231240 public ValueTask WriteAsync ( byte [ ] buffer , int offset , int count , CancellationToken cancellationToken = default )
232241 {
242+ EnsureNotDisposed ( ) ;
233243 if ( buffer == null || count <= 0 )
234244 return ValueTask . CompletedTask ;
235245
@@ -257,6 +267,7 @@ async ValueTask WriteDirectAsync(byte[] directBuffer, int directOffset, int dire
257267
258268 public ValueTask WriteAsync ( ReadOnlyMemory < byte > buffer , int offset , int count , CancellationToken cancellationToken = default )
259269 {
270+ EnsureNotDisposed ( ) ;
260271 if ( count <= 0 )
261272 return ValueTask . CompletedTask ;
262273
@@ -284,6 +295,7 @@ async ValueTask WriteDirectAsync(ReadOnlyMemory<byte> directBuffer, int directOf
284295
285296 public void Flush ( )
286297 {
298+ EnsureNotDisposed ( ) ;
287299 try
288300 {
289301 if ( _compressor != null )
@@ -305,6 +317,7 @@ public void Flush()
305317 }
306318 public async ValueTask FlushAsync ( CancellationToken cancellationToken = default )
307319 {
320+ EnsureNotDisposed ( ) ;
308321 try
309322 {
310323 if ( _compressor != null )
@@ -327,19 +340,22 @@ public async ValueTask FlushAsync(CancellationToken cancellationToken = default)
327340
328341 public void StartCompression ( )
329342 {
343+ EnsureNotDisposed ( ) ;
330344 _compressionBuffer = new byte [ PreferredBufferSize ] ;
331345 _compressor = new Ionic . Zlib . ZlibCodec ( Ionic . Zlib . CompressionMode . Compress ) ;
332346 _decompressor = new Ionic . Zlib . ZlibCodec ( Ionic . Zlib . CompressionMode . Decompress ) ;
333347 }
334348
335349 public void StartEncryption ( byte [ ] key )
336350 {
351+ EnsureNotDisposed ( ) ;
337352 _encryptor = CreateCipher ( key ) ;
338353 _decryptor = CreateCipher ( key ) ;
339354 }
340355
341356 void FillInputBuffer ( )
342357 {
358+ EnsureNotDisposed ( ) ;
343359 try
344360 {
345361 if ( _decompressor == null )
@@ -380,6 +396,7 @@ void FillInputBuffer()
380396
381397 async ValueTask FillInputBufferAsync ( CancellationToken cancellationToken )
382398 {
399+ EnsureNotDisposed ( ) ;
383400 try
384401 {
385402 if ( _decompressor == null )
@@ -420,6 +437,7 @@ async ValueTask FillInputBufferAsync(CancellationToken cancellationToken)
420437
421438 int HandleDecompression ( byte [ ] buffer , int count )
422439 {
440+ EnsureNotDisposed ( ) ;
423441 _decompressor . InputBuffer = buffer ;
424442 _decompressor . NextOut = 0 ;
425443 _decompressor . NextIn = 0 ;
@@ -448,6 +466,7 @@ static void ResizeBuffer(ref byte[] buffer)
448466
449467 void FlushPlain ( )
450468 {
469+ EnsureNotDisposed ( ) ;
451470 _outputBuffer . GetReadSegments ( out var off1 , out var len1 , out var off2 , out var len2 ) ;
452471
453472 try
@@ -481,6 +500,7 @@ void FlushPlain()
481500
482501 async ValueTask FlushPlainAsync ( CancellationToken cancellationToken )
483502 {
503+ EnsureNotDisposed ( ) ;
484504 _outputBuffer . GetReadSegments ( out var off1 , out var len1 , out var off2 , out var len2 ) ;
485505
486506 try
@@ -514,6 +534,7 @@ async ValueTask FlushPlainAsync(CancellationToken cancellationToken)
514534
515535 void FlushCompressed ( )
516536 {
537+ EnsureNotDisposed ( ) ;
517538 _outputBuffer . GetReadSegments ( out var off1 , out var len1 , out var off2 , out var len2 ) ;
518539 try
519540 {
@@ -535,6 +556,7 @@ void FlushCompressed()
535556
536557 async ValueTask FlushCompressedAsync ( CancellationToken cancellationToken )
537558 {
559+ EnsureNotDisposed ( ) ;
538560 _outputBuffer . GetReadSegments ( out var off1 , out var len1 , out var off2 , out var len2 ) ;
539561 try
540562 {
@@ -556,6 +578,7 @@ async ValueTask FlushCompressedAsync(CancellationToken cancellationToken)
556578
557579 void DeflateAndWrite ( byte [ ] input , int offset , int count , Ionic . Zlib . FlushType flushType )
558580 {
581+ EnsureNotDisposed ( ) ;
559582 _compressor . InputBuffer = input ;
560583 _compressor . NextIn = offset ;
561584 _compressor . AvailableBytesIn = count ;
@@ -589,6 +612,7 @@ void DeflateAndWrite(byte[] input, int offset, int count, Ionic.Zlib.FlushType f
589612
590613 async ValueTask DeflateAndWriteAsync ( byte [ ] input , int offset , int count , Ionic . Zlib . FlushType flushType , CancellationToken cancellationToken )
591614 {
615+ EnsureNotDisposed ( ) ;
592616 _compressor . InputBuffer = input ;
593617 _compressor . NextIn = offset ;
594618 _compressor . AvailableBytesIn = count ;
@@ -627,11 +651,34 @@ static Org.BouncyCastle.Crypto.Engines.RC4Engine CreateCipher(byte[] key)
627651 return cipher ;
628652 }
629653
630- sealed class ByteRingBuffer
654+ public void Dispose ( )
655+ {
656+ if ( _disposed )
657+ return ;
658+ _disposed = true ;
659+
660+ _inputBuffer . Dispose ( ) ;
661+ _outputBuffer . Dispose ( ) ;
662+
663+ _compressionBuffer = null ;
664+ _compressor = null ;
665+ _decompressor = null ;
666+ _decryptor = null ;
667+ _encryptor = null ;
668+ }
669+
670+ void EnsureNotDisposed ( )
671+ {
672+ if ( _disposed )
673+ throw new ObjectDisposedException ( nameof ( FirebirdNetworkHandlingWrapper ) ) ;
674+ }
675+
676+ sealed class ByteRingBuffer : IDisposable
631677 {
632678 byte [ ] _buffer ;
633679 int _head ;
634680 int _count ;
681+ bool _disposed ;
635682
636683 public byte [ ] Buffer => _buffer ;
637684 public int Count => _count ;
@@ -641,10 +688,35 @@ public ByteRingBuffer(int initialCapacity)
641688 _buffer = ArrayPool < byte > . Shared . Rent ( initialCapacity ) ;
642689 _head = 0 ;
643690 _count = 0 ;
691+ _disposed = false ;
692+ }
693+
694+ public void Dispose ( )
695+ {
696+ if ( _disposed )
697+ return ;
698+ _disposed = true ;
699+
700+ var buffer = _buffer ;
701+ _buffer = Array . Empty < byte > ( ) ;
702+ _head = 0 ;
703+ _count = 0 ;
704+
705+ if ( buffer . Length > 0 )
706+ {
707+ ArrayPool < byte > . Shared . Return ( buffer ) ;
708+ }
709+ }
710+
711+ void EnsureNotDisposed ( )
712+ {
713+ if ( _disposed )
714+ throw new ObjectDisposedException ( nameof ( ByteRingBuffer ) ) ;
644715 }
645716
646717 public void EnsureFree ( int bytes )
647718 {
719+ EnsureNotDisposed ( ) ;
648720 if ( bytes <= 0 )
649721 return ;
650722
@@ -657,6 +729,7 @@ public void EnsureFree(int bytes)
657729
658730 void Grow ( int requiredCapacity )
659731 {
732+ EnsureNotDisposed ( ) ;
660733 var newCapacity = _buffer . Length ;
661734 while ( newCapacity < requiredCapacity )
662735 {
@@ -682,6 +755,7 @@ void Grow(int requiredCapacity)
682755
683756 public void Write ( ReadOnlySpan < byte > src )
684757 {
758+ EnsureNotDisposed ( ) ;
685759 if ( src . IsEmpty )
686760 return ;
687761
@@ -702,6 +776,7 @@ public void Write(ReadOnlySpan<byte> src)
702776
703777 public int CopyTo ( Span < byte > dst )
704778 {
779+ EnsureNotDisposed ( ) ;
705780 if ( dst . IsEmpty || _count == 0 )
706781 return 0 ;
707782
@@ -719,6 +794,7 @@ public int CopyTo(Span<byte> dst)
719794
720795 public void Consume ( int bytes )
721796 {
797+ EnsureNotDisposed ( ) ;
722798 if ( bytes <= 0 )
723799 return ;
724800
@@ -735,6 +811,7 @@ public void Consume(int bytes)
735811
736812 public void GetReadSegments ( out int offset1 , out int length1 , out int offset2 , out int length2 )
737813 {
814+ EnsureNotDisposed ( ) ;
738815 if ( _count == 0 )
739816 {
740817 offset1 = offset2 = length1 = length2 = 0 ;
@@ -749,6 +826,7 @@ public void GetReadSegments(out int offset1, out int length1, out int offset2, o
749826
750827 public void GetWriteSegment ( out int offset , out int length )
751828 {
829+ EnsureNotDisposed ( ) ;
752830 if ( _count == _buffer . Length )
753831 {
754832 offset = 0 ;
@@ -763,6 +841,7 @@ public void GetWriteSegment(out int offset, out int length)
763841
764842 public void AdvanceWrite ( int bytes )
765843 {
844+ EnsureNotDisposed ( ) ;
766845 if ( bytes <= 0 )
767846 return ;
768847
0 commit comments