/// <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(); } }
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; }
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); }
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); }
/// <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; } }
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); }
public static extern unsafe size_t sendmsg(int sockfd, msghdr *msg, int flags);
/// <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);
private static unsafe extern SSizeT sendmsg(int sockfd, msghdr *msg, int flags);
static unsafe cmsghdr *CMSG_FIRSTHDR(msghdr *mhdr) { return(mhdr->msg_controllen >= sizeof(cmsghdr) ? (cmsghdr *)mhdr->msg_control : null); }
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); }
// out public unsafe static int recvmsg(this SOCKET s, msghdr *msg, int flags) { return(default(int)); }