Exemple #1
0
        public void TestGettingAwaiter()
        {
            var awaitable = new SocketAwaitable();
            var awaiter   = awaitable.GetAwaiter();

            Assert.IsTrue(awaiter.IsCompleted);
            Assert.AreEqual(awaiter.GetResult(), default(SocketError));
        }
Exemple #2
0
        public void TestInitialization()
        {
            // Default values.
            var awaitable = new SocketAwaitable();

            Assert.IsNull(awaitable.AcceptSocket);

            var awaiter = awaitable.GetAwaiter();

            Assert.IsTrue(awaiter.IsCompleted);
            Assert.AreEqual(awaiter.GetResult(), SocketError.Success);
        }
Exemple #3
0
        public async Task TestAwaiterStatus()
        {
            using (var listener = new Socket(SocketType.Stream, ProtocolType.Tcp))
            {
                listener.Bind(new IPEndPoint(IPAddress.IPv6Any, 0));
                listener.Listen(1);
                var acceptTask = Task.Run(async() =>
                {
                    using (var awaitable = new SocketAwaitable())
                    {
                        var awaiter = awaitable.GetAwaiter();
                        Assert.IsTrue(awaiter.IsCompleted);
                        Assert.AreEqual(awaiter.GetResult(), SocketError.Success);

                        var a = listener.AcceptAsync(awaitable);
                        Assert.IsFalse(awaiter.IsCompleted);
                        Assert.AreEqual(awaiter.GetResult(), SocketError.AlreadyInProgress);

                        var result = await a;
                        Assert.IsTrue(awaiter.IsCompleted);
                        Assert.AreEqual(awaiter.GetResult(), result);
                    }
                });

                await Task.Delay(500);

                using (var client = new Socket(SocketType.Stream, ProtocolType.Tcp))
                {
                    using (var awaitable = new SocketAwaitable())
                    {
                        awaitable.RemoteEndPoint = new IPEndPoint(
                            IPAddress.IPv6Loopback,
                            (listener.LocalEndPoint as IPEndPoint).Port);

                        var awaiter = awaitable.GetAwaiter();
                        Assert.IsTrue(awaiter.IsCompleted);
                        Assert.AreEqual(awaiter.GetResult(), SocketError.Success);

                        var a = client.ConnectAsync(awaitable);
                        Assert.IsFalse(awaiter.IsCompleted);
                        Assert.AreEqual(awaiter.GetResult(), SocketError.AlreadyInProgress);

                        var result = await a;
                        Assert.IsTrue(awaiter.IsCompleted);
                        Assert.AreEqual(awaiter.GetResult(), result);
                    }
                }

                await acceptTask;
            }
        }
        /// <summary>
        ///     Calls the specified asynchronous method of a <see cref="Socket" /> and returns an awaitable
        ///     object that provides the operation result when awaited.
        /// </summary>
        /// <param name="socket">
        ///     <see cref="Socket" /> to run an asynchronous operation.
        /// </param>
        /// <param name="awaitable">
        ///     The <see cref="SocketAwaitable" /> object to use for this asynchronous socket operation.
        /// </param>
        /// <param name="operation">
        ///     Socket operation to perform.
        /// </param>
        /// <returns>
        ///     A <see cref="SocketAwaitable" /> which, when awaited, returns a <see cref="SocketError" />
        ///     object that corresponds to the result of <paramref name="operation" />.
        /// </returns>
        /// <exception cref="ArgumentNullException">
        ///     <paramref name="socket" /> or <paramref name="awaitable" /> is null.
        /// </exception>
        /// <exception cref="InvalidOperationException">
        ///     A socket operation was already in progress using <paramref name="awaitable"/>.
        ///     -or-
        ///     For accept operations:
        ///     <paramref name="socket" /> is not bound, is not listening for connections, or is already connected.
        ///     -or-
        ///     For connect operations:
        ///     <paramref name="socket" /> is listening.
        /// </exception>
        /// <exception cref="NotSupportedException">
        ///     Windows XP or later is required for this method.
        ///     -or-
        ///     For connect operations:
        ///     Address family of <see cref="Socket.LocalEndPoint" /> is different than the address family of
        ///     <see cref="SocketAsyncEventArgs.RemoteEndPoint" />.
        /// </exception>
        /// <exception cref="ObjectDisposedException">
        ///     <paramref name="socket" /> has been disposed.
        /// </exception>
        /// <exception cref="SecurityException">
        ///     For connection operations:
        ///     A caller higher in the call stack does not have permission for the requested operation.
        /// </exception>
        private static SocketAwaitable OperateAsync(
            Socket socket,
            SocketAwaitable awaitable,
            Func<Socket, SocketAwaitable, bool> operation)
        {
            if (socket == null)
                throw new ArgumentNullException("socket", "Socket must not be null.");

            if (awaitable == null)
                throw new ArgumentNullException("awaitable", "Awaitable must not be null.");

            var a = awaitable.GetAwaiter();
            lock (a.SyncRoot)
            {
                if (!a.IsCompleted)
                    throw new InvalidOperationException(
                        "A socket operation is already in progress using the same awaitable arguments.");

                a.Reset();
                if (awaitable.ShouldCaptureContext)
                    a.SyncContext = SynchronizationContext.Current;
            }
            
            try
            {
                if (!operation.Invoke(socket, awaitable))
                    a.Complete();
            }
            catch (SocketException x)
            {
                a.Complete();
                awaitable.Arguments.SocketError = x.SocketErrorCode != SocketError.Success
                    ? x.SocketErrorCode
                    : SocketError.SocketError;
            }
            catch (Exception)
            {
                a.Complete();
                awaitable.Arguments.SocketError = SocketError.Success;
                throw;
            }

            return awaitable;
        }