コード例 #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="SaeaAwaitable" /> object to use for this asynchronous socket
        ///     operation.
        /// </param>
        /// <param name="operation">
        ///     Socket operation to perform.
        /// </param>
        /// <returns>
        ///     A <see cref="SaeaAwaitable" /> 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 SaeaAwaitable OperateAsync(Socket socket, SaeaAwaitable awaitable, Func <Socket, SaeaAwaitable, bool> operation)
        {
            if (socket == null)
            {
                throw new ArgumentNullException(nameof(socket));
            }

            if (awaitable == null)
            {
                throw new ArgumentNullException(nameof(awaitable));
            }

            var awaiter = awaitable.GetAwaiter();

            lock (awaiter.SyncRoot)
            {
                if (!awaiter.IsCompleted)
                {
                    throw new InvalidOperationException(
                              "A socket operation is already in progress using the same await-able SAEA.");
                }

                awaiter.Reset();
            }

            try
            {
                if (!operation.Invoke(socket, awaitable))
                {
                    awaiter.Complete();
                }
            }
            catch (SocketException ex)
            {
                awaiter.Complete();
                awaitable.Saea.SocketError =
                    ex.SocketErrorCode != SocketError.Success ? ex.SocketErrorCode : SocketError.SocketError;
            }
            catch (Exception)
            {
                awaiter.Complete();
                awaitable.Saea.SocketError = SocketError.Success;
                throw;
            }

            return(awaitable);
        }
コード例 #2
0
        /// <summary>
        /// Setup <see cref="SocketAsyncEventArgs.Buffer"/> in <see cref="SaeaAwaitable"/>
        /// </summary>
        /// <param name="awaitable"></param>
        /// <param name="buf">src buffer</param>
        /// <param name="bufLen">src buffer length</param>
        public static void PrepareSAEABuffer(this SaeaAwaitable awaitable, byte[] buf, int bufLen)
        {
            if (awaitable == null)
            {
                throw new ArgumentNullException(nameof(awaitable));
            }
            if (buf == null)
            {
                throw new ArgumentNullException(nameof(buf));
            }
            if (bufLen <= 0)
            {
                throw new ArgumentOutOfRangeException(nameof(bufLen));
            }

            var saea = awaitable.Saea;

            if (saea == null)
            {
                throw new NullReferenceException();
            }
            Buffer.BlockCopy(buf, 0, saea.Buffer, 0, bufLen);
            saea.SetBuffer(0, bufLen);
        }
コード例 #3
0
 public static SaeaAwaitable SendToAsync(this Socket socket, SaeaAwaitable awaitable)
 {
     return(OperateAsync(socket, awaitable, SENDTO));
 }
コード例 #4
0
 public static SaeaAwaitable ReceiveFromAsync(this Socket socket, SaeaAwaitable awaitable)
 {
     return(OperateAsync(socket, awaitable, RECEIVEFROM));
 }
コード例 #5
0
 public static SaeaAwaitable DisconnectAsync(this Socket socket, SaeaAwaitable awaitable)
 {
     return(OperateAsync(socket, awaitable, DISCONNECT));
 }
コード例 #6
0
        public static async Task <TcpTrafficToken> FullSendTaskAsync(this Socket socket, SaeaAwaitable awaitable, int intendedSendSize)
        {
            if (socket == null)
            {
                throw new ArgumentNullException(nameof(socket));
            }
            if (awaitable == null)
            {
                throw new ArgumentNullException(nameof(awaitable));
            }
            int         bytesSent = 0;
            SocketError err;

            awaitable.Saea.SetBuffer(0, intendedSendSize);
            while (true)
            {
                err = await socket.SendAsync(awaitable);

                if (err != SocketError.Success)
                {
                    break;
                }
                if (awaitable.Saea.BytesTransferred <= 0)
                {
                    break;
                }
                Interlocked.Add(ref bytesSent, awaitable.Saea.BytesTransferred);
                if (bytesSent >= intendedSendSize)
                {
                    break;
                }
                awaitable.Saea.SetBuffer(awaitable.Saea.Offset + awaitable.Saea.BytesTransferred,
                                         awaitable.Saea.Count - awaitable.Saea.BytesTransferred);
            }
            return(new TcpTrafficToken(err, bytesSent));
        }
コード例 #7
0
 public static SaeaAwaitable AcceptAsync(this Socket socket, SaeaAwaitable awaitable)
 {
     return(OperateAsync(socket, awaitable, ACCEPT));
 }
コード例 #8
0
 /// <summary>
 ///     Initializes a new instance of the <see cref="SaeaAwaiter" /> class.
 /// </summary>
 /// <param name="awaitable">
 ///     The asynchronous socket arguments to await.
 /// </param>
 public SaeaAwaiter(SaeaAwaitable awaitable)
 {
     _awaitable = awaitable;
     _awaitable.Saea.Completed += this.OnSaeaOnCompleted;
 }