Beispiel #1
0
        /// <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);
        }
        /// <summary>
        ///     Initializes a new instance of the <see cref="SocketAwaiter" /> class.
        /// </summary>
        /// <param name="awaitable">
        ///     The asynchronous socket arguments to await.
        /// </param>
        internal SocketAwaiter(SocketAwaitable awaitable)
        {
            this.awaitable = awaitable;
            this.awaitable.Arguments.Completed += delegate
            {
                var c = this.continuation ?? Interlocked.CompareExchange(ref this.continuation, sentinel, null);
                if (c != null)
                {
                    var syncContext = this.awaitable.ShouldCaptureContext ? this.SyncContext : null;
                    this.Complete();

                    if (syncContext != null)
                    {
                        syncContext.Post(s => c.Invoke(), null);
                    }
                    else
                    {
                        c.Invoke();
                    }
                }
            };
        }
Beispiel #3
0
 /// <summary>
 ///     Begins an awaitable operation to accept an incoming connection attempt.
 /// </summary>
 /// <param name="socket">
 ///     Socket that will accept the connection.
 /// </param>
 /// <param name="awaitable">
 ///     The <see cref="SocketAwaitable" /> object to use for this asynchronous socket operation.
 /// </param>
 /// <returns>
 ///     <paramref name="awaitable" />, when awaited, will have the accepted socket
 ///     in its <see cref="SocketAwaitable.AcceptSocket" /> property. Awaiter of the result returns a
 ///     <see cref="SocketError" /> that corresponds to the result of this asynchronous operation.
 /// </returns>
 /// <exception cref="ArgumentNullException">
 ///     <paramref name="socket" /> or <paramref name="awaitable" /> is null.
 /// </exception>
 /// <exception cref="ArgumentException">
 ///     <see cref="SocketAwaitable.Buffer" /> of the <paramref name="awaitable" /> is not large enough.
 ///     The buffer must be at least 2 * (sizeof(SOCKADDR_STORAGE + 16) bytes.
 /// </exception>
 /// <exception cref="InvalidOperationException">
 ///     <paramref name="socket" /> is not bound, is not listening for connections, or is already connected.
 ///     -or-
 ///     A socket operation was already in progress using <paramref name="awaitable" />
 /// </exception>
 /// <exception cref="NotSupportedException">
 ///     Windows XP or later is required for this method.
 /// </exception>
 /// <exception cref="ObjectDisposedException">
 ///     <paramref name="socket" /> has been disposed.
 /// </exception>
 public static SocketAwaitable AcceptAsync(this Socket socket, SocketAwaitable awaitable)
 {
     return(OperateAsync(socket, awaitable, acceptOp));
 }
Beispiel #4
0
 /// <summary>
 ///     Sends data asynchronously to a connected <see cref="Socket" /> object and returns a
 ///     <see cref="SocketAwaitable" /> to await.
 /// </summary>
 /// <param name="socket">
 ///     Socket to send the data to.
 /// </param>
 /// <param name="awaitable">
 ///     The <see cref="SocketAwaitable" /> object to use for this asynchronous socket operation.
 /// </param>
 /// <returns>
 ///     The specified <see cref="SocketAwaitable" /> which, when awaited, will return a
 ///     <see cref="SocketError" /> object that corresponds to the result of the send 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"/>.
 /// </exception>
 /// <exception cref="NotSupportedException">
 ///     Windows XP or later is required for this method.
 /// </exception>
 /// <exception cref="ObjectDisposedException">
 ///     <paramref name="socket" /> has been disposed.
 /// </exception>
 public static SocketAwaitable SendAsync(this Socket socket, SocketAwaitable awaitable)
 {
     return(OperateAsync(socket, awaitable, sendOp));
 }
Beispiel #5
0
 /// <summary>
 ///     Begins an awaitable request to receive data from a connected <see cref="Socket" /> object.
 /// </summary>
 /// <param name="socket">
 ///     Socket that will receive data.
 /// </param>
 /// <param name="awaitable">
 ///     The <see cref="SocketAwaitable" /> object to use for this asynchronous socket operation.
 /// </param>
 /// <returns>
 ///     The specified <see cref="SocketAwaitable" /> which, when awaited, will hold the received
 ///     data in its <see cref="SocketAsyncEventArgs.Buffer" /> property. Awaiter of <see cref="SocketAwaitable" />
 ///     returns a <see cref="SocketError" /> object that corresponds to the result of the asynchronous 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"/>.
 /// </exception>
 /// <exception cref="NotSupportedException">
 ///     Windows XP or later is required for this method.
 /// </exception>
 /// <exception cref="ObjectDisposedException">
 ///     <paramref name="socket" /> has been disposed.
 /// </exception>
 public static SocketAwaitable ReceiveAsync(this Socket socket, SocketAwaitable awaitable)
 {
     return(OperateAsync(socket, awaitable, receiveOp));
 }
Beispiel #6
0
 /// <summary>
 ///     Begins an awaitable request to disconnect from a remote endpoint.
 /// </summary>
 /// <param name="socket">
 ///     Socket that will connect to a remote host.
 /// </param>
 /// <param name="awaitable">
 ///     The <see cref="SocketAwaitable" /> object to use for this asynchronous socket operation.
 /// </param>
 /// <returns>
 ///     The specified <see cref="SocketAwaitable" /> which, when awaited, returns a
 ///     <see cref="SocketError" /> object that corresponds to the result of the connection attempt.
 /// </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" />.
 /// </exception>
 /// <exception cref="NotSupportedException">
 ///     Windows XP or later is required for this method. This exception also occurs if the local endpoint
 ///     and the <see cref="SocketAwaitable.RemoteEndPoint" /> are not the same address family.
 ///     -or-
 ///     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>
 public static SocketAwaitable DisonnectAsync(this Socket socket, SocketAwaitable awaitable)
 {
     return(OperateAsync(socket, awaitable, disconnectOp));
 }