예제 #1
0
        public async Task ReceiveSent_TCP_Success(bool ipv6)
        {
            if (ipv6 && PlatformDetection.IsOSX)
            {
                // [ActiveIssue("https://github.com/dotnet/runtime/issues/47335")]
                // accept() will create a (seemingly) DualMode socket on Mac,
                // but since recvmsg() does not work with DualMode on that OS, we throw PNSE CheckDualModeReceiveSupport().
                // Weirdly, the flag is readable, but an attempt to write it leads to EINVAL.
                // The best option seems to be to skip this test for the Mac+IPV6 case
                return;
            }

            (Socket sender, Socket receiver) = SocketTestExtensions.CreateConnectedSocketPair(ipv6);
            using (sender)
                using (receiver)
                {
                    byte[] sendBuffer = { 1, 2, 3 };
                    sender.Send(sendBuffer);

                    byte[] receiveBuffer = new byte[3];
                    var    r             = await ReceiveMessageFromAsync(receiver, receiveBuffer, sender.LocalEndPoint);

                    Assert.Equal(3, r.ReceivedBytes);
                    AssertExtensions.SequenceEqual(sendBuffer, receiveBuffer);
                }
        }
예제 #2
0
        public async Task SendFileAsync_CanceledDuringOperation_Throws(bool ipv6)
        {
            const int CancelAfter    = 200; // ms
            const int NumOfSends     = 100;
            const int SendBufferSize = 1024;

            (Socket client, Socket server) = SocketTestExtensions.CreateConnectedSocketPair(ipv6);
            byte[] buffer = new byte[1024 * 64];
            using (client)
                using (server)
                {
                    client.SendBufferSize = SendBufferSize;
                    CancellationTokenSource cts = new CancellationTokenSource();

                    List <Task> tasks = new List <Task>();

                    // After flooding the socket with a high number of SendFile tasks,
                    // we assume some of them won't complete before the "CancelAfter" period expires.
                    for (int i = 0; i < NumOfSends; i++)
                    {
                        var task = server.SendFileAsync(null, buffer, ReadOnlyMemory <byte> .Empty, TransmitFileOptions.UseDefaultWorkerThread, cts.Token).AsTask();
                        tasks.Add(task);
                    }

                    cts.CancelAfter(CancelAfter);

                    // We shall see at least one cancellation amongst all the scheduled sends:
                    await Assert.ThrowsAnyAsync <OperationCanceledException>(() => Task.WhenAll(tasks));
                }
        }
예제 #3
0
        public void ConnectWithV4AndV6_Success()
        {
            int          port;
            TcpListener  listener    = SocketTestExtensions.CreateAndStartTcpListenerOnAnonymousPort(out port);
            IAsyncResult asyncResult = listener.BeginAcceptTcpClient(null, null);

            TcpClient v6Client = new TcpClient(AddressFamily.InterNetworkV6);

            v6Client.ConnectAsync(IPAddress.IPv6Loopback, port).GetAwaiter().GetResult();

            TcpClient acceptedV6Client = listener.EndAcceptTcpClient(asyncResult);

            Assert.Equal(AddressFamily.InterNetworkV6, acceptedV6Client.Client.RemoteEndPoint.AddressFamily);
            Assert.Equal(AddressFamily.InterNetworkV6, v6Client.Client.RemoteEndPoint.AddressFamily);

            asyncResult = listener.BeginAcceptTcpClient(null, null);

            TcpClient v4Client = new TcpClient(AddressFamily.InterNetwork);

            v4Client.ConnectAsync(IPAddress.Loopback, port).GetAwaiter().GetResult();

            TcpClient acceptedV4Client = listener.EndAcceptTcpClient(asyncResult);

            Assert.Equal(AddressFamily.InterNetworkV6, acceptedV4Client.Client.RemoteEndPoint.AddressFamily);
            Assert.Equal(AddressFamily.InterNetwork, v4Client.Client.RemoteEndPoint.AddressFamily);

            v6Client.Dispose();
            acceptedV6Client.Dispose();

            v4Client.Dispose();
            acceptedV4Client.Dispose();

            listener.Stop();
        }
예제 #4
0
        public async Task SliceBuffers_Success()
        {
            if (!SupportsSendFileSlicing)
            {
                return;                           // The overloads under test only support sending byte[] without offset and length
            }
            Random rnd = new Random(0);

            ArraySegment <byte> preBuffer  = new ArraySegment <byte>(new byte[100], 25, 50);
            ArraySegment <byte> postBuffer = new ArraySegment <byte>(new byte[100], 25, 50);

            rnd.NextBytes(preBuffer);
            rnd.NextBytes(postBuffer);

            byte[] expected = preBuffer.ToArray().Concat(postBuffer.ToArray()).ToArray();

            (Socket client, Socket server) = SocketTestExtensions.CreateConnectedSocketPair();

            using (client)
                using (server)
                {
                    await SendFileAsync(client, null, preBuffer, postBuffer, TransmitFileOptions.UseDefaultWorkerThread);

                    byte[] receiveBuffer = new byte[100];
                    int    receivedBytes = server.Receive(receiveBuffer);
                    Assert.Equal(100, receivedBytes);
                    AssertExtensions.SequenceEqual(expected, receiveBuffer);
                }
        }
예제 #5
0
        public void EndReceive_Throws_SocketException()
        {
            (Socket a, Socket b) = SocketTestExtensions.CreateConnectedSocketPair();

            using (b)
            {
                var iar = a.BeginReceive(new byte[1], 0, 1, SocketFlags.None, null, null);
                a.Dispose();

                Assert.Throws <SocketException>(() => a.EndReceive(iar));
            }
        }
예제 #6
0
        public void SetUnsupportedSocketOptionIntArg_DoesNotDisconnectSocket()
        {
            (Socket socket1, Socket socket2) = SocketTestExtensions.CreateConnectedSocketPair();
            using (socket1)
                using (socket2)
                {
                    SocketException se = Assert.Throws <SocketException>(() => socket1.SetSocketOption(SocketOptionLevel.Socket, (SocketOptionName)(-1), optionValue: 1));
                    Assert.True(se.SocketErrorCode == SocketError.ProtocolOption ||
                                se.SocketErrorCode == SocketError.OperationNotSupported, $"SocketError: {se.SocketErrorCode}");

                    Assert.True(socket1.Connected, "Connected");
                }
        }
예제 #7
0
        public void SetUnsupportedRawSocketOption_DoesNotDisconnectSocket()
        {
            (Socket socket1, Socket socket2) = SocketTestExtensions.CreateConnectedSocketPair();
            using (socket1)
                using (socket2)
                {
                    var             optionValue = new byte[4];
                    SocketException se          = Assert.Throws <SocketException>(() => socket1.SetRawSocketOption(SOL_SOCKET, -1, optionValue));
                    Assert.True(se.SocketErrorCode == SocketError.ProtocolOption ||
                                se.SocketErrorCode == SocketError.OperationNotSupported, $"SocketError: {se.SocketErrorCode}");

                    Assert.True(socket1.Connected, "Connected");
                }
        }
예제 #8
0
        public void ConnectWithV6_Success()
        {
            int          port;
            TcpListener  listener    = SocketTestExtensions.CreateAndStartTcpListenerOnAnonymousPort(out port);
            IAsyncResult asyncResult = listener.BeginAcceptTcpClient(null, null);

            TcpClient client = new TcpClient(AddressFamily.InterNetworkV6);

            client.ConnectAsync(IPAddress.IPv6Loopback, port).GetAwaiter().GetResult();

            TcpClient acceptedClient = listener.EndAcceptTcpClient(asyncResult);

            client.Dispose();
            acceptedClient.Dispose();
            listener.Stop();
        }
예제 #9
0
        public async Task FileDoesNotExist_ThrowsFileNotFoundException(bool useOverloadWithBuffers)
        {
            string doesNotExist = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());

            (Socket client, Socket server) = SocketTestExtensions.CreateConnectedSocketPair();

            using (client)
                using (server)
                {
                    if (!useOverloadWithBuffers)
                    {
                        await Assert.ThrowsAsync <FileNotFoundException>(() => SendFileAsync(client, doesNotExist));
                    }
                    else
                    {
                        await Assert.ThrowsAsync <FileNotFoundException>(() => SendFileAsync(client, doesNotExist, null, null, TransmitFileOptions.UseDefaultWorkerThread));
                    }
                }
        }
예제 #10
0
        public async Task SliceBuffers_Success()
        {
            if (!SupportsSendFileSlicing)
            {
                return;                           // The overloads under test only support sending byte[] without offset and length
            }
            Random rnd = new Random(0);

            ArraySegment <byte> preBuffer  = new ArraySegment <byte>(new byte[100], 25, 50);
            ArraySegment <byte> postBuffer = new ArraySegment <byte>(new byte[100], 25, 50);

            rnd.NextBytes(preBuffer);
            rnd.NextBytes(postBuffer);

            byte[] expected         = preBuffer.ToArray().Concat(postBuffer.ToArray()).ToArray();
            uint   expectedChecksum = Fletcher32.Checksum(expected, 0, expected.Length);

            (Socket client, Socket server) = SocketTestExtensions.CreateConnectedSocketPair();

            using (client)
                using (server)
                {
                    await SendFileAsync(client, null, preBuffer, postBuffer, TransmitFileOptions.UseDefaultWorkerThread);

                    Fletcher32 receivedChecksum = new Fletcher32();
                    byte[]     receiveBuffer    = new byte[expected.Length];
                    int        receivedBytes;
                    int        totalReceived = 0;
                    while (totalReceived < expected.Length && (receivedBytes = server.Receive(receiveBuffer)) != 0)
                    {
                        totalReceived += receivedBytes;
                        receivedChecksum.Add(receiveBuffer, 0, receivedBytes);
                    }
                    Assert.Equal(expected.Length, totalReceived);
                    Assert.Equal(expectedChecksum, receivedChecksum.Sum);
                }
        }
예제 #11
0
        public async Task SyncSendFileGetsCanceledByDispose()
        {
            // We try this a couple of times to deal with a timing race: if the Dispose happens
            // before the operation is started, the peer won't see a ConnectionReset SocketException and we won't
            // see a SocketException either.
            int msDelay = 100;
            await RetryHelper.ExecuteAsync(async() =>
            {
                (Socket socket1, Socket socket2) = SocketTestExtensions.CreateConnectedSocketPair();
                using (socket2)
                {
                    Task socketOperation = Task.Run(() =>
                    {
                        // Create a large file that will cause SendFile to block until the peer starts reading.
                        string filename = GetTestFilePath();
                        using (var fs = new FileStream(filename, FileMode.CreateNew, FileAccess.Write))
                        {
                            fs.SetLength(20 * 1024 * 1024 /* 20MB */);
                        }

                        socket1.SendFile(filename);
                    });

                    // Wait a little so the operation is started.
                    await Task.Delay(msDelay);
                    msDelay         *= 2;
                    Task disposeTask = Task.Run(() => socket1.Dispose());

                    var cts          = new CancellationTokenSource();
                    Task timeoutTask = Task.Delay(30000, cts.Token);
                    Assert.NotSame(timeoutTask, await Task.WhenAny(disposeTask, socketOperation, timeoutTask));
                    cts.Cancel();

                    await disposeTask;

                    SocketError?localSocketError = null;
                    try
                    {
                        await socketOperation;
                    }
                    catch (SocketException se)
                    {
                        localSocketError = se.SocketErrorCode;
                    }
                    catch (ObjectDisposedException)
                    { }
                    Assert.Equal(SocketError.ConnectionAborted, localSocketError);

                    // On OSX, we're unable to unblock the on-going socket operations and
                    // perform an abortive close.
                    if (!PlatformDetection.IsOSXLike)
                    {
                        SocketError?peerSocketError = null;
                        var receiveBuffer           = new byte[4096];
                        while (true)
                        {
                            try
                            {
                                int received = socket2.Receive(receiveBuffer);
                                if (received == 0)
                                {
                                    break;
                                }
                            }
                            catch (SocketException se)
                            {
                                peerSocketError = se.SocketErrorCode;
                                break;
                            }
                        }
                        Assert.Equal(SocketError.ConnectionReset, peerSocketError);
                    }
                }
            }, maxAttempts : 10);
        }
예제 #12
0
        public async Task SendFileGetsCanceledByDispose(bool owning)
        {
            // Aborting sync operations for non-owning handles is not supported on Unix.
            if (!owning && UsesSync && !PlatformDetection.IsWindows)
            {
                return;
            }

            // We try this a couple of times to deal with a timing race: if the Dispose happens
            // before the operation is started, the peer won't see a ConnectionReset SocketException and we won't
            // see a SocketException either.
            int msDelay = 100;
            await RetryHelper.ExecuteAsync(async() =>
            {
                (Socket socket1, Socket socket2) = SocketTestExtensions.CreateConnectedSocketPair();
                using SafeSocketHandle? owner    = ReplaceWithNonOwning(ref socket1, owning);

                using (socket2)
                {
                    Task socketOperation = Task.Run(async() =>
                    {
                        // Create a large file that will cause SendFile to block until the peer starts reading.
                        using var tempFile = TempFile.Create();
                        using (var fs = new FileStream(tempFile.Path, FileMode.CreateNew, FileAccess.Write))
                        {
                            fs.SetLength(20 * 1024 * 1024 /* 20MB */);
                        }

                        await SendFileAsync(socket1, tempFile.Path);
                    });

                    // Wait a little so the operation is started.
                    await Task.Delay(msDelay);
                    msDelay         *= 2;
                    Task disposeTask = Task.Run(() => socket1.Dispose());

                    await Task.WhenAny(disposeTask, socketOperation).WaitAsync(TimeSpan.FromSeconds(30));
                    await disposeTask;

                    SocketError?localSocketError = null;

                    try
                    {
                        await socketOperation;
                    }
                    catch (SocketException se)
                    {
                        localSocketError = se.SocketErrorCode;
                    }

                    if (UsesSync)
                    {
                        Assert.Equal(SocketError.ConnectionAborted, localSocketError);
                    }
                    else
                    {
                        Assert.Equal(SocketError.OperationAborted, localSocketError);
                    }

                    owner?.Dispose();

                    // On OSX, we're unable to unblock the on-going socket operations and
                    // perform an abortive close.
                    if (!(UsesSync && PlatformDetection.IsOSXLike))
                    {
                        SocketError?peerSocketError = null;
                        var receiveBuffer           = new byte[4096];
                        while (true)
                        {
                            try
                            {
                                int received = socket2.Receive(receiveBuffer);
                                if (received == 0)
                                {
                                    break;
                                }
                            }
                            catch (SocketException se)
                            {
                                peerSocketError = se.SocketErrorCode;
                                break;
                            }
                        }
                        Assert.Equal(SocketError.ConnectionReset, peerSocketError);
                    }
                }
            }, maxAttempts : 10, retryWhen : e => e is XunitException);
        }