Пример #1
0
 /// <summary>
 /// Adds a recvmsg to the Submission Queue without it being submitted.
 /// The actual submission can be deferred to avoid unnecessary memory barriers.
 /// </summary>
 /// <param name="fd">File descriptor to receive from</param>
 /// <param name="msg">Message to read to</param>
 /// <param name="flags">Flags for the operator (as per recvmsg)</param>
 /// <param name="userData">User data that will be returned with the respective <see cref="Completion"/></param>
 /// <param name="options">Options for the handling of the prepared Submission Queue Entry</param>
 /// <exception cref="SubmissionQueueFullException">If no more free space in the Submission Queue is available</exception>
 public void PrepareRecvMsg(int fd, msghdr *msg, int flags, ulong userData = 0,
                            SubmissionOption options = SubmissionOption.None)
 {
     if (!TryPrepareRecvMsg(fd, msg, flags, userData, options))
     {
         ThrowSubmissionQueueFullException();
     }
 }
Пример #2
0
        public bool TryCompleteReceive(Ring ring, int result, [NotNullWhen(true)] out InboundConnection connection)
        {
            // Start work-around for https://github.com/axboe/liburing/issues/128
            _iov.AsSpan().Clear();
            _dummyBuffer.AsSpan().Clear();
            _control.AsSpan().Clear();
            _header.AsSpan().Clear();

            iovec* iov = (iovec*) MemoryHelper.UnsafeGetAddressOfPinnedArrayData(_iov);
            iov->iov_base = (byte*) MemoryHelper.UnsafeGetAddressOfPinnedArrayData(_dummyBuffer);
            iov->iov_len = 1;

            byte* control = (byte*) MemoryHelper.UnsafeGetAddressOfPinnedArrayData(_control);

            msghdr* header = (msghdr*) MemoryHelper.UnsafeGetAddressOfPinnedArrayData(_header);
            header->msg_iov = iov;
            header->msg_iovlen = 1;
            header->msg_control = control;
            header->msg_controllen = _control.Length;

            result = _recipient.RecvMsg(header, (MSG_NOSIGNAL | MSG_CMSG_CLOEXEC));
            // End of work-around for https://github.com/axboe/liburing/issues/128

            connection = default;
            if (result < 0)
            {
                HandleCompleteReceiveError(ring, result);
                return false;
            }

            bool receivedSocket = false;
            LinuxSocket socket = default;
            for (cmsghdr* cmsg = CMSG_FIRSTHDR(header); cmsg != null; cmsg = CMSG_NXTHDR(header, cmsg))
            {
                if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS)
                {
                    int* fdptr = (int*) CMSG_DATA(cmsg);
                    socket = *fdptr;
                    socket.SetFlag(O_NONBLOCK);

                    receivedSocket = true;
                    break;
                }
            }

            if (!receivedSocket)
            {
                if (result != 0)
                {
                    PollReceive(ring);
                }

                return false;
            }

            connection = new InboundConnection(socket, _endPoint, null, _memoryPool, _options, _scheduler);
            return true;
        }
Пример #3
0
        static unsafe cmsghdr *CMSG_NXTHDR(msghdr *mhdr, cmsghdr *cmsg)
        {
            if ((long)cmsg->cmsg_len < sizeof(cmsghdr))
            {
                return(null);
            }

            cmsg = (cmsghdr *)((byte *)cmsg + CMSG_ALIGN((ulong)cmsg->cmsg_len));
            if ((byte *)(cmsg + 1) > (byte *)mhdr->msg_control + mhdr->msg_controllen ||
                (byte *)cmsg + CMSG_ALIGN((ulong)cmsg->cmsg_len) > (byte *)mhdr->msg_control + mhdr->msg_controllen)
                return(null); }
Пример #4
0
        public unsafe RingResult RecvMsg(int fd, msghdr *msg, int flags,
                                         SubmissionOption options = SubmissionOption.None)
        {
            RingResult result = CreateRingResult();

            if (!_ring.TryPrepareRecvMsg(fd, msg, flags, result.Handle, options))
            {
                _pool.Return(result);
                return(_ringFullException);
            }

            return(result);
        }
Пример #5
0
        /// <summary>
        /// Prepares this Submission Queue Entry as a recvmsg.
        /// </summary>
        /// <param name="fd">File descriptor to receive from</param>
        /// <param name="msg">Message to read to</param>
        /// <param name="flags">Flags for the operation (as per recvmsg)</param>
        /// <param name="userData">User data that will be returned with the respective <see cref="Completion"/></param>
        /// <param name="options">Options for the handling of the prepared Submission Queue Entry</param>
        /// <param name="personality">The personality to impersonate for this submission</param>
        public void PrepareRecvMsg(int fd, msghdr *msg, uint flags, ulong userData = 0, SubmissionOption options = SubmissionOption.None, ushort personality = 0)
        {
            var sqe = _sqe;

            unchecked
            {
                sqe->opcode      = IORING_OP_RECVMSG;
                sqe->flags       = (byte)options;
                sqe->fd          = fd;
                sqe->addr        = (ulong)msg;
                sqe->len         = 1;
                sqe->msg_flags   = flags;
                sqe->user_data   = userData;
                sqe->personality = personality;
            }
        }
Пример #6
0
        private bool TryPrepareSendRecvMsg(byte op, int fd, msghdr *msg, int flags, ulong userData,
                                           SubmissionOption options)
        {
            if (!NextSubmissionQueueEntry(out var sqe))
            {
                return(false);
            }

            unchecked
            {
                sqe->opcode    = op;
                sqe->user_data = userData;
                sqe->flags     = (byte)options;
                sqe->fd        = fd;
                sqe->addr      = (ulong)msg;
                sqe->len       = 1;
                sqe->msg_flags = (uint)flags;
            }

            return(true);
        }
Пример #7
0
 public static extern unsafe size_t sendmsg(int sockfd, msghdr *msg, int flags);
Пример #8
0
 /// <summary>
 /// Attempts to add a recvmsg to the Submission Queue without it being submitted.
 /// The actual submission can be deferred to avoid unnecessary memory barriers.
 /// </summary>
 /// <param name="fd">File descriptor to receive from</param>
 /// <param name="msg">Message to read to</param>
 /// <param name="flags">Flags for the operator (as per recvmsg)</param>
 /// <param name="userData">User data that will be returned with the respective <see cref="Completion"/></param>
 /// <param name="options">Options for the handling of the prepared Submission Queue Entry</param>
 /// <returns><code>false</code> if the submission queue is full. <code>true</code> otherwise.</returns>
 public bool TryPrepareRecvMsg(int fd, msghdr *msg, int flags, ulong userData = 0,
                               SubmissionOption options = SubmissionOption.None)
 => TryPrepareSendRecvMsg(IORING_OP_RECVMSG, fd, msg, flags, userData, options);
Пример #9
0
 private static unsafe extern SSizeT sendmsg(int sockfd, msghdr *msg, int flags);
Пример #10
0
 static unsafe cmsghdr *CMSG_FIRSTHDR(msghdr *mhdr)
 {
     return(mhdr->msg_controllen >= sizeof(cmsghdr) ? (cmsghdr *)mhdr->msg_control : null);
 }
Пример #11
0
        internal static unsafe (SocketError socketError, int bytesTransferred) SendMsg(SafeSocketHandle handle, msghdr *msghdr)
        {
            int         bytesTransferred;
            SocketError socketError;

            int fd = handle.DangerousGetHandle().ToInt32(); // TODO: make safe
            int rv;

            do
            {
                rv = (int)sendmsg(fd, msghdr, 0);
            } while (rv == -1 && errno == EINTR);

            if (rv < 0)
            {
                bytesTransferred = 0;
                socketError      = GetSocketErrorForErrno(errno);
            }
            else
            {
                bytesTransferred = rv;
                socketError      = SocketError.Success;
            }

            return(socketError, bytesTransferred);
        }
Пример #12
0
 // out
 public unsafe static int recvmsg(this SOCKET s, msghdr *msg, int flags)
 {
     return(default(int));
 }