diff --git a/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.cs b/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.cs index 8225f802f3987..94d1cea46d1b0 100644 --- a/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.cs +++ b/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.cs @@ -2155,7 +2155,7 @@ public bool Poll(int microSeconds, SelectMode mode) } /// Determines the status of the . - /// The time to wait for a response. + /// The time to wait for a response. indicates an infinite timeout. /// One of the values. /// /// The status of the based on the polling mode value passed in the parameter. @@ -2167,7 +2167,7 @@ public bool Poll(int microSeconds, SelectMode mode) /// does not block and the connection has failed, or if OutOfBandInline is not set and out-of-band data is available. /// Otherwise, it returns . /// - /// is less than -1 milliseconds or greater than milliseconds. + /// was negative or greater than TimeSpan.FromMicroseconds(int.MaxValue). /// An error occurred when attempting to access the socket. /// The has been closed. public bool Poll(TimeSpan timeout, SelectMode mode) => @@ -2217,10 +2217,10 @@ public static void Select(IList? checkRead, IList? checkWrite, IList? checkError /// An of instances to check for readability. /// An of instances to check for writability. /// An of instances to check for errors. - /// The timeout value. A value equal to -1 microseconds indicates an infinite timeout. + /// The timeout value. A value equal to indicates an infinite timeout. /// The , , or parameter is or empty. /// The , , or parameter contains too many sockets. - /// The was less than -1 microseconds or greater than microseconds + /// The was negative or greater than TimeSpan.FromMicroseconds(int.MaxValue). /// An error occurred when attempting to access the socket. /// One or more sockets was disposed. public static void Select(IList? checkRead, IList? checkWrite, IList? checkError, TimeSpan timeout) => @@ -2228,8 +2228,18 @@ public static void Select(IList? checkRead, IList? checkWrite, IList? checkError private static int ToTimeoutMicroseconds(TimeSpan timeout) { + if (timeout == Timeout.InfiniteTimeSpan) + { + return -1; + } + + if (timeout < TimeSpan.Zero) + { + throw new ArgumentOutOfRangeException(nameof(timeout)); + } long totalMicroseconds = (long)timeout.TotalMicroseconds; - if (totalMicroseconds < -1 || totalMicroseconds > int.MaxValue) + + if (totalMicroseconds > int.MaxValue) { throw new ArgumentOutOfRangeException(nameof(timeout)); } diff --git a/src/libraries/System.Net.Sockets/tests/FunctionalTests/ArgumentValidationTests.cs b/src/libraries/System.Net.Sockets/tests/FunctionalTests/ArgumentValidationTests.cs index 31da90800351a..f0f7ed672ac04 100644 --- a/src/libraries/System.Net.Sockets/tests/FunctionalTests/ArgumentValidationTests.cs +++ b/src/libraries/System.Net.Sockets/tests/FunctionalTests/ArgumentValidationTests.cs @@ -371,6 +371,58 @@ public void Select_NullOrEmptyLists_Throws_ArgumentNull_TimeSpan() Assert.Throws(() => Socket.Select(emptyList, emptyList, emptyList, nonInfinity)); } + [Fact] + public void SelectPoll_NegativeTimeSpan_Throws() + { + using (Socket host = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)) + { + host.Bind(new IPEndPoint(IPAddress.Loopback, 0)); + host.Listen(1); + Task accept = host.AcceptAsync(); + + using (Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)) + { + s.Connect(new IPEndPoint(IPAddress.Loopback, ((IPEndPoint)host.LocalEndPoint).Port)); + + var list = new List(); + list.Add(s); + + Assert.Throws(() => Socket.Select(null, list, null, TimeSpan.FromMicroseconds(-1))); + Assert.Throws(() => Socket.Select(null, list, null, TimeSpan.FromMicroseconds((double)int.MaxValue + 1))); + Assert.Throws(() => Socket.Select(null, list, null, TimeSpan.FromMilliseconds(-1.1))); + + Assert.Throws(() => s.Poll(TimeSpan.FromMicroseconds(-1), SelectMode.SelectWrite)); + Assert.Throws(() => s.Poll(TimeSpan.FromMicroseconds((double)int.MaxValue + 1), SelectMode.SelectWrite)); + Assert.Throws(() => s.Poll(TimeSpan.FromMilliseconds(-1.1), SelectMode.SelectWrite)); + } + } + } + + [Fact] + public void SelectPoll_InfiniteTimeSpan_Ok() + { + using (Socket host = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)) + { + host.Bind(new IPEndPoint(IPAddress.Loopback, 0)); + host.Listen(1); + Task accept = host.AcceptAsync(); + + using (Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)) + { + s.Connect(new IPEndPoint(IPAddress.Loopback, ((IPEndPoint)host.LocalEndPoint).Port)); + + var list = new List(); + list.Add(s); + + // should be writable + Socket.Select(null, list, null, Timeout.InfiniteTimeSpan); + Socket.Select(null, list, null, -1); + s.Poll(Timeout.InfiniteTimeSpan, SelectMode.SelectWrite); + s.Poll(-1, SelectMode.SelectWrite); + } + } + } + [Fact] public void Select_LargeList_Throws_ArgumentOutOfRange() {