diff --git a/src/Network/NWProtocolMetadata.cs b/src/Network/NWProtocolMetadata.cs index 895d83216c..0b6754dd55 100644 --- a/src/Network/NWProtocolMetadata.cs +++ b/src/Network/NWProtocolMetadata.cs @@ -87,7 +87,35 @@ namespace Network { [DllImport (Constants.NetworkLibrary)] static extern IntPtr nw_tls_copy_sec_protocol_metadata (IntPtr handle); - public SecProtocolMetadata SecProtocolMetadata => new SecProtocolMetadata (nw_tls_copy_sec_protocol_metadata (GetCheckedHandle ()), owns: true); + void CheckIsIP () + { + if (!IsIP) + throw new InvalidOperationException ("This metadata is not IP metadata."); + } + + void CheckIsTcp () + { + if (!IsTcp) + throw new InvalidOperationException ("This metadata is not TCP metadata."); + } + + void CheckIsTls () + { + if (!IsTls) + throw new InvalidOperationException ("This metadata is not TLS metadata."); + } + +#if !XAMCORE_4_0 + [Obsolete ("Use 'TlsSecProtocolMetadata' instead.")] + public SecProtocolMetadata SecProtocolMetadata => TlsSecProtocolMetadata; +#endif + + public SecProtocolMetadata TlsSecProtocolMetadata { + get { + CheckIsTls (); + return new SecProtocolMetadata (nw_tls_copy_sec_protocol_metadata (GetCheckedHandle ()), owns: true); + } + } [DllImport (Constants.NetworkLibrary)] static extern void nw_ip_metadata_set_ecn_flag (OS_nw_protocol_metadata metadata, NWIPEcnFlag ecn_flag); @@ -96,15 +124,24 @@ namespace Network { static extern NWIPEcnFlag nw_ip_metadata_get_ecn_flag (OS_nw_protocol_metadata metadata); public NWIPEcnFlag IPMetadataEcnFlag { - get => nw_ip_metadata_get_ecn_flag (GetCheckedHandle ()); - set => nw_ip_metadata_set_ecn_flag (GetCheckedHandle (), value); + get { + CheckIsIP (); + return nw_ip_metadata_get_ecn_flag (GetCheckedHandle ()); + } + set { + CheckIsIP (); + nw_ip_metadata_set_ecn_flag (GetCheckedHandle (), value); + } } [DllImport (Constants.NetworkLibrary)] static extern /* uint64_t */ ulong nw_ip_metadata_get_receive_time (OS_nw_protocol_metadata metadata); public ulong IPMetadataReceiveTime { - get => nw_ip_metadata_get_receive_time (GetCheckedHandle ()); + get { + CheckIsIP (); + return nw_ip_metadata_get_receive_time (GetCheckedHandle ()); + } } [DllImport (Constants.NetworkLibrary)] @@ -113,19 +150,41 @@ namespace Network { [DllImport (Constants.NetworkLibrary)] static extern NWServiceClass nw_ip_metadata_get_service_class (OS_nw_protocol_metadata metadata); +#if !XAMCORE_4_0 + [Obsolete ("Use 'IPServiceClass' instead.")] public NWServiceClass ServiceClass { - get => nw_ip_metadata_get_service_class (GetCheckedHandle ()); - set => nw_ip_metadata_set_service_class (GetCheckedHandle (), value); + get => IPServiceClass; + set => IPServiceClass = value; + } +#endif + + public NWServiceClass IPServiceClass { + get { + CheckIsIP (); + return nw_ip_metadata_get_service_class (GetCheckedHandle ()); + } + set { + CheckIsIP (); + nw_ip_metadata_set_service_class (GetCheckedHandle (), value); + } } [DllImport (Constants.NetworkLibrary)] extern static /* uint32_t */ uint nw_tcp_get_available_receive_buffer (IntPtr handle); - public uint TcpGetAvailableReceiveBuffer () => nw_tcp_get_available_receive_buffer (GetCheckedHandle ()); + public uint TcpGetAvailableReceiveBuffer () + { + CheckIsTcp (); + return nw_tcp_get_available_receive_buffer (GetCheckedHandle ()); + } [DllImport (Constants.NetworkLibrary)] extern static /* uint32_t */ uint nw_tcp_get_available_send_buffer (IntPtr handle); - public uint TcpGetAvailableSendBuffer () => nw_tcp_get_available_send_buffer (GetCheckedHandle ()); + public uint TcpGetAvailableSendBuffer () + { + CheckIsTcp (); + return nw_tcp_get_available_send_buffer (GetCheckedHandle ()); + } } } diff --git a/tests/monotouch-test/Network/NWProtocolMetadataTest.cs b/tests/monotouch-test/Network/NWProtocolMetadataTest.cs index 363a43d73d..e51a7e8f04 100644 --- a/tests/monotouch-test/Network/NWProtocolMetadataTest.cs +++ b/tests/monotouch-test/Network/NWProtocolMetadataTest.cs @@ -28,8 +28,10 @@ namespace MonoTouchFixtures.Network { Assert.False (m.IsTcp, "IsTcp"); Assert.False (m.IsUdp, "IsUdp"); Assert.NotNull (m.ProtocolDefinition, "ProtocolDefinition"); - Assert.NotNull (m.SecProtocolMetadata, "SecProtocolMetadata"); + Assert.Throws (() => { var x = m.SecProtocolMetadata; }, "SecProtocolMetadata"); + Assert.Throws (() => { var x = m.TlsSecProtocolMetadata; }, "TlsSecProtocolMetadata"); Assert.That (m.ServiceClass, Is.EqualTo (NWServiceClass.BestEffort), "ServiceClass"); + Assert.That (m.IPServiceClass, Is.EqualTo (NWServiceClass.BestEffort), "IPServiceClass"); } } @@ -37,16 +39,18 @@ namespace MonoTouchFixtures.Network { public void Udp () { using (var m = NWProtocolMetadata.CreateUdpMetadata ()) { - Assert.That (m.IPMetadataEcnFlag, Is.EqualTo (NWIPEcnFlag.NonEct), "IPMetadataEcnFlag"); - Assert.That (m.IPMetadataReceiveTime, Is.EqualTo (0), "IPMetadataReceiveTime"); + Assert.Throws (() => { var x = m.IPMetadataEcnFlag; }, "IPMetadataEcnFlag"); + Assert.Throws (() => { var x = m.IPMetadataReceiveTime; }, "IPMetadataReceiveTime"); Assert.False (m.IsIP, "IsIP"); Assert.False (m.IsTcp, "IsTcp"); Assert.True (m.IsUdp, "IsUdp"); Assert.NotNull (m.ProtocolDefinition, "ProtocolDefinition"); - Assert.NotNull (m.SecProtocolMetadata, "SecProtocolMetadata"); - Assert.That (m.ServiceClass, Is.EqualTo (NWServiceClass.BestEffort), "ServiceClass"); + Assert.Throws (() => { var x = m.SecProtocolMetadata; }, "SecProtocolMetadata"); + Assert.Throws (() => { var x = m.TlsSecProtocolMetadata; }, "TlsSecProtocolMetadata"); + Assert.Throws (() => { var x = m.ServiceClass; }, "ServiceClass"); + Assert.Throws (() => { var x = m.IPServiceClass; }, "IPServiceClass"); } } } } -#endif \ No newline at end of file +#endif diff --git a/tests/monotouch-test/Security/SecProtocolMetadataTest.cs b/tests/monotouch-test/Security/SecProtocolMetadataTest.cs index d8a982f17e..77a6cb4915 100644 --- a/tests/monotouch-test/Security/SecProtocolMetadataTest.cs +++ b/tests/monotouch-test/Security/SecProtocolMetadataTest.cs @@ -1,6 +1,9 @@ #if !__WATCHOS__ using System; using System.Runtime.InteropServices; +using System.Threading; + +using CoreFoundation; using Foundation; using Network; using ObjCRuntime; @@ -21,44 +24,55 @@ namespace MonoTouchFixtures.Security { } [Test] - public void IPDefaults () + public void TlsDefaults () { - if (TestRuntime.CheckXcodeVersion (11, 0)) - Assert.Ignore ("NWProtocolMetadata.CreateIPMetadata () returns a metadata object with uninitialized metadata, which means the asserts here fail randomly."); + using (var ep = NWEndpoint.Create ("www.microsoft.com", "https")) + using (var parameters = NWParameters.CreateSecureTcp ()) + using (var queue = new DispatchQueue (GetType ().FullName)) { + var connection = new NWConnection (ep, parameters); - using (var m = NWProtocolMetadata.CreateIPMetadata ()) { - var s = m.SecProtocolMetadata; - // This is mostly, but not always, returning false - // Assert.False (s.EarlyDataAccepted, "EarlyDataAccepted"); - Assert.That (s.NegotiatedCipherSuite, Is.EqualTo (SslCipherSuite.SSL_NULL_WITH_NULL_NULL), "NegotiatedCipherSuite"); - Assert.Null (s.NegotiatedProtocol, "NegotiatedProtocol"); - Assert.That (s.NegotiatedProtocolVersion, Is.EqualTo (SslProtocol.Unknown), "NegotiatedProtocolVersion"); - Assert.Null (s.PeerPublicKey, "PeerPublicKey"); -#if false - Assert.True (SecProtocolMetadata.ChallengeParametersAreEqual (s, s), "ChallengeParametersAreEqual"); - Assert.True (SecProtocolMetadata.PeersAreEqual (s, s), "PeersAreEqual"); -#endif - } - } + var ready = new ManualResetEvent (false); + connection.SetStateChangeHandler ((state, error) => { + Console.WriteLine (state); + switch (state) { + case NWConnectionState.Cancelled: + case NWConnectionState.Failed: + // We can't dispose until the connection has been closed or it failed. + connection.Dispose (); + break; + case NWConnectionState.Invalid: + case NWConnectionState.Preparing: + case NWConnectionState.Waiting: + break; + case NWConnectionState.Ready: + ready.Set (); + break; + default: + break; + } + }); -#if false - [DllImport (Constants.CoreFoundationLibrary)] - extern static nint CFGetRetainCount (IntPtr handle); + connection.SetQueue (queue); + connection.Start (); - [Test] - public void CreateSecret () - { - using (var npm = NWProtocolMetadata.CreateIPMetadata ()) { - // `npm` and `spm` have the same handle - same internal object satistfy both protocols - Console.WriteLine ($"{CFGetRetainCount (npm.Handle)}"); - using (var spm = npm.SecProtocolMetadata) { - Console.WriteLine ($"{CFGetRetainCount (npm.Handle)}"); - Console.WriteLine ($"{CFGetRetainCount (spm.Handle)}"); - var secret = spm.CreateSecret ("test", 16); // crash + // Wait until the connection is ready. + Assert.True (ready.WaitOne (TimeSpan.FromSeconds (10)), "Connection is ready"); + + using (var m = connection.GetProtocolMetadata (NWProtocolDefinition.TlsDefinition)) { + var s = m.TlsSecProtocolMetadata; + Assert.False (s.EarlyDataAccepted, "EarlyDataAccepted"); + Assert.That (s.NegotiatedCipherSuite, Is.Not.EqualTo (SslCipherSuite.SSL_NULL_WITH_NULL_NULL), "NegotiatedCipherSuite"); + Assert.Null (s.NegotiatedProtocol, "NegotiatedProtocol"); + Assert.That (s.NegotiatedProtocolVersion, Is.EqualTo (SslProtocol.Tls_1_2).Or.EqualTo (SslProtocol.Tls_1_3), "NegotiatedProtocolVersion"); + Assert.NotNull (s.PeerPublicKey, "PeerPublicKey"); + + Assert.True (SecProtocolMetadata.ChallengeParametersAreEqual (s, s), "ChallengeParametersAreEqual"); + Assert.True (SecProtocolMetadata.PeersAreEqual (s, s), "PeersAreEqual"); } + + connection.Cancel (); } } -#endif } } -#endif \ No newline at end of file +#endif