public unsafe void ReceiveMessage( Span <byte> fixedLengthHeader, Span <byte> control ) { fixed(byte *fixedLengthHeaderP = fixedLengthHeader) fixed(byte *controlP = control) { const int iovecsLength = 1; var iovecs = stackalloc iovec[iovecsLength]; iovecs[0].iov_base = fixedLengthHeaderP; iovecs[0].iov_len = fixedLengthHeader.Length; var msg = new msghdr { iov = iovecs, iovlen = 1, controllen = control.Length, control = controlP }; var length = recvmsg(handle, ref msg, 0); if (length == 0) { throw new OperationCanceledException("Socket was shut down"); } if (length < 0) { throw new InvalidOperationException("recvmsg failed with " + length); } } }
public unsafe void Send(Span <ReadOnlyMemory <byte> > segments, int numberOfSegments) { var handlesMemoryOwner = MemoryPool <MemoryHandle> .Shared.Rent(numberOfSegments); var handles = handlesMemoryOwner.Memory.Span; var iovecs = stackalloc iovec[numberOfSegments]; for (var i = 0; i < numberOfSegments; ++i) { handles[i] = segments[i].Pin(); iovecs[i].iov_base = (byte *)handles[i].Pointer; iovecs[i].iov_len = segments[i].Length; } var msg = new msghdr { iov = iovecs, iovlen = numberOfSegments, }; var sendResult = sendmsg(handle, ref msg, 0); for (var i = 0; i < numberOfSegments; ++i) { handles[i].Dispose(); } handlesMemoryOwner.Dispose(); if (sendResult < 0) { throw new Win32Exception(Marshal.GetLastWin32Error()); } }
public unsafe bool ReceiveMessage( Span <byte> header, Span <byte> body, Span <byte> fixedLengthHeader, Span <byte> control ) { fixed(byte *headerP = header) fixed(byte *bodyP = body) fixed(byte *fixedLengthHeaderP = fixedLengthHeader) fixed(byte *controlP = control) { const int iovecsLength = 3; var iovecs = stackalloc iovec[iovecsLength]; var lengthTillBodyEnd = header.Length + body.Length; var allReceivedLength = 0; iovecs[0].iov_base = headerP; iovecs[0].iov_len = header.Length; iovecs[1].iov_base = bodyP; iovecs[1].iov_len = body.Length; iovecs[2].iov_base = fixedLengthHeaderP; iovecs[2].iov_len = fixedLengthHeader.Length; var nextMsg = new msghdr { iov = iovecs, iovlen = iovecsLength, control = controlP, controllen = control.Length, }; allReceivedLength += receiveAndCheck(ref nextMsg); if (allReceivedLength < lengthTillBodyEnd) { // Did not receive an entire body, continue by moving the contents // in the iovecs "up"… iovecs[1].iov_base = iovecs[2].iov_base; // and the new header iovecs[1].iov_len = iovecs[2].iov_len; nextMsg.iovlen -= 1; } while (allReceivedLength < lengthTillBodyEnd) { // …and by adapting the pointer and length of the body var offset = allReceivedLength - header.Length; iovecs[0].iov_base = bodyP + offset; iovecs[0].iov_len = lengthTillBodyEnd - allReceivedLength; allReceivedLength += receiveAndCheck(ref nextMsg); } return(allReceivedLength == header.Length + body.Length + fixedLengthHeader.Length); } }
public unsafe static PosixResult ReceiveSocket(int fromSocket, out int socket, bool blocking) { socket = -1; byte dummyBuffer = 0; iovec iov = default(iovec); iov.iov_base = &dummyBuffer; iov.iov_len = 1; int controlLength = CMSG_SPACE(sizeof(int)); byte *control = stackalloc byte[controlLength]; msghdr header = default(msghdr); header.msg_iov = &iov; header.msg_iovlen = 1; header.msg_control = control; header.msg_controllen = controlLength; int flags = MSG_NOSIGNAL | MSG_CMSG_CLOEXEC; ssize_t rv; do { rv = recvmsg(fromSocket, &header, flags); } while (rv < 0 && errno == EINTR); if (rv != -1) { 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; flags = fcntl(socket, F_GETFL, 0); if (blocking) { flags &= ~O_NONBLOCK; } else { flags |= O_NONBLOCK; } fcntl(socket, F_SETFL, flags); break; } } } return(PosixResult.FromReturnValue(rv)); }
private int receiveAndCheck(ref msghdr nextMsg) { var length = recvmsg(handle, ref nextMsg, 0); if (length == 0) { throw new OperationCanceledException("Socket was shut down"); } if (length < 0) { throw new InvalidOperationException("recvmsg failed with " + length); } return(length); }
public unsafe static PosixResult AcceptAndSendHandleTo(Socket fromSocket, int toSocket) { int acceptFd = fromSocket.DangerousGetHandle().ToInt32(); ssize_t rv; do { rv = accept4(acceptFd, null, null, SOCK_CLOEXEC); } while (rv < 0 && errno == EINTR); if (rv != -1) { int acceptedFd = (int)rv; byte dummyBuffer = 0; iovec iov = default(iovec); iov.iov_base = &dummyBuffer; iov.iov_len = 1; int controlLength = CMSG_SPACE(sizeof(int)); byte *control = stackalloc byte[controlLength]; msghdr header = default(msghdr); header.msg_iov = &iov; header.msg_iovlen = 1; header.msg_control = control; header.msg_controllen = controlLength; cmsghdr *cmsg = CMSG_FIRSTHDR(&header); cmsg->cmsg_level = SOL_SOCKET; cmsg->cmsg_type = SCM_RIGHTS; cmsg->cmsg_len = CMSG_LEN(sizeof(int)); int *fdptr = (int *)CMSG_DATA(cmsg); * fdptr = acceptedFd; do { rv = sendmsg(toSocket, &header, MSG_NOSIGNAL); } while (rv < 0 && errno == EINTR); IOInterop.Close(acceptedFd); } return(PosixResult.FromReturnValue(rv)); }
public static unsafe PosixResult Receive(int socket, iovec *ioVectors, int ioVectorLen) { msghdr hdr = default(msghdr); hdr.msg_iov = ioVectors; hdr.msg_iovlen = ioVectorLen; int flags = MSG_NOSIGNAL; ssize_t rv; do { rv = recvmsg(socket, &hdr, flags); } while (rv < 0 && errno == EINTR); return(PosixResult.FromReturnValue(rv)); }
public unsafe static PosixResult CompleteZeroCopy(int socket) { msghdr msg = default(msghdr); int controlLength = 100; byte * control = stackalloc byte[controlLength]; do { msg.msg_control = control; msg.msg_controllen = controlLength; ssize_t rv; do { rv = recvmsg(socket, &msg, MSG_NOSIGNAL | MSG_ERRQUEUE); } while (rv < 0 && errno == EINTR); if (rv == -1) { return(PosixResult.FromReturnValue(rv)); } cmsghdr *cm = CMSG_FIRSTHDR(&msg); if (cm == null) { continue; } if (!((cm->cmsg_level == SOL_IP && cm->cmsg_type == IP_RECVERR) || (cm->cmsg_level == SOL_IPV6 && cm->cmsg_type == IPV6_RECVERR))) { continue; } sock_extended_err *serr = (sock_extended_err *)CMSG_DATA(cm); if ((serr->ee_origin != SO_EE_ORIGIN_ZEROCOPY) || (serr->ee_errno != 0)) { continue; } return(new PosixResult(((serr->ee_code & SO_EE_CODE_ZEROCOPY_COPIED) != 0) ? ZeroCopyCopied : ZeroCopySuccess)); } while (true); }
public static extern unsafe size_t recvmsg(int sockfd, msghdr* msg, int flags);
// out public unsafe static int recvmsg(this SOCKET s, msghdr* msg, int flags) { return default(int); }
private static extern int recvmsg(SafeHandle sockfd, [In] ref msghdr buf, int flags);
private static extern unsafe nint sendmsg(SafeHandle sockfd, [In] ref msghdr buf, int flags);