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 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; }
public static SocketError Send(SafeCloseSocket handle, IList<ArraySegment<byte>> buffers, SocketFlags socketFlags, out int bytesTransferred) { var bufferList = new BufferList(buffers); int platformFlags = GetPlatformSocketFlags(socketFlags); if (!handle.IsNonBlocking) { return handle.AsyncContext.Send(bufferList, platformFlags, handle.SendTimeout, out bytesTransferred); } bytesTransferred = 0; int bufferIndex = 0; int offset = 0; SocketError errorCode; bool completed = TryCompleteSendTo(handle.FileDescriptor, bufferList, ref bufferIndex, ref offset, platformFlags, null, 0, ref bytesTransferred, out errorCode); return completed ? errorCode : SocketError.WouldBlock; }
public static bool TryCompleteSendTo(int fileDescriptor, byte[] buffer, BufferList buffers, ref int bufferIndex, ref int offset, ref int count, int flags, byte[] socketAddress, int socketAddressLen, ref int bytesSent, out SocketError errorCode) { for (;;) { int sent; Interop.Error errno; if (buffer != null) { sent = Send(fileDescriptor, flags, buffer, ref offset, ref count, socketAddress, socketAddressLen, out errno); } else { Debug.Assert(buffers.IsInitialized); sent = Send(fileDescriptor, flags, buffers, ref bufferIndex, ref offset, socketAddress, socketAddressLen, out errno); } if (sent == -1) { if (errno != Interop.Error.EAGAIN && errno != Interop.Error.EWOULDBLOCK) { errorCode = GetSocketErrorForErrorCode(errno); return true; } errorCode = SocketError.Success; return false; } bytesSent += sent; bool isComplete = sent == 0 || (buffer != null && count == 0) || (buffers.IsInitialized && bufferIndex == buffers.Count); if (isComplete) { errorCode = SocketError.Success; return true; } } }
public static bool TryCompleteSendTo(int fileDescriptor, BufferList buffers, ref int bufferIndex, ref int offset, int flags, byte[] socketAddress, int socketAddressLen, ref int bytesSent, out SocketError errorCode) { int count = 0; return TryCompleteSendTo(fileDescriptor, null, buffers, ref bufferIndex, ref offset, ref count, flags, socketAddress, socketAddressLen, ref bytesSent, out errorCode); }
public static unsafe bool TryCompleteReceiveFrom(int fileDescriptor, byte[] buffer, BufferList buffers, int offset, int count, int flags, byte[] socketAddress, ref int socketAddressLen, out int bytesReceived, out int receivedFlags, out SocketError errorCode) { int available; int err = Interop.libc.ioctl(fileDescriptor, (UIntPtr)Interop.libc.FIONREAD, &available); if (err == -1) { bytesReceived = 0; receivedFlags = 0; errorCode = GetLastSocketError(); return true; } if (available == 0) { // Always request at least one byte. available = 1; } int received; Interop.Error errno; if (buffer != null) { received = Receive(fileDescriptor, flags, available, buffer, offset, count, socketAddress, ref socketAddressLen, out receivedFlags, out errno); } else { Debug.Assert(buffers.IsInitialized); received = Receive(fileDescriptor, flags, available, buffers, socketAddress, ref socketAddressLen, out receivedFlags, out errno); } if (received != -1) { bytesReceived = received; errorCode = SocketError.Success; return true; } bytesReceived = 0; if (errno != Interop.Error.EAGAIN && errno != Interop.Error.EWOULDBLOCK) { errorCode = GetSocketErrorForErrorCode(errno); return true; } errorCode = SocketError.Success; return false; }