Пример #1
0
        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);
                }
            }
        }
Пример #2
0
        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());
            }
        }
Пример #3
0
        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);
            }
        }
Пример #4
0
        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));
        }
Пример #5
0
        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);
        }
Пример #6
0
        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));
        }
Пример #7
0
        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));
        }
Пример #8
0
        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);
        }
Пример #9
0
 public static extern unsafe size_t recvmsg(int sockfd, msghdr* msg, int flags);
Пример #10
0
 // out
 public unsafe static int recvmsg(this SOCKET s, msghdr* msg, int flags) { return default(int); }
Пример #11
0
 private static extern int recvmsg(SafeHandle sockfd, [In] ref msghdr buf, int flags);
Пример #12
0
 private static extern unsafe nint sendmsg(SafeHandle sockfd, [In] ref msghdr buf, int flags);