private static unsafe int ReceiveMessageFrom(int fd, int flags, int available, byte[] buffer, int offset, int count, byte[] socketAddress, ref int socketAddressLen, bool isIPv4, bool isIPv6, out int receivedFlags, out IPPacketInformation ipPacketInformation, out Interop.Error errno) { Debug.Assert(socketAddress != null); int cmsgBufferLen = (isIPv4 ? AlignControlMessageSize(sizeof(Interop.libc.cmsghdr) + sizeof(Interop.libc.in_pktinfo)) : 0) + (isIPv6 ? AlignControlMessageSize(sizeof(Interop.libc.cmsghdr) + sizeof(Interop.libc.in6_pktinfo)) : 0); var cmsgBuffer = stackalloc byte[cmsgBufferLen]; var sockAddrLen = (uint)socketAddressLen; int received; fixed (byte* rawSocketAddress = socketAddress) fixed (byte* b = buffer) { var sockAddr = (Interop.libc.sockaddr*)rawSocketAddress; var iov = new Interop.libc.iovec { iov_base = &b[offset], iov_len = (IntPtr)count }; var msghdr = new Interop.libc.msghdr(sockAddr, sockAddrLen, &iov, 1, cmsgBuffer, cmsgBufferLen, 0); received = (int)Interop.libc.recvmsg(fd, &msghdr, flags); receivedFlags = msghdr.msg_flags; sockAddrLen = msghdr.msg_namelen; cmsgBufferLen = (int)msghdr.msg_controllen; } ipPacketInformation = GetIPPacketInformation(cmsgBuffer, cmsgBufferLen, isIPv4, isIPv6); if (received == -1) { errno = Interop.Sys.GetLastError(); return -1; } socketAddressLen = (int)sockAddrLen; errno = Interop.Error.SUCCESS; return received; }
private static unsafe int Send(int fd, int flags, BufferList 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); Interop.libc.sockaddr* sockAddr = null; uint sockAddrLen = 0; int maxBuffers = buffers.Count - startIndex; var handles = new GCHandle[maxBuffers]; var iovecs = new Interop.libc.iovec[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].iov_base = &((byte*)handles[i].AddrOfPinnedObject())[buffer.Offset + startOffset]; toSend += (buffer.Count - startOffset); iovecs[i].iov_len = (IntPtr)(buffer.Count - startOffset); } if (socketAddress != null) { pinnedSocketAddress = GCHandle.Alloc(socketAddress, GCHandleType.Pinned); sockAddr = (Interop.libc.sockaddr*)pinnedSocketAddress.AddrOfPinnedObject(); sockAddrLen = (uint)socketAddressLen; } // Make the call fixed (Interop.libc.iovec* iov = iovecs) { var msghdr = new Interop.libc.msghdr(sockAddr, sockAddrLen, iov, iovCount, null, 0, 0); sent = (int)Interop.libc.sendmsg(fd, &msghdr, flags); } errno = Interop.Sys.GetLastError(); } finally { // Free GC handles. for (int i = 0; i < iovCount; i++) { if (handles[i].IsAllocated) { handles[i].Free(); } } if (pinnedSocketAddress.IsAllocated) { pinnedSocketAddress.Free(); } } if (sent == -1) { 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; }
private static unsafe int Receive(int fd, int flags, int available, BufferList buffers, byte[] socketAddress, ref int socketAddressLen, out int receivedFlags, out Interop.Error errno) { // Pin buffers and set up iovecs. int maxBuffers = buffers.Count; var handles = new GCHandle[maxBuffers]; var iovecs = new Interop.libc.iovec[maxBuffers]; var pinnedSocketAddress = default(GCHandle); Interop.libc.sockaddr* sockAddr = null; uint sockAddrLen = 0; int 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].iov_base = &((byte*)handles[i].AddrOfPinnedObject())[buffer.Offset]; int space = buffer.Count; toReceive += space; if (toReceive >= available) { iovecs[i].iov_len = (IntPtr)(space - (toReceive - available)); toReceive = available; iovCount = i + 1; break; } iovecs[i].iov_len = (IntPtr)space; } if (socketAddress != null) { pinnedSocketAddress = GCHandle.Alloc(socketAddress, GCHandleType.Pinned); sockAddr = (Interop.libc.sockaddr*)pinnedSocketAddress.AddrOfPinnedObject(); sockAddrLen = (uint)socketAddressLen; } // Make the call. fixed (Interop.libc.iovec* iov = iovecs) { var msghdr = new Interop.libc.msghdr(sockAddr, sockAddrLen, iov, iovCount, null, 0, 0); received = (int)Interop.libc.recvmsg(fd, &msghdr, flags); receivedFlags = msghdr.msg_flags; sockAddrLen = msghdr.msg_namelen; } } finally { // Free GC handles. for (int i = 0; i < iovCount; i++) { if (handles[i].IsAllocated) { handles[i].Free(); } } if (pinnedSocketAddress.IsAllocated) { pinnedSocketAddress.Free(); } } if (received == -1) { errno = Interop.Sys.GetLastError(); return -1; } socketAddressLen = (int)sockAddrLen; errno = Interop.Error.SUCCESS; return received; }
private static unsafe int Receive(int fd, int flags, int available, byte[] buffer, int offset, int count, byte[] socketAddress, ref int socketAddressLen, out int receivedFlags, out Interop.Error errno) { Debug.Assert(socketAddress != null || socketAddressLen == 0); var pinnedSocketAddress = default(GCHandle); Interop.libc.sockaddr* sockAddr = null; uint sockAddrLen = 0; int received; try { if (socketAddress != null) { pinnedSocketAddress = GCHandle.Alloc(socketAddress, GCHandleType.Pinned); sockAddr = (Interop.libc.sockaddr*)pinnedSocketAddress.AddrOfPinnedObject(); sockAddrLen = (uint)socketAddressLen; } fixed (byte* b = buffer) { var iov = new Interop.libc.iovec { iov_base = &b[offset], iov_len = (IntPtr)count }; var msghdr = new Interop.libc.msghdr(sockAddr, sockAddrLen, &iov, 1, null, 0, 0); received = (int)Interop.libc.recvmsg(fd, &msghdr, flags); receivedFlags = msghdr.msg_flags; sockAddrLen = msghdr.msg_namelen; } } finally { if (pinnedSocketAddress.IsAllocated) { pinnedSocketAddress.Free(); } } if (received == -1) { errno = Interop.Sys.GetLastError(); return -1; } socketAddressLen = (int)sockAddrLen; errno = Interop.Error.SUCCESS; return received; }