Пример #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);
        }
Пример #2
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));
 }
Пример #3
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));
 }
Пример #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));
 }
Пример #5
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));
 }