public override bool TryExecuteSync()
        {
            Socket socket = Socket !;

            (SocketError socketError, int bytesTransferred) = SocketPal.Recv(socket.SafeHandle, MemoryBuffer);
            BytesTransferred = bytesTransferred;
            if (socketError == SocketError.WouldBlock)
            {
                return(false);
            }
            SocketError = socketError;
            return(true);
        }
Esempio n. 2
0
        public override AsyncExecutionResult TryExecute(bool triggeredByPoll, bool isCancellationRequested, bool asyncOnly, AsyncExecutionQueue?executionQueue, AsyncExecutionCallback?callback, object?state, int data, AsyncOperationResult asyncResult)
        {
            SocketError          socketError      = SocketError.SocketError;
            int                  bytesTransferred = -1;
            AsyncExecutionResult result           = AsyncExecutionResult.Executing;

            if (asyncResult.HasResult)
            {
                if (asyncResult.IsError)
                {
                    if (asyncResult.Errno == EINTR)
                    {
                        result = AsyncExecutionResult.Executing;
                    }
                    else if (asyncResult.Errno == EAGAIN)
                    {
                        result = AsyncExecutionResult.WaitForPoll;
                    }
                    else
                    {
                        bytesTransferred = 0;
                        socketError      = SocketPal.GetSocketErrorForErrno(asyncResult.Errno);
                        result           = AsyncExecutionResult.Finished;
                    }
                }
                else
                {
                    bytesTransferred = asyncResult.IntValue;
                    socketError      = SocketError.Success;
                    result           = AsyncExecutionResult.Finished;
                }
            }

            if (isCancellationRequested && result != AsyncExecutionResult.Finished)
            {
                SocketError = SocketError.OperationAborted;
                return(AsyncExecutionResult.Cancelled);
            }

            // When there is a pollable executionQueue, use it to poll, and then try the operation.
            if (result == AsyncExecutionResult.Executing ||
                (result == AsyncExecutionResult.WaitForPoll && executionQueue?.SupportsPolling == true))
            {
                Memory <byte> memory            = MemoryBuffer;
                bool          isPollingReadable = memory.Length == 0; // A zero-byte read is a poll.
                if (triggeredByPoll && isPollingReadable)
                {
                    // No need to make a syscall, poll told us we're readable.
                    (socketError, bytesTransferred) = (SocketError.Success, 0);
                    result = AsyncExecutionResult.Finished;
                }
                else
                {
                    Socket socket = Socket !;

                    // Using Linux AIO executionQueue, we can't check when there is no
                    // data available. Instead of return value EAGAIN, a 0-byte read returns '0'.
                    if (executionQueue != null &&
                        (!isPollingReadable || executionQueue.SupportsPolling)) // Don't use Linux AIO for 0-byte reads.
                    {
                        executionQueue.AddRead(socket.SafeHandle, memory, callback !, state, data);
                        result = AsyncExecutionResult.Executing;
                    }
                    else if (result == AsyncExecutionResult.Executing)
                    {
                        if (asyncOnly)
                        {
                            result = AsyncExecutionResult.WaitForPoll;
                        }
                        else
                        {
                            (socketError, bytesTransferred) = SocketPal.Recv(socket.SafeHandle, memory);
                            result = socketError == SocketError.WouldBlock ? AsyncExecutionResult.WaitForPoll : AsyncExecutionResult.Finished;
                        }
                    }
                }
            }

            if (result == AsyncExecutionResult.Finished)
            {
                Debug.Assert(bytesTransferred != -1);
                BytesTransferred = bytesTransferred;
                SocketError      = socketError;
            }

            return(result);
        }