summary refs log tree commit diff
path: root/crypto/src/tls/DtlsTransport.cs
diff options
context:
space:
mode:
Diffstat (limited to 'crypto/src/tls/DtlsTransport.cs')
-rw-r--r--crypto/src/tls/DtlsTransport.cs111
1 files changed, 105 insertions, 6 deletions
diff --git a/crypto/src/tls/DtlsTransport.cs b/crypto/src/tls/DtlsTransport.cs
index a41cb7866..033e0af0b 100644
--- a/crypto/src/tls/DtlsTransport.cs
+++ b/crypto/src/tls/DtlsTransport.cs
@@ -1,8 +1,6 @@
 using System;
 using System.IO;
-#if !PORTABLE || DOTNET
 using System.Net.Sockets;
-#endif
 
 namespace Org.BouncyCastle.Tls
 {
@@ -10,10 +8,12 @@ namespace Org.BouncyCastle.Tls
         : DatagramTransport
     {
         private readonly DtlsRecordLayer m_recordLayer;
+        private readonly bool m_ignoreCorruptRecords;
 
-        internal DtlsTransport(DtlsRecordLayer recordLayer)
+        internal DtlsTransport(DtlsRecordLayer recordLayer, bool ignoreCorruptRecords)
         {
-            this.m_recordLayer = recordLayer;
+            m_recordLayer = recordLayer;
+            m_ignoreCorruptRecords = ignoreCorruptRecords;
         }
 
         /// <exception cref="IOException"/>
@@ -37,6 +37,10 @@ namespace Org.BouncyCastle.Tls
                 throw new ArgumentException("invalid offset: " + off, "off");
             if (len < 0 || len > buf.Length - off)
                 throw new ArgumentException("invalid length: " + len, "len");
+
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+            return Receive(buf.AsSpan(off, len), waitMillis);
+#else
             if (waitMillis < 0)
                 throw new ArgumentException("cannot be negative", "waitMillis");
 
@@ -46,6 +50,9 @@ namespace Org.BouncyCastle.Tls
             }
             catch (TlsFatalAlert fatalAlert)
             {
+                if (m_ignoreCorruptRecords && AlertDescription.bad_record_mac == fatalAlert.AlertDescription)
+                    return -1;
+
                 m_recordLayer.Fail(fatalAlert.AlertDescription);
                 throw fatalAlert;
             }
@@ -53,7 +60,6 @@ namespace Org.BouncyCastle.Tls
             {
                 throw e;
             }
-#if !PORTABLE || DOTNET
             catch (SocketException e)
             {
                 if (TlsUtilities.IsTimeout(e))
@@ -62,7 +68,55 @@ namespace Org.BouncyCastle.Tls
                 m_recordLayer.Fail(AlertDescription.internal_error);
                 throw new TlsFatalAlert(AlertDescription.internal_error, e);
             }
+            // TODO[tls-port] Can we support interrupted IO on .NET?
+            //catch (InterruptedIOException e)
+            //{
+            //    throw e;
+            //}
+            catch (IOException e)
+            {
+                m_recordLayer.Fail(AlertDescription.internal_error);
+                throw e;
+            }
+            catch (Exception e)
+            {
+                m_recordLayer.Fail(AlertDescription.internal_error);
+                throw new TlsFatalAlert(AlertDescription.internal_error, e);
+            }
 #endif
+        }
+
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+        /// <exception cref="IOException"/>
+        public virtual int Receive(Span<byte> buffer, int waitMillis)
+        {
+            if (waitMillis < 0)
+                throw new ArgumentException("cannot be negative", nameof(waitMillis));
+
+            try
+            {
+                return m_recordLayer.Receive(buffer, waitMillis);
+            }
+            catch (TlsFatalAlert fatalAlert)
+            {
+                if (m_ignoreCorruptRecords && AlertDescription.bad_record_mac == fatalAlert.AlertDescription)
+                    return -1;
+
+                m_recordLayer.Fail(fatalAlert.AlertDescription);
+                throw fatalAlert;
+            }
+            catch (TlsTimeoutException e)
+            {
+                throw e;
+            }
+            catch (SocketException e)
+            {
+                if (TlsUtilities.IsTimeout(e))
+                    throw e;
+
+                m_recordLayer.Fail(AlertDescription.internal_error);
+                throw new TlsFatalAlert(AlertDescription.internal_error, e);
+            }
             // TODO[tls-port] Can we support interrupted IO on .NET?
             //catch (InterruptedIOException e)
             //{
@@ -79,6 +133,7 @@ namespace Org.BouncyCastle.Tls
                 throw new TlsFatalAlert(AlertDescription.internal_error, e);
             }
         }
+#endif
 
         /// <exception cref="IOException"/>
         public virtual void Send(byte[] buf, int off, int len)
@@ -90,6 +145,9 @@ namespace Org.BouncyCastle.Tls
             if (len < 0 || len > buf.Length - off)
                 throw new ArgumentException("invalid length: " + len, "len");
 
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+            Send(buf.AsSpan(off, len));
+#else
             try
             {
                 m_recordLayer.Send(buf, off, len);
@@ -103,7 +161,6 @@ namespace Org.BouncyCastle.Tls
             {
                 throw e;
             }
-#if !PORTABLE || DOTNET
             catch (SocketException e)
             {
                 if (TlsUtilities.IsTimeout(e))
@@ -112,7 +169,48 @@ namespace Org.BouncyCastle.Tls
                 m_recordLayer.Fail(AlertDescription.internal_error);
                 throw new TlsFatalAlert(AlertDescription.internal_error, e);
             }
+            // TODO[tls-port] Can we support interrupted IO on .NET?
+            //catch (InterruptedIOException e)
+            //{
+            //    throw e;
+            //}
+            catch (IOException e)
+            {
+                m_recordLayer.Fail(AlertDescription.internal_error);
+                throw e;
+            }
+            catch (Exception e)
+            {
+                m_recordLayer.Fail(AlertDescription.internal_error);
+                throw new TlsFatalAlert(AlertDescription.internal_error, e);
+            }
 #endif
+        }
+
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+        public virtual void Send(ReadOnlySpan<byte> buffer)
+        {
+            try
+            {
+                m_recordLayer.Send(buffer);
+            }
+            catch (TlsFatalAlert fatalAlert)
+            {
+                m_recordLayer.Fail(fatalAlert.AlertDescription);
+                throw fatalAlert;
+            }
+            catch (TlsTimeoutException e)
+            {
+                throw e;
+            }
+            catch (SocketException e)
+            {
+                if (TlsUtilities.IsTimeout(e))
+                    throw e;
+
+                m_recordLayer.Fail(AlertDescription.internal_error);
+                throw new TlsFatalAlert(AlertDescription.internal_error, e);
+            }
             // TODO[tls-port] Can we support interrupted IO on .NET?
             //catch (InterruptedIOException e)
             //{
@@ -129,6 +227,7 @@ namespace Org.BouncyCastle.Tls
                 throw new TlsFatalAlert(AlertDescription.internal_error, e);
             }
         }
+#endif
 
         /// <exception cref="IOException"/>
         public virtual void Close()