public IPEndPointStruct ToIPEndPoint(IPAddress reuseAddress = null) { if (Family == AddressFamily.InterNetwork) { long value; fixed(byte *address = Address) { value = ((address[3] << 24 | address[2] << 16 | address[1] << 8 | address[0]) & 0x0FFFFFFFF); } bool matchesReuseAddress = reuseAddress != null && reuseAddress.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork && reuseAddress.Address == value; return(new IPEndPointStruct(matchesReuseAddress ? reuseAddress : new IPAddress(value), Port)); } else if (Family == AddressFamily.InterNetworkV6) { // We can't check if we can use reuseAddress without allocating. const int length = 16; var bytes = new byte[length]; fixed(byte *address = Address) { for (int i = 0; i < length; i++) { bytes[i] = address[i]; } } return(new IPEndPointStruct(new IPAddress(bytes, ScopeId), Port)); } else { var result = new PosixResult(PosixResult.EAFNOSUPPORT); throw result.AsException(); } }
public IPEndPoint ToIPEndPoint() { if (Family == AddressFamily.InterNetwork) { long value; fixed(byte *address = Address) { value = ((address[3] << 24 | address[2] << 16 | address[1] << 8 | address[0]) & 0x0FFFFFFFF); } return(new IPEndPoint(new IPAddress(value), Port)); } else if (Family == AddressFamily.InterNetworkV6) { const int length = 16; var bytes = new byte[length]; fixed(byte *address = Address) { for (int i = 0; i < length; i++) { bytes[i] = address[i]; } } return(new IPEndPoint(new IPAddress(bytes, ScopeId), Port)); } else { var result = new PosixResult(PosixResult.EAFNOSUPPORT); throw result.AsException(); } }
public static unsafe PosixResult Accept(Socket socket, byte *socketAddress, int socketAddressLen, bool blocking, out Socket clientSocket) { int clientSocketFd; PosixResult result = Accept(socket.DangerousGetHandle().ToInt32(), socketAddress, socketAddressLen, blocking, out clientSocketFd); clientSocket = result.IsSuccess ? new Socket(clientSocketFd) : null; return(result); }
public static PosixResult Socket(AddressFamily addressFamily, SocketType socketType, ProtocolType protocolType, bool blocking, out Socket socket) { int socketFd; PosixResult result = Socket(addressFamily, socketType, protocolType, blocking, out socketFd); socket = result.IsSuccess ? new Socket(socketFd) : null; return(result); }
public static PosixResult ReceiveSocket(Socket fromSocket, out Socket socket, bool blocking) { int receiveSocketFd; PosixResult result = ReceiveSocket(fromSocket.DangerousGetHandle().ToInt32(), out receiveSocketFd, blocking); socket = result.IsSuccess ? new Socket(receiveSocketFd) : null; return(result); }
private unsafe void AioSend(List <ScheduledSend> sendQueue) { while (sendQueue.Count > 0) { int sendCount = 0; int completedCount = 0; AioCb * aioCbs = AioCbs; IOVector *ioVectors = IoVectorTable; ReadOnlySequence <byte>[] sendBuffers = _aioSendBuffers; Span <MemoryHandle> memoryHandles = MemoryHandles; int memoryHandleCount = 0; for (int i = 0; i < sendQueue.Count; i++) { TSocket socket = sendQueue[i].Socket; ReadOnlySequence <byte> buffer; Exception error = socket.GetReadResult(out buffer); if (error != null) { socket.CompleteOutput(error == TransportConstants.StopSentinel ? null : error); completedCount++; } else { int ioVectorLength = socket.CalcIOVectorLengthForSend(ref buffer, IoVectorsPerAioSocket); socket.FillSendIOVector(ref buffer, ioVectors, ioVectorLength, memoryHandles); memoryHandles = memoryHandles.Slice(ioVectorLength); memoryHandleCount += ioVectorLength; aioCbs->Fd = socket.Fd; aioCbs->Data = i; aioCbs->OpCode = AioOpCode.PWritev; aioCbs->Buffer = ioVectors; aioCbs->Length = ioVectorLength; aioCbs++; sendBuffers[sendCount] = buffer; sendCount++; if (sendCount == EventBufferLength) { break; } ioVectors += ioVectorLength; } } if (sendCount > 0) { IntPtr ctxp = _aioContext; PosixResult res = AioInterop.IoSubmit(ctxp, sendCount, AioCbsTable); memoryHandles = MemoryHandles; for (int i = 0; i < memoryHandleCount; i++) { memoryHandles[i].Dispose(); } if (res != sendCount) { throw new NotSupportedException("Unexpected IoSubmit Send retval " + res); } AioEvent *aioEvents = AioEvents; res = AioInterop.IoGetEvents(ctxp, sendCount, aioEvents); if (res != sendCount) { throw new NotSupportedException("Unexpected IoGetEvents Send retval " + res); } AioEvent *aioEvent = aioEvents; for (int i = 0; i < sendCount; i++) { PosixResult result = aioEvent->Result; int socketIndex = (int)aioEvent->Data; TSocket socket = sendQueue[socketIndex].Socket; ReadOnlySequence <byte> buffer = sendBuffers[i]; // assumes in-order events sendBuffers[i] = default; socket.HandleSendResult(ref buffer, result, loop: false, zerocopy: false, zeroCopyRegistered: false); aioEvent++; } } sendQueue.RemoveRange(0, sendCount + completedCount); } }
private unsafe void AioReceive(List <TSocket> readableSockets) { long PackReceiveState(int received, int advanced, int iovLength) => ((long)received << 32) + (advanced << 8) + (iovLength); (int received, int advanced, int iovLength) UnpackReceiveState(long data) => ((int)(data >> 32), (int)((data >> 8) & 0xffffff), (int)(data & 0xff)); int readableSocketCount = readableSockets.Count; AioCb * aioCb = AioCbs; IOVector * ioVectors = IoVectorTable; PosixResult * receiveResults = stackalloc PosixResult[readableSocketCount]; bool checkAvailable = _transportOptions.CheckAvailable; Span <MemoryHandle> receiveMemoryHandles = MemoryHandles; int receiveMemoryHandleCount = 0; for (int i = 0; i < readableSocketCount; i++) { TSocket socket = readableSockets[i]; int availableBytes = !checkAvailable ? 0 : socket.GetAvailableBytes(); int ioVectorLength = socket.CalcIOVectorLengthForReceive(availableBytes, IoVectorsPerAioSocket); int advanced = socket.FillReceiveIOVector(availableBytes, ioVectors, receiveMemoryHandles, ref ioVectorLength); aioCb->Fd = socket.Fd; aioCb->Data = PackReceiveState(0, advanced, ioVectorLength); aioCb->OpCode = AioOpCode.PReadv; aioCb->Buffer = ioVectors; aioCb->Length = ioVectorLength; aioCb++; ioVectors += ioVectorLength; receiveMemoryHandleCount += ioVectorLength; receiveMemoryHandles = receiveMemoryHandles.Slice(ioVectorLength); } int eAgainCount = 0; while (readableSocketCount > 0) { IntPtr ctxp = _aioContext; PosixResult res = AioInterop.IoSubmit(ctxp, readableSocketCount, AioCbsTable); if (res != readableSocketCount) { throw new NotSupportedException("Unexpected IoSubmit retval " + res); } AioEvent *aioEvents = AioEvents; res = AioInterop.IoGetEvents(ctxp, readableSocketCount, aioEvents); if (res != readableSocketCount) { throw new NotSupportedException("Unexpected IoGetEvents retval " + res); } int socketsRemaining = readableSocketCount; bool allEAgain = true; AioEvent *aioEvent = aioEvents; for (int i = 0; i < readableSocketCount; i++) { PosixResult result = aioEvent->Result; int socketIndex = i; // assumes in-order events TSocket socket = readableSockets[socketIndex]; (int received, int advanced, int iovLength) = UnpackReceiveState(aioEvent->Data); (bool done, PosixResult retval) = socket.InterpretReceiveResult(result, ref received, advanced, (IOVector *)aioEvent->AioCb->Buffer, iovLength); if (done) { receiveResults[socketIndex] = retval; socketsRemaining--; aioEvent->AioCb->OpCode = AioOpCode.Noop; allEAgain = false; } else if (retval != PosixResult.EAGAIN) { aioEvent->AioCb->Data = PackReceiveState(received, advanced, iovLength); allEAgain = false; } aioEvent++; } if (socketsRemaining > 0) { if (allEAgain) { eAgainCount++; if (eAgainCount == TransportConstants.MaxEAgainCount) { throw new NotSupportedException("Too many EAGAIN, unable to receive available bytes."); } } else { aioCb = AioCbs; AioCb *aioCbWriteAt = aioCb; // The kernel doesn't handle Noop, we need to remove them from the aioCbs for (int i = 0; i < readableSocketCount; i++) { if (aioCb[i].OpCode != AioOpCode.Noop) { if (aioCbWriteAt != aioCb) { *aioCbWriteAt = *aioCb; } aioCbWriteAt++; } aioCb++; } readableSocketCount = socketsRemaining; eAgainCount = 0; } } else { readableSocketCount = 0; } } for (int i = 0; i < readableSockets.Count; i++) { readableSockets[i].OnReceiveFromSocket(receiveResults[i]); } readableSockets.Clear(); receiveMemoryHandles = MemoryHandles; for (int i = 0; i < receiveMemoryHandleCount; i++) { receiveMemoryHandles[i].Dispose(); } }