internal static unsafe long ReadScatterAtOffset(SafeFileHandle handle, IReadOnlyList <Memory <byte> > buffers, long fileOffset)
        {
            MemoryHandle[] handles = new MemoryHandle[buffers.Count];
            Span <Interop.Sys.IOVector> vectors = buffers.Count <= IovStackThreshold ? stackalloc Interop.Sys.IOVector[IovStackThreshold] : new Interop.Sys.IOVector[buffers.Count];

            long result;

            try
            {
                int buffersCount = buffers.Count;
                for (int i = 0; i < buffersCount; i++)
                {
                    Memory <byte> buffer       = buffers[i];
                    MemoryHandle  memoryHandle = buffer.Pin();
                    vectors[i] = new Interop.Sys.IOVector {
                        Base = (byte *)memoryHandle.Pointer, Count = (UIntPtr)buffer.Length
                    };
                    handles[i] = memoryHandle;
                }

                fixed(Interop.Sys.IOVector *pinnedVectors = &MemoryMarshal.GetReference(vectors))
                {
                    result = Interop.Sys.PReadV(handle, pinnedVectors, buffers.Count, fileOffset);
                }
            }
            finally
            {
                foreach (MemoryHandle memoryHandle in handles)
                {
                    memoryHandle.Dispose();
                }
            }

            return(FileStreamHelpers.CheckFileCall(result, handle.Path));
        }
Exemple #2
0
        private static unsafe int Receive(SafeCloseSocket socket, SocketFlags flags, byte[] buffer, int offset, int count, byte[] socketAddress, ref int socketAddressLen, out SocketFlags receivedFlags, out Interop.Error errno)
        {
            Debug.Assert(socketAddress != null || socketAddressLen == 0, $"Unexpected values: socketAddress={socketAddress}, socketAddressLen={socketAddressLen}");

            long received;

            int sockAddrLen = 0;
            if (socketAddress != null)
            {
                sockAddrLen = socketAddressLen;
            }

            fixed (byte* sockAddr = socketAddress)
            fixed (byte* b = buffer)
            {
                var iov = new Interop.Sys.IOVector {
                    Base = (b == null) ? null : &b[offset],
                    Count = (UIntPtr)count
                };

                var messageHeader = new Interop.Sys.MessageHeader {
                    SocketAddress = sockAddr,
                    SocketAddressLen = sockAddrLen,
                    IOVectors = &iov,
                    IOVectorCount = 1
                };

                errno = Interop.Sys.ReceiveMessage(socket, &messageHeader, flags, &received);
                receivedFlags = messageHeader.Flags;
                sockAddrLen = messageHeader.SocketAddressLen;
            }

            if (errno != Interop.Error.SUCCESS)
            {
                return -1;
            }

            socketAddressLen = sockAddrLen;
            return checked((int)received);
        }
Exemple #3
0
        private static unsafe int ReceiveMessageFrom(int fd, SocketFlags flags, int available, byte[] buffer, int offset, int count, byte[] socketAddress, ref int socketAddressLen, bool isIPv4, bool isIPv6, out SocketFlags receivedFlags, out IPPacketInformation ipPacketInformation, out Interop.Error errno)
        {
            Debug.Assert(socketAddress != null);

            int cmsgBufferLen = Interop.Sys.GetControlMessageBufferSize(isIPv4, isIPv6);
            var cmsgBuffer = stackalloc byte[cmsgBufferLen];

            int sockAddrLen = socketAddressLen;

            Interop.Sys.MessageHeader messageHeader;

            long received;
            fixed (byte* rawSocketAddress = socketAddress)
            fixed (byte* b = buffer)
            {
                var sockAddr = (byte*)rawSocketAddress;

                var iov = new Interop.Sys.IOVector {
                    Base = &b[offset],
                    Count = (UIntPtr)count
                };

                messageHeader = new Interop.Sys.MessageHeader {
                    SocketAddress = sockAddr,
                    SocketAddressLen = sockAddrLen,
                    IOVectors = &iov,
                    IOVectorCount = 1,
                    ControlBuffer = cmsgBuffer,
                    ControlBufferLen = cmsgBufferLen
                };

                errno = Interop.Sys.ReceiveMessage(fd, &messageHeader, flags, &received);
                receivedFlags = messageHeader.Flags;
                sockAddrLen = messageHeader.SocketAddressLen;
            }

            ipPacketInformation = GetIPPacketInformation(&messageHeader, isIPv4, isIPv6);

            if (errno != Interop.Error.SUCCESS)
            {
                return -1;
            }

            socketAddressLen = sockAddrLen;
            return checked((int)received);
        }
Exemple #4
0
        private static unsafe int Receive(int fd, SocketFlags flags, int available, IList<ArraySegment<byte>> buffers, byte[] socketAddress, ref int socketAddressLen, out SocketFlags receivedFlags, out Interop.Error errno)
        {
            // Pin buffers and set up iovecs.
            int maxBuffers = buffers.Count;
            var handles = new GCHandle[maxBuffers];
            var iovecs = new Interop.Sys.IOVector[maxBuffers];

            var pinnedSocketAddress = default(GCHandle);
            byte* sockAddr = null;
            int sockAddrLen = 0;

            long received = 0;
            int toReceive = 0, iovCount = maxBuffers;
            try
            {
                for (int i = 0; i < maxBuffers; i++)
                {
                    ArraySegment<byte> buffer = buffers[i];
                    handles[i] = GCHandle.Alloc(buffer.Array, GCHandleType.Pinned);
                    iovecs[i].Base = &((byte*)handles[i].AddrOfPinnedObject())[buffer.Offset];

                    int space = buffer.Count;
                    toReceive += space;
                    if (toReceive >= available)
                    {
                        iovecs[i].Count = (UIntPtr)(space - (toReceive - available));
                        toReceive = available;
                        iovCount = i + 1;
                        break;
                    }

                    iovecs[i].Count = (UIntPtr)space;
                }

                if (socketAddress != null)
                {
                    pinnedSocketAddress = GCHandle.Alloc(socketAddress, GCHandleType.Pinned);
                    sockAddr = (byte*)pinnedSocketAddress.AddrOfPinnedObject();
                    sockAddrLen = socketAddressLen;
                }

                // Make the call.
                fixed (Interop.Sys.IOVector* iov = iovecs)
                {
                    var messageHeader = new Interop.Sys.MessageHeader {
                        SocketAddress = sockAddr,
                        SocketAddressLen = sockAddrLen,
                        IOVectors = iov,
                        IOVectorCount = iovCount
                    };

                    errno = Interop.Sys.ReceiveMessage(fd, &messageHeader, flags, &received);
                    receivedFlags = messageHeader.Flags;
                    sockAddrLen = messageHeader.SocketAddressLen;
                }
            }
            finally
            {
                // Free GC handles.
                for (int i = 0; i < iovCount; i++)
                {
                    if (handles[i].IsAllocated)
                    {
                        handles[i].Free();
                    }
                }

                if (pinnedSocketAddress.IsAllocated)
                {
                    pinnedSocketAddress.Free();
                }
            }

            if (errno != Interop.Error.SUCCESS)
            {
                return -1;
            }

            socketAddressLen = sockAddrLen;
            return checked((int)received);
        }
Exemple #5
0
        private static unsafe int Send(int fd, SocketFlags flags, IList<ArraySegment<byte>> buffers, ref int bufferIndex, ref int offset, byte[] socketAddress, int socketAddressLen, out Interop.Error errno)
        {
            // Pin buffers and set up iovecs.
            int startIndex = bufferIndex, startOffset = offset;

            var pinnedSocketAddress = default(GCHandle);
            byte* sockAddr = null;
            int sockAddrLen = 0;

            int maxBuffers = buffers.Count - startIndex;
            var handles = new GCHandle[maxBuffers];
            var iovecs = new Interop.Sys.IOVector[maxBuffers];

            int sent;
            int toSend = 0, iovCount = maxBuffers;
            try
            {
                for (int i = 0; i < maxBuffers; i++, startOffset = 0)
                {
                    ArraySegment<byte> buffer = buffers[startIndex + i];
                    Debug.Assert(buffer.Offset + startOffset < buffer.Array.Length);

                    handles[i] = GCHandle.Alloc(buffer.Array, GCHandleType.Pinned);
                    iovecs[i].Base = &((byte*)handles[i].AddrOfPinnedObject())[buffer.Offset + startOffset];

                    toSend += (buffer.Count - startOffset);
                    iovecs[i].Count = (UIntPtr)(buffer.Count - startOffset);
                }

                if (socketAddress != null)
                {
                    pinnedSocketAddress = GCHandle.Alloc(socketAddress, GCHandleType.Pinned);
                    sockAddr = (byte*)pinnedSocketAddress.AddrOfPinnedObject();
                    sockAddrLen = socketAddressLen;
                }

                // Make the call
                fixed (Interop.Sys.IOVector* iov = iovecs)
                {
                    var messageHeader = new Interop.Sys.MessageHeader {
                        SocketAddress = sockAddr,
                        SocketAddressLen = sockAddrLen,
                        IOVectors = iov,
                        IOVectorCount = iovCount
                    };

                    long bytesSent;
                    errno = Interop.Sys.SendMessage(fd, &messageHeader, flags, &bytesSent);

                    sent = checked((int)bytesSent);
                }
            }
            finally
            {
                // Free GC handles.
                for (int i = 0; i < iovCount; i++)
                {
                    if (handles[i].IsAllocated)
                    {
                        handles[i].Free();
                    }
                }

                if (pinnedSocketAddress.IsAllocated)
                {
                    pinnedSocketAddress.Free();
                }
            }

            if (errno != Interop.Error.SUCCESS)
            {
                return -1;
            }

            // Update position.
            int endIndex = bufferIndex, endOffset = offset, unconsumed = sent;
            for (; endIndex < buffers.Count && unconsumed > 0; endIndex++, endOffset = 0)
            {
                int space = buffers[endIndex].Count - endOffset;
                if (space > unconsumed)
                {
                    endOffset += unconsumed;
                    break;
                }
                unconsumed -= space;
            }

            bufferIndex = endIndex;
            offset = endOffset;

            return sent;
        }
Exemple #6
0
        private static unsafe int Send(int fd, SocketFlags flags, byte[] buffer, ref int offset, ref int count, byte[] socketAddress, int socketAddressLen, out Interop.Error errno)
        {
            var pinnedSocketAddress = default(GCHandle);
            byte* sockAddr = null;
            int sockAddrLen = 0;

            int sent;
            try
            {
                if (socketAddress != null)
                {
                    pinnedSocketAddress = GCHandle.Alloc(socketAddress, GCHandleType.Pinned);
                    sockAddr = (byte*)pinnedSocketAddress.AddrOfPinnedObject();
                    sockAddrLen = socketAddressLen;
                }

                fixed (byte* b = buffer)
                {
                    var iov = new Interop.Sys.IOVector {
                        Base = &b[offset],
                        Count = (UIntPtr)count
                    };

                    var messageHeader = new Interop.Sys.MessageHeader {
                        SocketAddress = sockAddr,
                        SocketAddressLen = sockAddrLen,
                        IOVectors = &iov,
                        IOVectorCount = 1
                    };

                    long bytesSent;
                    errno = Interop.Sys.SendMessage(fd, &messageHeader, flags, &bytesSent);

                    sent = checked((int)bytesSent);
                }
            }
            finally
            {
                if (pinnedSocketAddress.IsAllocated)
                {
                    pinnedSocketAddress.Free();
                }
            }

            if (errno != Interop.Error.SUCCESS)
            {
                return -1;
            }

            
            offset += sent;
            count -= sent;
            return sent;
        }
Exemple #7
0
        private static unsafe int Receive(int fd, SocketFlags flags, int available, byte[] buffer, int offset, int count, byte[] socketAddress, ref int socketAddressLen, out SocketFlags receivedFlags, out Interop.Error errno)
        {
            Debug.Assert(socketAddress != null || socketAddressLen == 0);

            var pinnedSocketAddress = default(GCHandle);
            byte* sockAddr = null;
            int sockAddrLen = 0;

            long received;
            try
            {
                if (socketAddress != null)
                {
                    pinnedSocketAddress = GCHandle.Alloc(socketAddress, GCHandleType.Pinned);
                    sockAddr = (byte*)pinnedSocketAddress.AddrOfPinnedObject();
                    sockAddrLen = socketAddressLen;
                }

                fixed (byte* b = buffer)
                {
                    var iov = new Interop.Sys.IOVector {
                        Base = &b[offset],
                        Count = (UIntPtr)count
                    };

                    var messageHeader = new Interop.Sys.MessageHeader {
                        SocketAddress = sockAddr,
                        SocketAddressLen = sockAddrLen,
                        IOVectors = &iov,
                        IOVectorCount = 1
                    };

                    errno = Interop.Sys.ReceiveMessage(fd, &messageHeader, flags, &received);
                    receivedFlags = messageHeader.Flags;
                    sockAddrLen = messageHeader.SocketAddressLen;
                }
            }
            finally
            {
                if (pinnedSocketAddress.IsAllocated)
                {
                    pinnedSocketAddress.Free();
                }
            }

            if (errno != Interop.Error.SUCCESS)
            {
                return -1;
            }

            socketAddressLen = sockAddrLen;
            return checked((int)received);
        }
        private static unsafe int Send(int fd, SocketFlags flags, byte[] buffer, ref int offset, ref int count, byte[] socketAddress, int socketAddressLen, out Interop.Error errno)
        {
            int sent;

            int sockAddrLen = 0;
            if (socketAddress != null)
            {
                sockAddrLen = socketAddressLen;
            }

            fixed (byte* sockAddr = socketAddress)
            fixed (byte* b = buffer)
            {
                var iov = new Interop.Sys.IOVector {
                    Base = &b[offset],
                    Count = (UIntPtr)count
                };

                var messageHeader = new Interop.Sys.MessageHeader {
                    SocketAddress = sockAddr,
                    SocketAddressLen = sockAddrLen,
                    IOVectors = &iov,
                    IOVectorCount = 1
                };

                long bytesSent;
                errno = Interop.Sys.SendMessage(fd, &messageHeader, flags, &bytesSent);

                sent = checked((int)bytesSent);
            }

            if (errno != Interop.Error.SUCCESS)
            {
                return -1;
            }

            
            offset += sent;
            count -= sent;
            return sent;
        }
        internal static unsafe void WriteGatherAtOffset(SafeFileHandle handle, IReadOnlyList <ReadOnlyMemory <byte> > buffers, long fileOffset)
        {
            int buffersCount = buffers.Count;

            if (buffersCount == 0)
            {
                return;
            }

            var handles = new MemoryHandle[buffersCount];
            Span <Interop.Sys.IOVector> vectors = buffersCount <= IovStackThreshold ?
                                                  stackalloc Interop.Sys.IOVector[IovStackThreshold] :
                                                  new Interop.Sys.IOVector[buffersCount];

            try
            {
                int buffersOffset = 0, firstBufferOffset = 0;
                while (true)
                {
                    long totalBytesToWrite = 0;

                    for (int i = buffersOffset; i < buffersCount; i++)
                    {
                        ReadOnlyMemory <byte> buffer = buffers[i];
                        totalBytesToWrite += buffer.Length;

                        MemoryHandle memoryHandle = buffer.Pin();
                        vectors[i] = new Interop.Sys.IOVector {
                            Base = firstBufferOffset + (byte *)memoryHandle.Pointer, Count = (UIntPtr)buffer.Length
                        };
                        handles[i] = memoryHandle;

                        firstBufferOffset = 0;
                    }

                    if (totalBytesToWrite == 0)
                    {
                        break;
                    }

                    long bytesWritten;
                    fixed(Interop.Sys.IOVector *pinnedVectors = &MemoryMarshal.GetReference(vectors))
                    {
                        bytesWritten = Interop.Sys.PWriteV(handle, pinnedVectors, buffersCount, fileOffset);
                    }

                    FileStreamHelpers.CheckFileCall(bytesWritten, handle.Path);
                    if (bytesWritten == totalBytesToWrite)
                    {
                        break;
                    }

                    // The write completed successfully but for fewer bytes than requested.
                    // We need to try again for the remainder.
                    for (int i = 0; i < buffersCount; i++)
                    {
                        int n = buffers[i].Length;
                        if (n <= bytesWritten)
                        {
                            buffersOffset++;
                            bytesWritten -= n;
                            if (bytesWritten == 0)
                            {
                                break;
                            }
                        }
                        else
                        {
                            firstBufferOffset = (int)(bytesWritten - n);
                            break;
                        }
                    }
                }
            }
            finally
            {
                foreach (MemoryHandle memoryHandle in handles)
                {
                    memoryHandle.Dispose();
                }
            }
        }